在我开发的java项目中,我需要计算矩阵的逆矩阵。为了与其他项目和其他开发人员保持一致,我使用了高效Java矩阵库(orj.ejml)。
使用org.ejml.ops.CommonOps中的反转来反转矩阵我已经工作到现在为止我得到了意想不到的结果
我已经隔离了不起作用的案例:
DenseMatrix64F X = new DenseMatrix64F(3, 3);
X.setData(new double[]{77.44000335693366,-24.64000011444091,-8.800000190734865, -24.640000114440916,7.839999732971196,2.799999952316285, -8.800000190734865,2.799999952316285,1.0000000000000004});
DenseMatrix64F invX = new DenseMatrix64F(3, 3);
boolean completed = CommonOps.invert(X, invX);
System.out.println(X);
System.out.println(invX);
System.out.println(completed);
我从这次测试得到的输出是:
Type = dense,numRows = 3,numCols = 3
77.440 -24.640 -8.800
-24.640 7.840 2.800
-8.800 2.800 1.000Type = dense,numRows = 3,numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinity真
我的第一个想法是,它可能是一个奇异的矩阵,因此不可逆,但在使用不同的计算工具测试相同的矩阵后,我发现它不是单数。
所以我回到EJML文档,找到了这个特定功能的以下信息。
如果算法无法反转矩阵,则返回false。如果它返回true,则表示算法已完成。结果可能仍然很糟糕,因为矩阵是单数或近似单数。
并且,在这种特殊情况下,矩阵不是单数,但我们可以说它几乎是单数。
我能想到的唯一解决方案是在计算它之后搜索倒置矩阵中的NaN或Infinites,如果我在那里找到一些有趣的东西,我只需用原始矩阵替换倒置矩阵,尽管它没有看起来非常干净,它可以产生合理的结果。
我的问题是:
你能想到这种情况的解决方案吗?比使用原始矩阵作为自己的逆矩阵更聪明,更聪明的东西。
如果无法绕过它,您是否知道任何其他Java Matrix库可以解决这种情况,我不期待引入新的库,但它可能是唯一的解决方案,如果这成为一个真正的问题。
关心并感谢您的投入!
答案 0 :(得分:1)
如果必须有反转,则应尝试使用SVD。另请考虑伪逆。基本上任何使用LU分解的库都会有严重的问题。这是Octave的输出。注意两个奇异值几乎为零。 Octave会给你一个与实数相反的数字,但它很差......
octave:7> cond(B)
ans = 8.5768e+17
octave:8> svd(B)
ans =
8.6280e+01
3.7146e-15
1.0060e-16
inv(B)*B
warning: inverse: matrix singular to machine precision, rcond = 4.97813e-19
ans =
0.62500 0.06250 0.03125
0.00000 0.00000 0.00000
0.00000 0.00000 4.00000