(伪) - 具有零行列式的N×N矩阵的逆

时间:2012-12-17 18:10:30

标签: c++ matrix lapack eigen slam-algorithm

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

我遇到的问题:

  • .inverse()特征库(3.1.2)不允许零值,返回NaN
  • LAPACK(3.4.2)库不允许使用零行列式,但允许零值(使用来自Computing the inverse of a matrix using lapack in C的示例代码)
  • Seldon图书馆(5.1.2)由于某种原因无法编译

是否有人成功实现了 n x n 矩阵反转代码,允许负值,零值和零行列式?任何好的库(C ++)建议?

我尝试为GraphSlam计算以下的omega: 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 pseudoinverse)中计算出来,但由于某种原因,我无法用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 Inverse)工作(使用来自Computing the inverse of a matrix using lapack in C的示例代码)。
但作为具有零行列式的“伪逆”失败。


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

适用于:

  • 零值(甚至完整0行和完整0列)
  • 负值
  • 决定性为零

一个^ -1:

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

4 个答案:

答案 0 :(得分:7)

如果您只想解决Ax = B形式的问题(或者等效地计算A ^ -1 * b形式的产品),那么我建议您不要计算A的逆或伪逆,但是使用适当的等级显示求解器直接求解Ax = b。例如,使用Eigen:

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

答案 1 :(得分:4)

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

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

上一页

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

det A != 0

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

例如,如果存在零行的完整行或列,则给定矩阵的行列式为零。

答案 2 :(得分:2)

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

如果矩阵的行列式非零(mathworld link),并且您在问题has a zero determinant中发布了矩阵示例,那么它只有一个逆矩阵,因此它没有逆。

这应该解释为什么那些库不允许你采用给定矩阵的逆矩阵,但我不能说你的全尺寸170x170矩阵是否有相同的推理。

答案 3 :(得分:0)

如果你的矩阵是一种协方差或权重矩阵,你可以使用“广义cholesky反演”而不是SVD。结果将更适合实际使用