0

在我开发的 java 项目中,我需要计算矩阵的逆。为了与其他项目和其他开发人员保持一致,我正在使用 Efficient Java Matrix Library (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);  

我从这个测试中得到的输出是:

类型 = 密集,numRows = 3,numCols = 3
77.440 -24.640 -8.800
-24.640 7.840 2.800
-8.800 2.800 1.000

类型 = 密集,numRows = 3,numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinity

真的

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

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

如果算法无法反转矩阵,则返回 false。如果它返回 true,则意味着算法完成。结果可能仍然很糟糕,因为矩阵是奇异的或几乎是奇异的。

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

我能想到的唯一解决方案是在计算后搜索 NaN 或 Infinites 的倒置矩阵,如果我在那里发现一些有趣的东西,我只需用原始矩阵替换倒置矩阵,尽管这似乎不是一个非常干净的做法它产生合理的结果。

我的问题是:

  • 你能想出任何解决这种情况的办法吗?比仅使用原始矩阵作为自己的逆矩阵更聪明和更明智的方法。

  • 如果没有办法解决,你知道有没有其他 Java Matrix 库可以解决这种情况,我不期待引入一个新库,但如果这成为一个真正的问题,它可能是唯一的解决方案.

问候并感谢您的投入!

4

1 回答 1

1

如果你必须有一个逆,你应该尝试使用 SVD。还要考虑一个伪逆。基本上任何使用 LU 分解的库都会有严重的问题。这是 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
于 2015-07-26T05:47:01.893 回答