5

我想在我的 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 计算以下欧米茄: 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 逆)起作用(使用来自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

4 回答 4

7

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

x = A.colPivHouseholderQr().solve(b);
x = A.jacobiSvd(ComputeThinU|ComputeThinV).solve(b);
于 2012-12-17T23:35:43.387 回答
4

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

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

以前的

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

det A != 0

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

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

于 2012-12-17T18:28:20.253 回答
2

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

如果矩阵的行列式不为零(mathworld 链接),则矩阵只有逆矩阵,并且您在问题中发布的矩阵示例的行列式为零,因此它没有逆矩阵。

这应该可以解释为什么这些库不允许您取给定矩阵的逆矩阵,但我不能说相同的推理是否适用于您的全尺寸 170x170 矩阵。

于 2012-12-17T18:26:48.227 回答
0

如果您的矩阵是一种协方差或权重矩阵,您可以使用“广义 cholesky 反演”而不是 SVD。结果在实际使用中会更容易接受

于 2014-02-20T08:59:10.237 回答