Difference in calculating eigenvectors with Java and Python

As the current task, I need to calculate the eigenvalues ​​and eigenvectors for the 120 * 120 matrix. First, I checked these calculations on a simple 2 by 2 matrix in both Java (Apache Commons Math library) and Python 2.7 (Numpy library). I have a problem with eigenvector values ​​that do not match, as shown below:

//Java import org.apache.commons.math3.linear.EigenDecomposition; import org.apache.commons.math3.linear.MatrixUtils; import org.apache.commons.math3.linear.RealMatrix; public class TemporaryTest { public static void main(String[] args) { double[][] testArray = {{2, -1}, {1, 1}}; RealMatrix testMatrix = MatrixUtils.createRealMatrix(testArray); EigenDecomposition decomposition = new EigenDecomposition (testMatrix); System.out.println("eigenvector[0] = " + decomposition.getEigenvector(0)); System.out.println("eigenvector[1] = " + decomposition.getEigenvector(1)); } 

The eigenvector output is shown as {real_value + imaginary_value; real_value + imaginary_value}:

 //Java output eigenvector[0] = {-0.8660254038; 0} eigenvector[1] = {0.5; 1} 

The same code in Python, but using the Numpy library:

 # Python import numpy as np from numpy import linalg as LA w, v = LA.eig(np.array([[2, -1], [1, 1]])) print (v[:, 0]) print (v[:, 1]) 

Python eigenvector output is shown similarly to [real + imag real + imag]:

 [ 0.35355339+0.61237244j 0.70710678+0.j ] [ 0.35355339-0.61237244j 0.70710678-0.j ] 

Does it bother me why these vectors are different? Is there something I'm missing? Ty for any help or advice.

+6
source share
2 answers

In Apache Commons Math 3, EigenDecomposition accepts asymmetric matrices, but returns results using the RealVector and RealMatrix . To get real complex results, you need to combine the corresponding real results with complex conjugate pairs.

In the case of eigenvectors, you get:

 eigenvector[0] = {-0.8660254038; 0} eigenvector[1] = {0.5; 1} 

Both of these vectors are associated with a complex conjugate pair of eigenvalues getRealEigenvalue(0) + getImagEigenvalue(0)*i and getRealEigenvalue(1) + getImagEigenvalue(1)*i , but these vectors are not real eigenvectors. The actual eigenvectors are the complex conjugate pairs eigenvector[0] + eigenvector[1]*i and eigenvector[0] - eigenvector[1]*i .

These vectors still do not "match" the results returned by numpy, but this is due to the fact that the two libraries did not use the same normalization. Eigenvectors are not unique; the eigenvector multiplied by any nonzero scalar (including the complex scalar) is still an eigenvector. The only difference between the Java result and the numpy result is the scalar factor.

For convenience, I will convert floating point values ​​to their exact values. That is, -0.8660254038 is the floating point -sqrt(3)/2 . The Java Mathematical Library produces the following eigenvectors:

  [-sqrt(3)/2 + (1/2)*i] and [-sqrt(3)/2 - (1/2)*i] [ 0 + 1*i] [ 0 - 1*i] 

If you multiply the first eigenvector by - (sqrt (2) / 2) * i and the second by (sqrt (2) / 2) * i, you get the eigenvectors returned by numpy.

Here is the ipython session with this calculation. v1 and v2 are the vectors shown above.

 In [20]: v1 = np.array([-np.sqrt(3)/2 + 0.5j, 1j]) In [21]: v1 Out[21]: array([-0.8660254+0.5j, 0.0000000+1.j ]) In [22]: v2 = np.array([-np.sqrt(3)/2 - 0.5j, -1j]) In [23]: v2 Out[23]: array([-0.8660254-0.5j, 0.0000000-1.j ]) 

Multiply v1 by - (sqrt (2) / 2) * i to get the first eigenvector returned by numpy.linalg.eig :

 In [24]: v1*(-np.sqrt(2)/2*1j) Out[24]: array([ 0.35355339+0.61237244j, 0.70710678-0.j ]) 

Multiply v2 by (sqrt (2) / 2) * i to get the second eigenvector returned by numpy.linalg.eig :

 In [25]: v2*(np.sqrt(2)/2*1j) Out[25]: array([ 0.35355339-0.61237244j, 0.70710678+0.j ]) 

For convenience, the numpy calculation is repeated here. The evecs columns are eigenvectors.

 In [28]: evals, evecs = np.linalg.eig(a) In [29]: evecs Out[29]: array([[ 0.35355339+0.61237244j, 0.35355339-0.61237244j], [ 0.70710678+0.j , 0.70710678-0.j ]]) 
+1
source

I don’t think you can make it work. That's why:

Starting from 2.0, this class supports only symmetric matrices and, therefore, calculates only real real values . This means that the matrix D returned by getD () is always diagonal, and the returned imaginary values ​​getImagEigenvalue (int) and getImagEigenvalues ​​() are always zero. (c) EigenDecomposition JavaDoc

+1
source

Source: https://habr.com/ru/post/1012339/


All Articles