gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 14:54:04 25 4
gpt4 key购买 nike

我有以下矩阵,它是对称且实数的(它是汉密尔顿运算符):(Matlab 友好)

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

如果我用这些值创建 JAMA 矩阵,并执行特征值分解,V*D*transpose(V) 不等于哈密尔顿。你们中有人知道出了什么问题吗?特征值与 MATLAB 一致,但特征向量不一致。

这是一个测试它的类

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

编辑:结果 (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

最佳答案

如果只是关于矩阵的值:这是正确的。

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. With JAMA 1.0.3 it worked. The remaining part of this answer is still valid and relevant for the question nevertheless:

这里有两个问题。首先,JAMA Matrix 类的 equals 方法不会被重写来比较矩阵的内容equals 的默认实现会比较所引用对象的身份。所以即使是像这样的微不足道的比较

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

将打印false

第二个问题相当简单(也很常见):使用double值进行计算并不是无限精确的。您可以在 StackOverflow 上找到许多与此相关的问题,但可能想看看 Wikipedia about Floating Point Accuracy Problems 。 (有些人会推荐关于 What Every Computer Scientist Should Know About Floating-Point Arithmetic 的文章,但它相当复杂......)。

通过这个小例子可以轻松重现基本问题:

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

此计算的结果不是 y==1.0,而是y==0.99999999999999...

因此,即使如果覆盖equals方法来执行逐元素比较,由于 float ,比较仍然会产生false点错误。

缓解此问题的一种方法是检查某些值是否“等于一个小 epsilon”。这可能仍然很棘手,因为要比较的值的大小在这里会产生影响,但一种解决方案可能是使用以下方法来比较矩阵的 epsilon 相等性:

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

关于java - JAMA 没有计算正确的特征向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23411921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com