-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreducedSVD.py
36 lines (34 loc) · 1.74 KB
/
reducedSVD.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
from numpy import *
from numpy.linalg import *
from math import sqrt
def svd(D): # Taking the input matrix
A = array(D) # Assuring the matrix is in the array form
At = transpose(A)
M = At @ A
Eval, Evec = eig(M)
for i in range(len(Eval)): # Ordering the singular values in an ascending
for j in range(i + 1, len(Eval)): # \\ manner, preserving their correspondence to
if Eval[j] > Eval[i]: # \\ their eigen vectors
Eval[i], Eval[j] = Eval[j], Eval[i]
for k in range(len(Evec)):
Evec[k][i], Evec[k][j] = Evec[k][j], Evec[k][i]
Eval_ = list(Eval)
for i in range(len(Eval_)): # For very tiny negative values that might arise
if Eval_[i] < 0: # \\ from errors in the numerical calculations
Eval_[i] = 0
if 0 in Eval_:
r = Eval_.index(0)
else:
r = len(Eval_)
Evals = [sqrt(Eval_[i]) for i in range(r)] # Getting rid of zero values and corresponding
Rvecs = [] # \\ vectors
for i in Evec:
Rvecs.append(i[:r])
Lvecs = []
for i in range(r):
v = list((1/Evals[i]) * (A @ array(Rvecs)[:, i]))
Lvecs.append(v)
EVDiag = diag(array(Evals)) # The final factorization form
RSvecs = array(Rvecs)
LSvecs = transpose(array(Lvecs))
return LSvecs, EVDiag, RSvecs