Java:使用EJML的逆矩阵没有按预期工作



在我开发的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.000

Type = dense, numRows = 3, numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinity

真正

我的第一个想法是它可能是一个奇异矩阵,因此不可逆,但在用不同的计算工具测试了相同的矩阵后,我发现它不是奇异的。

所以我回到EJML文档,找到了这个特定函数的以下信息。

如果算法不能反转矩阵,则返回false。如果返回true,则表示算法完成。由于矩阵是奇异或近似奇异的,结果仍然可能是糟糕的。

在这种特殊情况下,矩阵不是奇异的,但我们可以说它是接近奇异的。

我能想到的唯一解决方案是在计算后搜索反向矩阵的NaN或无穷大,如果我在那里发现一些有趣的东西,我只是用原始矩阵替换反向矩阵,虽然它似乎不是一个非常干净的实践,它产生合理的结果。

我的问题是:
  • 对于这种情况你能想到什么解决办法吗?

  • 在没有办法的情况下,你知道任何其他Java矩阵库有一些解决这种情况的方法吗?我不期待引入一个新的库,但如果这成为一个真正的问题,它可能是唯一的解决方案。

尊敬并感谢您的输入!

如果您必须有一个逆,您应该尝试使用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

最新更新