(伪)-行列式为零的N乘N矩阵的逆

(Pseudo)-Inverse of N by N matrix with zero determinant

本文关键字:行列式      更新时间:2023-10-16

我想在GraphSlam中使用nxn矩阵的逆矩阵。

我遇到的问题:

  • .inverse()特征库(3.1.2)不允许零值,返回NaN
  • LAPACK(3.4.2)库不允许使用零行列式,但允许使用零值(使用C中使用LAPACK计算矩阵倒数的示例代码)
  • Seldon库(5.1.2)由于某种原因无法编译

是否有人成功实现了允许负值、零值和行列式为零的nxn矩阵求逆代码?有什么好的库(C++)推荐吗?

我尝试在下面的GraphSlam中计算ω:http://www.acastano.com/others/udacity/cs_373_autonomous_car.html


简单示例:

[ 1 -1  0 0 ]
[ -1 2 -1 0 ]
[ 0 -1  1 0 ]
[ 0  0  0 0 ]

真正的例子是170x170,包含0,负值,更大的正值。给定的简单示例用于调试代码。


我可以在matlab(Moore Penrose伪逆)中计算,但由于某些原因,我无法在C++中编程。

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:

[ 1 -1  0 ]
[ -1 2 -1 ]
[ 0 -1  1 ]

所以去掉第4列和第4行不会得到一个零行列式。但如果我的矩阵如上所述,我仍然可以有一个零行列式。当每一行或每一列的总和为零时,就会出现这种情况。(我将一直在GraphSlam中使用)

如果行列式不为零,则LAPACK解决方案(基于Moore Penrose逆)有效(使用C中使用LAPACK计算矩阵逆的示例代码)
但作为行列式为零的"伪逆"失败了


解决方案:(Frank Reininghaus所有学分),使用SVD(奇异值分解)
http://sourceware.org/ml/gsl-discuss/2008-q2/msg00013.html

适用于:

  • 零值(甚至是完整的0行和完整的0列)
  • 负值
  • 零的行列式

A^-1:

[0.56   -0.12  -0.44]
[-0.12  0.22   -0.11]
[-0.44  -0.11   0.56]

如果你只想解决形式Ax=B的问题(或等效地计算形式A^-1*B的乘积),那么我建议你不要计算A的逆或伪逆,而是使用适当的秩揭示求解器直接求解Ax=B。例如,使用特征:

x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);

在您的情况下,您的Matlab命令不会计算逆,因为矩阵已确定为零。pinv命令计算Moore-Penrose伪逆。pinv(A)具有inv(A)的一些性质,但不是全部。

所以你在C++和Matlab中没有做同样的事情!

上一个

正如我的评论。现在作为答案。您必须确保反转可逆矩阵。这意味着

det A != 0

您的示例矩阵的行列式等于零。这不是一个可逆矩阵。我希望你不要尝试这个!

例如,如果一个给定的矩阵有一整行或整列的零项,则该矩阵具有行列式零。

你确定这是因为零值/负值,而不是因为你的矩阵是不可逆的吗?

一个矩阵只有在其行列式为非零时才有一个逆(mathworld链接),而你在问题中发布的矩阵例子有一个零行列式,所以它没有逆。

这应该解释了为什么这些库不允许你取给定矩阵的倒数,但我不能说同样的推理是否适用于你的全尺寸170x170矩阵。

如果矩阵是协方差矩阵或权重矩阵,则可以使用"广义cholesky反演"而不是SVD。对于实际使用,结果将更容易接受