C++ 行列式为零的N×N矩阵的(伪)逆
我想取一个nxn矩阵的逆矩阵,用在我的GraphSlam中 我遇到的问题是:C++ 行列式为零的N×N矩阵的(伪)逆,c++,matrix,lapack,eigen,slam-algorithm,C++,Matrix,Lapack,Eigen,Slam Algorithm,我想取一个nxn矩阵的逆矩阵,用在我的GraphSlam中 我遇到的问题是: .inverse()Eigen库(3.1.2)不允许零值,返回NaN LAPACK(3.4.2)库不允许使用零行列式,但允许使用零值(使用的示例代码来自) 由于某种原因,Seldon库(5.1.2)无法编译 是否有人成功地实现了一个允许负值、零值和零行列式的nxn矩阵求逆代码?有什么好的库(C++)推荐吗 我试着用下面的公式来计算图表lam的ω: 简单的例子: [ 1 -1 0 0 ] [ -1 2 -1 0
Eigen库(3.1.2)不允许零值,返回.inverse()
NaN
- LAPACK(3.4.2)库不允许使用零行列式,但允许使用零值(使用的示例代码来自)
- 由于某种原因,Seldon库(5.1.2)无法编译
简单的例子:
[ 1 -1 0 0 ]
[ -1 2 -1 0 ]
[ 0 -1 1 0 ]
[ 0 0 0 0 ]
实际示例是170x170,包含0、负值和更大的正值。
给出的简单示例用于调试代码
我可以在Matlab中计算(Moore Penrose伪逆),但是由于某种原因,我不能在C++中编程。< /P>
A = [1 -1 0 0; -1 2 -1 0; 0 -1 1 0; 0 0 0 0]
B = pinv(A)
B=
[0.56 -0.12 -0.44 0]
[-0.12 0.22 -0.11 0]
[-0.44 -0.11 0.56 0]
[0 0 0 0]
对于我的应用程序,我可以(暂时)删除带有零的维度。
所以我要删除第4列和第4行
对于我的170x170矩阵,我也可以这样做,4x4只是一个例子
A: 所以去掉第四列和第四行不会得到零行列式。 但如果我的矩阵如上所述,我仍然可以有一个零行列式。 当每一行或每一列的总和为零时,会发生这种情况。(我将一直在GraphSlam中使用它)
如果行列式不是零(使用示例代码),则LAPACK解决方案(基于Moore-Penrose逆)有效。
但作为行列式为零的“伪逆”失败。
解决方案:(全部归功于Frank Reininghaus),使用SVD(奇异值分解)
与以下机构合作:
- 零值(即使是完整的0行和完整的0列)
- 负值
- 零行列式
你确定这是因为零/负值,而不是因为你的矩阵是不可逆的吗 如果矩阵的行列式为非零(),那么它只有一个逆矩阵,而你在问题中发布的矩阵示例,则它没有逆矩阵
这应该可以解释为什么这些库不允许您对给定的矩阵求逆,但我不能说相同的推理是否适用于您的全尺寸170x170矩阵。您的Matlab命令在您的情况下不会计算逆,因为矩阵具有确定零。
pinv
COMMAND命令计算出的值pinv(A)
具有inv(A)
的部分但不是全部属性
<>你在C++和MATLAB中不做同样的事情!
以前的
正如我的评论。现在作为答案。你必须确保你是可逆矩阵。这意味着
det A!=0
您的示例矩阵的行列式等于零。这不是可逆矩阵。我希望你不要试这个
例如,如果一个给定的矩阵有整行或整列的零项,则行列式为零。如果您只想解决Ax=B形式的问题(或等效计算a^-1*B形式的乘积),那么我建议您不要计算a的逆或伪逆,但使用适当的秩显示解算器直接求解Ax=b。例如,使用Eigen:
x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);
如果你的矩阵是协方差矩阵或权重矩阵,你可以用“广义cholesky反演”代替SVD。对于实际应用,结果会更容易接受高斯消去法有什么错?你能举一个小矩阵的具体例子吗?这些都不能反转?(我假设矩阵是非奇异的。)使用高斯消去法,结果中仍然可能有负值和0值。否?您的示例矩阵的行列式等于零。这不是可逆矩阵。我希望你不要试这个!你能理解这个标题吗?行列式为零的矩阵没有逆矩阵。我的错。对于我的应用程序(GraphSlam),每行上所有值的总和将等于零。但是在他们的代码中,他们仍然能够反转欧米茄矩阵,如果每行的和为零,那就不能说明它的行列式。至少我没有很快看到;-)您正在尝试求解线性方程
X=AY
。你当然可以要求A的倒数作为问题的一般解决方案,这需要det A=0
。然而,线性方程仍然可以用a
的零行列式求解。那么解空间的维数大于0。从而将整个子向量空间作为可能的解。我建议先测试行列式,然后决定如何解线性方程:倒数,高斯消去等等。好了,问题就更清楚了,我将开始在C++中挖掘Moore Penrose pseudoinverse。我真的不确定是什么问题。现在我知道我不能使用正态反演,但必须进行伪反演。Matlab使用Moore Penrose伪逆,可以得到下降结果。确切地说,它不是你试图在C++程序中计算的伪逆。
[0.56 -0.12 -0.44]
[-0.12 0.22 -0.11]
[-0.44 -0.11 0.56]
x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);