147 KiB
147 KiB
In [1]:
Ainv = np.linlag.pinv(A)In [4]:
import numpy as np
# SVD inversion
def SVDinv(A):
''' Takes as input a numpy matrix A and returns inv(A) based on singular value decomposition (SVD).
SVD is numerically more stable than the inversion algorithms provided by
numpy and scipy.linalg at the cost of being slower.
'''
U, s, VT = np.linalg.svd(A)
print('test U')
print( (np.transpose(U) @ U - U @np.transpose(U)))
print('test VT')
print( (np.transpose(VT) @ VT - VT @np.transpose(VT)))
D = np.zeros((len(U),len(VT)))
D = np.diag(s)
UT = np.transpose(U); V = np.transpose(VT); invD = np.linalg.inv(D)
return np.matmul(V,np.matmul(invD,UT))
X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ])
# Non-singular square matrix
#X = np.array( [ [1,2,3],[2,4,5],[3,5,6]])
print(X)
A = np.transpose(X) @ X
# Brute force inversion
B = np.linalg.pinv(A) # here we could use np.linalg.pinv(A)
C = SVDinv(A)
print(np.abs(B-C))[[ 1. -1. 2.] [ 1. 0. 1.] [ 1. 2. -1.] [ 1. 1. 0.]] test U [[-3.33066907e-16 -1.11022302e-16 3.33066907e-16] [-1.11022302e-16 4.44089210e-16 -2.49800181e-16] [ 3.33066907e-16 -2.49800181e-16 0.00000000e+00]] test VT [[ 2.22044605e-16 5.55111512e-17 -2.22044605e-16] [ 5.55111512e-17 -2.22044605e-16 5.55111512e-17] [-2.22044605e-16 5.55111512e-17 2.22044605e-16]] [[1.82969604e+30 1.82969604e+30 1.82969604e+30] [1.82969604e+30 1.82969604e+30 1.82969604e+30] [1.82969604e+30 1.82969604e+30 1.82969604e+30]]
In [5]:
import numpy as np
# SVD inversion
def SVDinv(A):
U, s, VT = np.linalg.svd(A)
# reciprocals of singular values of s
d = 1.0 / s
# create m x n D matrix
D = np.zeros(A.shape)
# populate D with n x n diagonal matrix
D[:A.shape[1], :A.shape[1]] = np.diag(d)
UT = np.transpose(U)
V = np.transpose(VT)
return np.matmul(V,np.matmul(D.T,UT))
A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]])
print(A)
# Brute force inversion of super-collinear matrix
B = np.linalg.pinv(A)
print(B)
# Compare our own algorithm with pinv
C = SVDinv(A)
print(np.abs(C-B))[[0.3 0.4] [0.5 0.6] [0.7 0.8] [0.9 1. ]] [[-13. -6. 1. 8. ] [ 11.5 5.5 -0.5 -6.5]] [[0. 0. 0. 0.] [0. 0. 0. 0.]]
Warning:
Output truncated. This notebook contains too many cells to display efficiently.