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 ]])