I made a very simple QR algorithm code that returns eigenvalues and eigenvectors. In many cases, it works well. However, in some cases, it returns incorrect eigenvectors although the eigenvalues are correct.
For example, a matrix of:
[[52,30,49,28],[30,50,8,44],[49,8,46,16],[28,44,16,22]]
,
the process returns correct eigenvalues and eigenvectors.
But, in a case of:
[[1,-2,0,5],[0,7,1,5],[0,4,4,0],[0,0,0,2]]
,
it returns incorrect eigenvectors with correct eigenvalues.
I checked the correct values by 'eigh' function and all the correct eigenvalues and eigenvectors are real number. So, it is not the problem of complex numbers.
I cannot understand why this happens.
import numpy as np
def process(self, mat: List[List[float]]):
check = True
a = mat[:]
residual = 0.00001
eigenValues = []
eigenVectors = np.eye(len(mat))
while check:
check = False
q, r = np.linalg.qr(a)
a = np.dot(r, q)
eigenVectors = np.dot(eigenVectors, q)
for i in range(len(mat)):
for j in range(i):
if abs(a[i][j]) > residual: check = True
for i in range(len(a)): eigenValues.append(a[i][i])
print(eigenValues) #[1.0, 8.000000054834647, 2.9999999451653365, 2.0]
print(eigenVectors) #[[1.0, 0.0, 0.0, 0.0],
[0.0, 0.7071067941112008, -0.7071067682618934, 0.0],
[0.0, 0.7071067682618939, 0.7071067941112008, 0.0],
[0.0, 0.0, 0.0, 1.0]]
# The correct eigenvectors are
[[ 1. -0.19802951 0.23570226 0.90744251],
[ 0. 0.69310328 -0.23570226 -0.1814885 ],
[ 0. 0.69310328 0.94280904 0.362977 ],
[ 0. 0. 0. 0.1088931 ]]
Is it a problem that comes from the Household reflection algorithm that the 'numpy.linalg.qr' adopts? Do I have to apply the Givens rotation? Or, is it the matter of my QR algorithm code?
QR algorithm is known to be able to get both the eigenvalue and eigenvector when the input matrix is symmetric but for the asymmetric case, there is no such promise.
Hence, your first input matrix works because it is symmetrical.
Your second input matrix is not symmetrical.