如何在Java中使用Apache Commons Math库找到矩阵的逆?

3
我正在尝试使用Apache Commons Math Library找到一个矩阵的逆。
下面是我的尝试:
BigReal[][] leftMatrixData = new BigReal[][] {
    { new BigReal(1), new BigReal(0), new BigReal(0), new BigReal(0) },
    { new BigReal(1), new BigReal(0), new BigReal(1), new BigReal(0) },
    { new BigReal(1), new BigReal(1), new BigReal(0), new BigReal(0) },
    { new BigReal(1), new BigReal(1), new BigReal(1), new BigReal(1) },
};

FieldMatrix<BigReal> leftMatrix = MatrixUtils.createFieldMatrix(leftMatrixData);
FieldMatrix<BigReal> leftMatrixInverse = new FieldLUDecomposition<>(leftMatrix)
    .getSolver()
    .getInverse();

当我运行这个程序时,出现了以下错误:
org.apache.commons.math3.exception.MathArithmeticException: zero not allowed here

    at org.apache.commons.math3.util.BigReal.divide(BigReal.java:255)
    at org.apache.commons.math3.util.BigReal.divide(BigReal.java:39)
    at org.apache.commons.math3.linear.FieldLUDecomposition.<init>(FieldLUDecomposition.java:160)

根据上面的错误信息,当我打开FieldLUDecomposition.java文件的第160行时,我发现该库认为这个矩阵是奇异的,即它认为它没有逆矩阵:
public T getDeterminant() {
    if (this.singular) { <---- this is line 160
        return (FieldElement)this.field.getZero();
    } else {
        int m = this.pivot.length;
        T determinant = this.even ? (FieldElement)this.field.getOne() : (FieldElement)((FieldElement)this.field.getZero()).subtract(this.field.getOne());

然而,通过 WolframAlpha 进行快速检查可以发现这个矩阵具有非零行列式并且确实具有逆矩阵:

enter image description here

所以问题是 - 我做错了什么,如何找到矩阵的逆?我使用的求解器有问题吗?
1个回答

3

以下内容基于apache common math 3.6.1

有关此问题,提出了,我提交了一个补丁来修复问题,修复版本将是4.0(截至2021年7月19日尚未发布)

该问题的原因在于BigReal中的equals方法。

    @Override
    public boolean equals(Object other) {
        if (this == other){
            return true;
        }

        if (other instanceof BigReal){
            return d.equals(((BigReal) other).d);
        }
        return false;
    }

其中d是BigDecimal,是BigReal的支持值。当两个BigReal具有相同但比例不同的d{{link1:时,这会导致等于比较返回不希望的结果,同时在初始化FieldLUDecomposition时引起错误。对于BigDecimal,我们应该进行检查。

    return d.compareTo((BigReal) other) == 0;

替代方案:

解决方案:

  1. 检查 解决方法部分(将 BigReal 复制为本地类并更改 equals) 是否有所帮助。
  2. 等待版本 4.0 发布。
  3. 如果双精度值矩阵可接受,使用 RealMatrix 替代,并且 MatrixUtils 提供便利的 inverse 方法。
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

public class CalculateInverse {
    public static void main(String[] args) {
        double[][] matrixData = new double[][]{
                {1, 0, 0, 0},
                {1, 0, 1, 0},
                {1, 1, 0, 0},
                {1, 1, 1, 1}
        };
        RealMatrix matrix = MatrixUtils.createRealMatrix(matrixData);
        RealMatrix inverse = MatrixUtils.inverse(matrix);
        System.out.println(inverse);
    }
}

谢谢您的建议!不幸的是,基于我的代码用例,我真的想保持BigDecimal。我只是简化了我的示例为1和0,以显示当我使用由BigDecimals组成的矩阵时,我很难找到逆元素,而且我不知道原因。我认为这可能是一个错误,但我不确定,因为我是第一次使用Apache Commons Math库。 - ptk
1
经过一些调试,我认为库中存在一些问题,我已经为此问题提出了一个工单并更新了答案。 - samabcde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接