1

I wrote a simple Linear Algebra code in Python Numpy to calculate the Diagonal of EigenValues by calculating $M^{-1}.A.M$ (M is the Modal Matrix) and it's working strange.

Here's the Code :

import numpy as np

array = np.arange(16)
array = array.reshape(4, -1)
print(array)

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

eigenvalues, eigenvectors = np.linalg.eig(array)

print eigenvalues
[  3.24642492e+01  -2.46424920e+00   1.92979794e-15  -4.09576009e-16]

print eigenvectors
[[-0.11417645 -0.7327781   0.54500164  0.00135151]
 [-0.3300046  -0.28974835 -0.68602671  0.40644504]
 [-0.54583275  0.15328139 -0.2629515  -0.8169446 ]
 [-0.76166089  0.59631113  0.40397657  0.40914805]]

inverseEigenVectors = np.linalg.inv(eigenvectors) #M^(-1)
diagonal= inverseEigenVectors.dot(array).dot(eigenvectors) #M^(-1).A.M

print(diagonal)
[[  3.24642492e+01  -1.06581410e-14   5.32907052e-15   0.00000000e+00]
 [  7.54951657e-15  -2.46424920e+00  -1.72084569e-15  -2.22044605e-16]
 [ -2.80737213e-15   1.46768503e-15   2.33547852e-16   7.25592561e-16]
 [ -6.22319863e-15  -9.69656080e-16  -1.38050658e-30   1.97215226e-31]]

the final 'diagonal' matrix should be a diagonal matrix with EigenValues on the main diagonal and zeros elsewhere. but it's not... the two first main diagonal values ARE eigenvalues but the two second aren't (although just like the two second eigenvalues, they are nearly zero).

and by the way a number like $-1.06581410e-14$ is literally zero so how can I make numpy show them as zero?

What am I doing wrong?

Thanks...

Cypher
  • 2,374
  • 4
  • 24
  • 36
  • 2
    Hint: row 3 = 2*row 2 - row 1 – Alexander Kemp Apr 03 '16 at 21:09
  • 1
    Uh oh... then... the Determinant of the matrix is zero? and det(A) = product of eigenvalues... and eigenvalues should be zero? if I've got it right till here, then why does numpy calculate EigenValues and not give 0 as an answer? – Cypher Apr 03 '16 at 21:16
  • 2
    all is ok. Consider in float word that any value < 1e-15 is null. Try diagonal.round(13) , and matrix_rank(array). – B. M. Apr 03 '16 at 21:18
  • can I tell numpy to transform really small values to null or zero ? sometimes if you're not careful, the length of those really small values deceives you and you think they're not zeros... I would have liked my final matrix to be a diagonal with zeros up and down... and having 0 as determinant would really be more useful than something like '-7.09974814699e-30' ! – Cypher Apr 03 '16 at 21:25
  • Sorry for asking too many questions but Why did Numpy calculate EigenValues in the first place where it should have told me that the Matrix is Singular? the strange thing is that it's giving 4 legit EigenValues two of which are big enough not to be considered 0 or null! – Cypher Apr 03 '16 at 21:29
  • 2
    It is normal - in some sense zero eigenvalues are 'telling you that the matrix is singular'. Eigenvalues are found iteratively, and iteration is stopped if the off-diagonal entries are small enough. What is on the diagonal may be of interest to you, but not the algorithm. – Alexander Kemp Apr 03 '16 at 21:29
  • Thanks so much for the answers... I still wish there was a way to make Numpy easily show that the EigenValue is Zero not "-4.09576009e-16" ! I may have to ask another question sometime later... Thanks Again for the answers... – Cypher Apr 04 '16 at 05:51

2 Answers2

3

Just round the final result to the desired digits :

print(diagonal.round(5))

array([[ 32.46425,   0.     ,   0.     ,   0.     ],
       [  0.     ,  -2.46425,   0.     ,   0.     ],
       [  0.     ,   0.     ,   0.     ,   0.     ],
       [  0.     ,   0.     ,   0.     ,   0.     ]])

Don't confuse precision of computation and printing policies.

B. M.
  • 18,243
  • 2
  • 35
  • 54
2
>>> diagonal[np.abs(diagonal)<0.0000000001]=0
>>> print diagonal
[[ 32.4642492   0.          0.          0.       ]
 [  0.         -2.4642492   0.          0.       ]
 [  0.          0.          0.          0.       ]
 [  0.          0.          0.          0.       ]]
>>>
Yaron
  • 10,166
  • 9
  • 45
  • 65