如何在 Java 中使用 Apache Commons 数学库求逆矩阵?
How to find the inverse of a matrix using Apache Commons Math library in Java?
我正在尝试使用 Apache Commons 数学库求逆矩阵。
下面是我的尝试:
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 进行快速检查表明该矩阵具有非零行列式并且确实具有逆矩阵:
所以问题是 - 我做错了什么以及如何找到矩阵的逆矩阵?我使用了错误的求解器吗?
以下是基于apache common math 3.6.1
关于这个问题有人提出ticket,我提交了一个补丁来修复这个问题,修复版本为4.0(截至2021-07-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
with same value but different scale时,这个原因等于比较return不想要的结果,并在初始化FieldLUDecomposition
时导致错误。对于 BigDecimal
我们应该检查
return d.compareTo((BigReal) other) == 0;
相反。
解决方案:
- 检查 workaround section(将
BigReal
复制为本地 class 并更改 equals
)是否有帮助。
- 等待4.0版本发布。
- 如果可以接受双值矩阵,
使用
RealMatrix
instead, and MatrixUtils
provide handy 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);
}
}
我正在尝试使用 Apache Commons 数学库求逆矩阵。
下面是我的尝试:
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 进行快速检查表明该矩阵具有非零行列式并且确实具有逆矩阵:
所以问题是 - 我做错了什么以及如何找到矩阵的逆矩阵?我使用了错误的求解器吗?
以下是基于apache common math 3.6.1
关于这个问题有人提出ticket,我提交了一个补丁来修复这个问题,修复版本为4.0(截至2021-07-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
with same value but different scale时,这个原因等于比较return不想要的结果,并在初始化FieldLUDecomposition
时导致错误。对于 BigDecimal
我们应该检查
return d.compareTo((BigReal) other) == 0;
相反。
解决方案:
- 检查 workaround section(将
BigReal
复制为本地 class 并更改equals
)是否有帮助。 - 等待4.0版本发布。
- 如果可以接受双值矩阵,
使用
RealMatrix
instead, andMatrixUtils
provide handyinverse
方法
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);
}
}