-
Notifications
You must be signed in to change notification settings - Fork 0
/
Decompositions.py
128 lines (82 loc) · 1.9 KB
/
Decompositions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import numpy as np
'''
below is an implmentation of the Householder_reflection tranformation
it takes the input vector a and return the tranformation H that would take a to
its mirror image point e
'''
def householder_reflection(a,e):
'''
return a orthogonal matrix that maps a onto e
'''
'''
u is the vector joining a and its reflection on e
u=a-||a||e
'''
u=a-np.sign(a[0])*np.linalg.norm(a)*e
'''
v is the normalization of u
'''
v=u/np.linalg.norm(u)
'''
H is the final householder matrix tranformation
Hx=x-2<x,v>v
=x-2v<x,v>
=x-2v(v.T*x)
=x-2(v*v.T)x
=[I-2(v*v.T)]x
hence H=I-2(v*v.T)x
'''
H=np.eye(len(a))-2*np.outer(v,v)
return H
'''
Below is the function for QR decomposition
It takes a matrix A and return Q and R where Q is orthogonal and R is a upper triangular
matrix and
QR=A
'''
def QR_decomposition(A):
N,M=A.shape
'''
initialise Q as a Identity matrix and R as a upper triangular matrix
'''
Q=np.eye(N)
R=A.copy()
'''
iteratively covert R and Q into the desired form while still maintaining
their original structure
'''
for i in range(M-int(N==M)):
r=R[i:,i]
'''
if its already in unit form
'''
if np.allclose(r[1:],0):
continue
'''
e is our ouput basis vector of the form (1,0,...,0)
'''
e=np.zeros(N-i)
e[0]=1
'''
H is the Householder_reflection matrix we would get from r and e
'''
H=np.eye(N)
H[i:,i:]=householder_reflection(r,e)
Q=Q @ H.T
R=H @ R
return Q,R
# Solve Ax=B using Back-substitution method where A is a upper triangular matrix
# there is also a scipy library function calles scipy.linalg.solve_triangular() which
# does the same thing bit faster
def solve_equation(A,b):
N,M = A.shape
'''
last x is just A[n,n]*x=B[n]
'''
x=b[(M-1):M] / A[M-1,M-1]
for i in range(M-2,-1,-1):
back=np.dot(A[i,(i+1):],x)
rhs=b[i]-back
x_i=rhs/A[i,i]
x=np.insert(x,0,x_i)
return x