简体   繁体   English

JAMA没有计算正确的特征向量

[英]JAMA is not calculating the right eigen vectors

I have the following matrix, which is symmetric and real (It is a hamilton-operator): (Matlab friendly) 我有以下对称且实的矩阵(它是汉密尔顿运算符):(适用于Matlab)

[63.000000, -1.732051, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; [63.000000,-1.732051、0.000000、0.000000、0.000000、0.000000、0.000000、0.000000、0.000000、0.000000; -1.732051, 61.000000, -2.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; -1.732051、61.000000,-2.000000、0.000000,-1.000000、0.000000、0.000000、0.000000、0.000000、0.000000; 0.000000, -2.000000, 61.000000, -1.732051, 0.000000, -1.414214, 0.000000, 0.000000, 0.000000, 0.000000; 0.000000,-2.000000、61.000000,-1.732051、0.000000,-1.414214、0.000000、0.000000、0.000000、0.000000; 0.000000, 0.000000, -1.732051, 63.000000, 0.000000, 0.000000, -1.732051, 0.000000, 0.000000, 0.000000; 0.000000、0.000000,-1.732051、63.000000、0.000000、0.000000,-1.732051、0.000000、0.000000、0.000000; 0.000000, -1.000000, 0.000000, 0.000000, 61.000000, -1.414214, 0.000000, 0.000000, 0.000000, 0.000000; 0.000000,-1.000000、0.000000、0.000000、61.000000,-1.414214、0.000000、0.000000、0.000000、0.000000; 0.000000, 0.000000, -1.414214, 0.000000, -1.414214, 60.000000, -1.414214, -1.414214, 0.000000, 0.000000; 0.000000,0.000000,-1.414214,0.000000,-1.414214,60.000000,-1.414214,-1.414214,0.000000,0.000000; 0.000000, 0.000000, 0.000000, -1.732051, 0.000000, -1.414214, 61.000000, 0.000000, -2.000000, 0.000000; 0.000000,0.000000,0.000000,-1.732051,0.000000,-1.414214,61.000000,0.000000,-2.000000,0.000000; 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.414214, 0.000000, 61.000000, -1.000000, 0.000000; 0.000000、0.000000、0.000000、0.000000、0.000000,-1.414214、0.000000、61.000000,-1.000000、0.000000; 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -2.000000, -1.000000, 61.000000, -1.732051; 0.000000、0.000000、0.000000、0.000000、0.000000、0.000000,-2.000000,-1.000000、61.000000,-1.732051; 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.732051, 63.000000] 0.000000、0.000000、0.000000、0.000000、0.000000、0.000000、0.000000、0.000000,-1.732051、63.000000]

If i make a JAMA-matrix with these values, and execute the eigenvalue decomposition, V*D*transpose(V) does NOT equal the hamilton. 如果我使用这些值制作一个JAMA矩阵,然后执行特征值分解,则V * D * transpose(V)不等于汉密尔顿。 Do any of you guys know what goes wrong? 你们有谁知道出了什么问题吗? The eigenvalues are consistent with MATLAB, but the eigenvectors are not. 特征值与MATLAB一致,但特征向量不一致。

Here is a class to test it 这是一个测试它的课程

