HM1_Aufgabenserie8/Schenk_Brandenberger_S8_Auf...

120 lines
3.5 KiB
Python
Raw Normal View History

2022-11-18 09:38:00 +01:00
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 7 13:26:09 2020
Höhere Mathematik 1, Serie 8, Gerüst für Aufgabe 2
Description: calculates the QR factorization of A so that A = QR
Input Parameters: A: array, n*n matrix
Output Parameters: Q : n*n orthogonal matrix
R : n*n upper right triangular matrix
Remarks: none
Example: A = np.array([[1,2,-1],[4,-2,6],[3,1,0]])
[Q,R]=Serie8_Aufg2(A)
@author: knaa
"""
2022-11-18 19:34:54 +01:00
import numpy as np
2022-11-19 01:41:07 +01:00
import timeit
2022-11-18 09:38:00 +01:00
2022-11-19 01:41:07 +01:00
# Aufgabe 2a
2022-11-18 09:38:00 +01:00
def Serie8_Aufg2(A):
A = np.copy(A) #necessary to prevent changes in the original matrix A_in
A = A.astype('float64') #change to float
n = np.shape(A)[0]
if n != np.shape(A)[1]:
raise Exception('Matrix is not square')
Q = np.eye(n)
R = A
2022-11-18 19:34:54 +01:00
2022-11-18 09:38:00 +01:00
for j in np.arange(0,n-1):
2022-11-18 22:01:05 +01:00
# erzeuge Nullen in R in der j-ten Spalte unterhalb der Diagonalen:
#a = (Q @ A)[j:,j:][:,0]
a = np.copy((Q @ A)[j:,j:][:,0]).reshape(n-j,1)
e = np.eye(n-j)[:,0].reshape(n-j,1)
2022-11-18 09:38:00 +01:00
length_a = np.linalg.norm(a)
2022-11-18 22:01:05 +01:00
if a[0] >= 0: sig = 1
else: sig = -1
v = a + sig * length_a * e # vj := aj + sign(a1j) · |aj| · ej
u = 1 / np.linalg.norm(v) * v # uj := 1/|vj|*vj
ut = u.T
ua = u @ ut
ub = 2 * ua
x = np.eye(n)
H = np.eye(n-j) - (2 * (u @ u.T)) # Hj := In 2u1u1T bestimme die (n j + 1) × (n j + 1) Householder-Matrix Hj
Qj = np.eye(n)
Qj[j:,j:] = H # erweitere Hi durch einen Ii1 Block links oben zur n × n Matrix Qi
R = Qj @ R # R := Qj · R
Q = Q @ Qj.T # Q := Q · QjT
2022-11-18 09:38:00 +01:00
return(Q,R)
2022-11-18 19:34:54 +01:00
if __name__ == '__main__':
2022-11-19 01:41:07 +01:00
# Beispiel aus Skript
2022-11-19 01:32:45 +01:00
# A = np.array([[1, 2, -1], [4, -2, 6], [3, 1, 0]])
2022-11-18 22:01:05 +01:00
# b = np.array([
# [9],
2022-11-19 01:32:45 +01:00
# [-4],
# [9]
2022-11-18 22:01:05 +01:00
# ])
2022-11-19 01:41:07 +01:00
# Beispiel aus Aufgabe 1
2022-11-19 01:32:45 +01:00
A = np.array([
[1, -2, 3],
[-5, 4, 1],
[2, -1, 3]
])
b = np.array([
[1],
[9],
[5]
])
2022-11-18 22:01:05 +01:00
[Q,R]=Serie8_Aufg2(A)
2022-11-19 01:32:45 +01:00
2022-11-19 01:41:07 +01:00
# Aufgabe 2b
2022-11-19 01:32:45 +01:00
n = len(b) - 1
QTb = Q.T @ b
result = [0 for i in range(n+1)]
row = n
while row >= 0:
value = QTb[row][0]
column = n
while column > row:
value -= R[row][column] * result[column]
column -= 1
value = value / R[row,row]
result[row] = value
row -= 1
2022-11-18 22:01:05 +01:00
print("\nQ:\n", Q)
2022-11-19 01:32:45 +01:00
print("\nR:\n", R)
2022-11-19 01:41:07 +01:00
print("\Result:\n", result)
# Aufgabe 2c
t1 = timeit.repeat("Serie8_Aufg2(A)", "from __main__ import Serie8_Aufg2, A", number=100)
t2 = timeit.repeat("np.linalg.qr(A)", "from __main__ import np, A", number=100)
avg_t1 = np.average(t1) / 100
avg_t2 = np.average(t2) / 100
print("Geschwindigkeit mit 3x3 Matrix:")
print("Benötigte Zeit mit eigener Funktion:", avg_t1)
print("Benötigte Zeit mit Numpy:", avg_t2)
# Aufgabe 2d
Test = np.random.rand(100,100)
t1 = timeit.repeat("Serie8_Aufg2(Test)", "from __main__ import Serie8_Aufg2, Test", number=100)
t2 = timeit.repeat("np.linalg.qr(Test)", "from __main__ import np, Test", number=100)
avg_t1 = np.average(t1) / 100
avg_t2 = np.average(t2) / 100
print("Geschwindigkeit mit 100x100 Matrix:")
print("Benötigte Zeit mit eigener Funktion:", avg_t1)
print("Benötigte Zeit mit Numpy:", avg_t2)
# Die von Numpy zur Verfügung gestellt Funktion ist wesentlich effizienter.