2016-11-15 69 views
6

作为当前的任务,我需要计算120 * 120矩阵的特征值和特征向量。首先,我在Java(Apache Commons Math库)和Python 2.7(Numpy库)中以简单的2乘2矩阵测试了这些计算。我有本征矢量的值不匹配的问题,如示于下:使用Java和Python计算特征向量的差异

//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)); 
} 

特征向量的输出被示为{real_value + imaginary_value; real_value + imaginary_value}:在Python

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

相同的代码,但使用numpy的库:

# 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特征向量的输出被类似地示出,[真实+ IMAG真实+ IMAG]:

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

我担心的是,为什么这些载体不同?有什么我失踪了吗? Ty的任何形式的帮助或建议

+1

Java输出中的那些向量不是特征向量。 'getEigenvector(i)'返回一个'RealVector',但是你的矩阵有复杂的特征值和特征向量。我不知道Apache Commons Math Library是如何表示复杂的特征向量的;希望熟悉图书馆的人能够帮助你将由Java函数返回的实际值转化为实际复杂的特征向量。 –

+0

我同意,但正如你所看到的,即使是真正的值不匹配: -/ – borgmater

+0

Java的甚至不规范化.. – user3684792

回答

1

阿帕奇百科全书式3,EigenDecomposition接受非对称矩阵,但它使用的类RealVectorRealMatrix返回结果。要获得实际的复杂结果,必须将适当的实际结果组合为复共轭对。

在特征向量的情况下,你有:

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

这两项矢量与复共轭对特征值getRealEigenvalue(0) + getImagEigenvalue(0)*igetRealEigenvalue(1) + getImagEigenvalue(1)*i相关,但这些向量不是实际的特征向量。实际的特征向量是复共轭对 eigenvector[0] + eigenvector[1]*ieigenvector[0] - eigenvector[1]*i

这些向量仍然不匹配numpy返回的结果,但这是因为这两个库没有使用相同的规范化。特征向量不是唯一的;一个乘以任意非零标量(包括一个复数标量)的特征向量仍然是一个特征向量。 Java结果和numpy结果之间的唯一区别是标量乘数。

为了方便起见,我会将浮点值转换为精确值。即,-0.8660254038-sqrt(3)/2的浮点近似值。Java的数学库是给下面的特征向量:

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

如果通过乘以第一特征向量 - (开方(2)/ 2)*我和第二个由(SQRT(2)/ 2)* 1,你会得到numpy返回的特征向量。

下面是这个计算的ipython会话。 v1v2是上面显示的向量。

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

v1由 - (SQRT(2)/ 2)*我得到的第一特征向量返回由numpy.linalg.eig

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

v2(开方(2)/ 2)* I获得由numpy.linalg.eig返回的第二个特征向量:

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

为了方便起见,这里的numpy的计算的重复。 evecs的列是特征向量。

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

首先,非常感谢你的详细解答:)第二,我希望你不介意我是否一步一步地采取这种方式,这样我就能理解一切。我目前的问题是 - 如果eigenvector [0]和eigenvector [1]都有两个条目(例如-0.8660254038; 0),那么您使用第二个条目(零),你是如何提出“我”和“-i”(在转换浮点后的答案中)? P.S.另外,我运行了{{2,-2},{1,1}}的另一个示例,并按照您的过程,无法获得正确的值:( – borgmater

+0

*“...您在哪里使用第二个条目(零) “*因为'eigenvector [0] [1]'为0,所以实际特征向量的第二项都是纯虚构的;实部是0.我编辑了特征向量的ASCII表示以解释包括”0 + ...“ “; 0是'特征向量[0] [1]' –

+0

*。” ......按照您的程序,不能得到正确的价值观“*您不能使用相同的常量(±开方(2)/ 2)标量倍数。对于每一个特征向量(更精确地,对于具有[* *简单特征值](https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Algebraic_multiplicity)相关联的每个特征向量),将有一些* *常数您可以使用到Java结果映射到numpy的结果。 –

1

我不认为你能够使它工作。这是为什么:

由于2.0,这一类只支持对称矩阵,因此只计算真实的特征值。这意味着由getD()返回的D矩阵总是对角的,并且返回的虚数值getImagEigenvalue(int)和getImagEigenvalues()始终为空。 (c)中EigenDecomposition JavaDoc

相关问题