public class TestJama {


public static void main(String[] args) {

    double[][] m = new double[][] {
            {63.000000, -1.732051, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
            { -1.732051, 61.000000, -2.000000, 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
            { 0.000000, -2.000000, 61.000000, -1.732051, 0.000000, -1.414214, 0.000000, 0.000000, 0.000000, 0.000000},
            { 0.000000, 0.000000, -1.732051, 63.000000, 0.000000, 0.000000, -1.732051, 0.000000, 0.000000, 0.000000},
            { 0.000000, -1.000000, 0.000000, 0.000000, 61.000000, -1.414214, 0.000000, 0.000000, 0.000000, 0.000000},
            { 0.000000, 0.000000, -1.414214, 0.000000, -1.414214, 60.000000, -1.414214, -1.414214, 0.000000, 0.000000},
            { 0.000000, 0.000000, 0.000000, -1.732051, 0.000000, -1.414214, 61.000000, 0.000000, -2.000000, 0.000000},
            { 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.414214, 0.000000, 61.000000, -1.000000, 0.000000},
            { 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -2.000000, -1.000000, 61.000000, -1.732051},
            { 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.732051, 63.000000}
    };


    Matrix hamilton = new Matrix(m);
    System.out.println(jamaToString(hamilton));

    EigenvalueDecomposition e = hamilton.eig();
    System.out.println(jamaToString(e.getD()));
    System.out.println(jamaToString(e.getV()));

    Matrix recomb = e.getV().times(e.getD()).times(e.getV().transpose());
    System.out.println(jamaToString(recomb));

    System.out.println(hamilton.equals(recomb));

}

private static String jamaToString(Matrix m) {
    StringBuilder b = new StringBuilder();
    b.append("[");
    for(int i=0; i<m.getRowDimension(); i++) {

        for(int j=0; j<m.getColumnDimension(); j++) {
            b.append(m.get(i, j));
            if(j<m.getColumnDimension() - 1) b.append(",");
        }
        if(i<m.getRowDimension() - 1) b.append(";");
    }
    b.append("]");
    return b.toString();
}
}

EDIT: The result (V*D*transpose(V)) yields 编辑:结果(V * D * transpose(V))产生

63.1093 -0.6379 0.3400 -0.6576 0.0938 -0.0437 -0.6056 -0.5066 0.3463 0.5039 -0.6379 61.3082 -0.2368 -1.7813 -0.0851 0.7949 -0.1337 0.7668 -0.0422 -2.4329 0.3400 -0.2368 60.1481 1.3323 -0.4099 -1.8834 -0.5780 0.7516 0.0946 0.1705 -0.6576 -1.7813 1.3323 61.2455 0.0972 -0.8075 -0.9004 0.0242 0.3963 -1.2527 0.0938 -0.0851 -0.4099 0.0972 60.3086 -0.1899 0.0394 0.1987 -0.0484 -0.1495 -0.0437 0.7949 -1.8834 -0.8075 -0.1899 61.7941 0.3741 0.8237 0.7772 0.7557 -0.6056 -0.1337 -0.5780 -0.9004 0.0394 0.3741 60.6415 0.6351 0.7099 0.3349 -0.5066 0.7668 0.7516 0.0242 0.1987 0.8237 0.6351 62.8108 1.3507 1.3002 0.3463 -0.0422 0.0946 0.3963 -0.0484 0.7772 0.7099 1.3507 63.3270 0.1244 0.5039 -2.4329 0.1705 -1.2527 -0.1495 0.7557 0.3349 1.3002 0.1244 60.3069 63.1093 -0.6379 0.3400 -0.6576 0.0938 -0.0437 -0.6056 -0.5066 0.3463 0.5039 -0.6379 61.3082 -0.2368 -1.7813 -0.0851 0.7949 -0.1337 0.7668 -0.0422 -2.4329 0.3400 -0.2368 60.1481 1.3323 -0.4099 -1.8834 -0.5780 0.7516 0.0946 0.1705 -0.6576 -1.7813 1.3323 61.2455 0.0972 -0.8075 -0.9004 0.0242 0.3963 -1.2527 0.0938 -0.0851 -0.4099 0.0972 60.3086 -0.1899 0.0394 0.1987 -0.0484 -0.1495 -0.0437 0.7949 -1.8834 -0.8075 -0.1899 61.7941 0.3741 0.8237 0.7772 0.7557 -0.6056 -0.1337 -0.5780 -0.9004 0.0394 0.3741 60.6415 0.6351 0.7099 0.3349 -0.5066 0.7668 0.7516 0.0242 0.1987 0.8237 0.6351 62.8108 1.3507 1.3002 0.3463 -0.0422 0.0946 0.3963 -0.0484 0.7772 0.7099 1.3507 63.3270 0.1244 0.5039 -2.4329 0.1705 -1.2527 -0.1495 0.7557 0.3349 1.3002 0.1244 60.3069

If it is only about the value of the matrix: It is correct. 如果仅关于矩阵的值:是正确的。

EDIT: The above statement was written before the resulting matrix was inserted into the original question. 编辑:以上语句是将结果矩阵插入到原始问题之前编写的。 Of course, this matrix is not correct. 当然,这个矩阵是正确的。 According to the comments, it seems that this wrong matrix was caused by some bug in an older JAMA version. 根据评论,似乎此错误矩阵是由较旧的JAMA版本中的某些错误引起的。 With JAMA 1.0.3 it worked. 使用JAMA 1.0.3可以正常工作。 The remaining part of this answer is still valid and relevant for the question nevertheless: 但是,此答案的其余部分仍然有效,并且与该问题相关:

There are two problems here. 这里有两个问题。 First of all, the equals method of the JAMA Matrix class is not overridden to compare the contents of the matrices. 首先,不会重写JAMA Matrix类的equals方法来比较矩阵的内容 And the default implementation of equals compares for identity of the referred objects. equals的默认实现比较所引用对象的身份 So even a trivial comparison like this 因此,即使是这样的琐碎比较

Matrix A = new Matrix(new double[][]{{1.0}});
Matrix B = new Matrix(new double[][]{{1.0}});
System.out.println(A.equals(B));

would print false . 将打印false

The second problem is rather simple (and common) : Computations with double values are not infinitely precise. 第二个问题很简单(并且很常见):具有double精度值的计算不是无限精确的。 You can find many questions about this on StackOverflow, but might want to have a look at Wikipedia about Floating Point Accuracy Problems . 您可以在StackOverflow上找到许多与此有关的问题,但可能想看一下有关浮点精度问题的Wikipedia (Some people would recommend the article about What Every Computer Scientist Should Know About Floating-Point Arithmetic , but it's rather involved...). (有些人会推荐有关每位计算机科学家应该了解的有关浮点算法的文章 ,但这确实涉及其中……)。

The basic problem can easily reproduced with this small example: 这个小例子可以很容易地重现基本问题:

double x = 0.1;
double y = 0;
for (int i=0; i<10; i++)
{
    y += x;
}
System.out.println(y+" == 1.0: "+(y==1.0));

The result of this computation is not y==1.0 , but y==0.99999999999999... instead. 该计算的结果不是 y==1.0 ,而是y==0.99999999999999...

So even if the equals method was overridden to perform an element-wise comparison, the comparison would still yield false due to the floating point error. 所以,即使 equals方法重写进行逐元素的比较,比较仍然会产生false由于浮点错误。

One way of alleviating this problem is to check whether some values are "equal up to a small epsilon". 缓解此问题的一种方法是检查某些值是否“等于小ε”。 This may still be tricky, because the magnitude of the values to be compared will make a difference here, but one solution could be to use the following method to compare matrices for epsilon-equality: 这可能仍然很棘手,因为要比较的值的大小会在这里有所不同,但是一种解决方案可能是使用以下方法比较矩阵以求出ε等式:

private static boolean epsilonEqual(Matrix a, Matrix b)
{
    int ra = a.getRowDimension();
    int rb = b.getRowDimension();
    if (ra != rb)
    {
        return false;
    }
    int ca = a.getColumnDimension();
    int cb = b.getColumnDimension();
    if (ca != cb)
    {
        return false;
    }
    for (int c=0; c<ca; c++)
    {
        for (int r=0; r<ra; r++)
        {
            double ea = a.get(r, c);
            double eb = b.get(r, c);
            if (!epsilonEqual(ea, eb))
            {
                return false;
            }
        }
    }
    return true;
}

private static boolean epsilonEqual(double x, double y)
{
  final double epsilon = 1e-8;
  return Math.abs(x - y) <= epsilon;
}    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM