2016-11-15 141 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