犰狳 C++ 找不到矩阵逆

Posted

技术标签:

【中文标题】犰狳 C++ 找不到矩阵逆【英文标题】:Armadillo C++ doesn't find matrix inverse 【发布时间】:2017-06-13 00:28:22 【问题描述】:

我正在使用 Armadillo 和 C++,我试图找到矩阵的逆矩阵,但是,逆矩阵只是返回矩阵本身。

在我看来,没有任何计算。此外,没有抛出任何错误。

我正在使用以下标题:

#include <armadillo>
using namespace std;
using namespace arma;

我已经使用犰狳几天了,并且运行了几个可以正常工作的矩阵操作。

输入:

mat A = randu<mat>(5,5);
A.print("A: ");
mat B = inv(A);
B.print("inv(A): ");

输出:

A: 
   0.0013   0.1741   0.9885   0.1662   0.8760
   0.1933   0.7105   0.1191   0.4508   0.9559
   0.5850   0.3040   0.0089   0.0571   0.5393
   0.3503   0.0914   0.5317   0.7833   0.4621
   0.8228   0.1473   0.6018   0.5199   0.8622
inv(A): 
   0.0013   0.1741   0.9885   0.1662   0.8760
   0.1933   0.7105   0.1191   0.4508   0.9559
   0.5850   0.3040   0.0089   0.0571   0.5393
   0.3503   0.0914   0.5317   0.7833   0.4621
   0.8228   0.1473   0.6018   0.5199   0.8622
Process finished with exit code 0

问题:

为什么 inv(ofAMatrix) 不起作用,有什么提示或想法吗? 谢谢!

【问题讨论】:

【参考方案1】:

这适用于带有 Intel (R) MKL 后端和 Clang 5.0 的 Armadillo 7.900.1。

除非绝对必要,否则永远不要取矩阵的逆。此外,您必须确保逆实际存在,否则算法将愉快地输出垃圾。如果你想计算 A 的逆以找到 x,如

x = A-1b

最好解线性系统

A x = b

相反。这些求解器速度更快,收敛性更好。

#include <armadillo>

int main()

  arma::mat A =   0.0013 , 0.1741 , 0.9885 , 0.1662 , 0.8760  ,
                   0.1933 , 0.7105 , 0.1191 , 0.4508 , 0.9559  ,
                   0.5850 , 0.3040 , 0.0089 , 0.0571 , 0.5393  ,
                   0.3503 , 0.0914 , 0.5317 , 0.7833 , 0.4621  ,
                   0.8228 , 0.1473 , 0.6018 , 0.5199 , 0.8622  ;
  A.print("A: ");
  arma::mat B = arma::inv(A);
  B.print("inv(A): ");
  arma::mat I = A*B;
  I.print("I: ");

输出:

A: 
   0.0013   0.1741   0.9885   0.1662   0.8760
   0.1933   0.7105   0.1191   0.4508   0.9559
   0.5850   0.3040   0.0089   0.0571   0.5393
   0.3503   0.0914   0.5317   0.7833   0.4621
   0.8228   0.1473   0.6018   0.5199   0.8622
inv(A): 
    0.4736   -1.7906    4.4377    2.2515   -2.4784
    2.9108   -3.1697   12.1159    7.7356  -11.1675
    2.5212   -2.8557    6.8074    4.7142   -6.1801
   -1.0317    0.9400   -2.3230    0.2413    1.3297
   -2.0869    3.6766   -9.6555   -6.9062    8.9447
I: 
   1.0000e+00   1.1340e-16  -1.8134e-15  -6.4918e-16  -4.8899e-17
   7.6334e-17   1.0000e+00  -9.1810e-16  -9.4668e-16   8.7907e-16
   2.5424e-16  -4.3981e-16   1.0000e+00   9.2981e-16  -2.0864e-15
   9.3036e-17  -2.6745e-17   7.5137e-16   1.0000e+00  -8.1372e-16
   4.3422e-16  -4.2293e-16   1.1321e-15   1.0687e-15   1.0000e+00

【讨论】:

感谢您这么快回复! 1.我不知道MKL是什么。 2. 我什至没有出错是不是很奇怪?可能是链接器/编译器问题吗?或者也许我错过了一个图书馆? 3. 不幸的是,我确实需要逆,而且我知道逆通常是一个瓶颈,谢谢! 请使用voting system 而不是发布“谢谢”。但无论如何,不​​客气:) MKL 是英特尔对 LAPACK 库的实现,对其处理器进行了特殊优化。这可以给你一些加速。此外,许多算法都是使用 OpenMP 并行实现的,这为您提供了额外的速度。【参考方案2】:

像他们一样“为我工作”。从 R 和 RcppArmadillo 驱动这个:

首先,我们读取矩阵并使用 MASS 包中的广义逆:

R> M <- as.matrix(read.table(text="0.0013   0.1741   0.9885   0.1662   0.8760
   0.1933   0.7105   0.1191   0.4508   0.9559
   0.5850   0.3040   0.0089   0.0571   0.5393
   0.3503   0.0914   0.5317   0.7833   0.4621
   0.8228   0.1473   0.6018   0.5199   0.8622"))
M <- as.matrix(read.table(text="0.0013   0.1741   0.9885   0.1662   0.8760
+    0.1933   0.7105   0.1191   0.4508   0.9559
+    0.5850   0.3040   0.0089   0.0571   0.5393
+    0.3503   0.0914   0.5317   0.7833   0.4621
+    0.8228   0.1473   0.6018   0.5199   0.8622"))
R> M
         V1     V2     V3     V4     V5
[1,] 0.0013 0.1741 0.9885 0.1662 0.8760
[2,] 0.1933 0.7105 0.1191 0.4508 0.9559
[3,] 0.5850 0.3040 0.0089 0.0571 0.5393
[4,] 0.3503 0.0914 0.5317 0.7833 0.4621
[5,] 0.8228 0.1473 0.6018 0.5199 0.8622
R> MASS::ginv(M)
          [,1]      [,2]     [,3]      [,4]      [,5]
[1,]  0.473579 -1.790599  4.43767  2.251542  -2.47842
[2,]  2.910752 -3.169657 12.11587  7.735612 -11.16755
[3,]  2.521167 -2.855651  6.80743  4.714239  -6.18015
[4,] -1.031667  0.940028 -2.32302  0.241345   1.32967
[5,] -2.086858  3.676647 -9.65548 -6.906203   8.94472
R> 

我们使用 RcppArmadillo:

R> Rcpp::cppFunction("arma::mat armaInv(arma::mat x)  return arma::inv(x); ", depends="RcppArmadillo")
R> armaInv(M)
          [,1]      [,2]     [,3]      [,4]      [,5]
[1,]  0.473579 -1.790599  4.43767  2.251542  -2.47842
[2,]  2.910752 -3.169657 12.11587  7.735612 -11.16755
[3,]  2.521167 -2.855651  6.80743  4.714239  -6.18015
[4,] -1.031667  0.940028 -2.32302  0.241345   1.32967
[5,] -2.086858  3.676647 -9.65548 -6.906203   8.94472
R> 

两种方式的答案相同。

【讨论】:

感谢您的快速回复,但我没有使用 R。 没关系。 Armadillo 代码是 Armadillo 代码,我只是从 R 中调用它,它们都使用相同的 LAPACK 后端。所以我给了你一个存在证明:犰狳没有问题,很可能是你需要解决的本地问题。 谢谢,我知道这是一个本地问题,我确定这不是犰狳问题,但我希望您能深入了解问题所在,谢谢! 从一个完整且可重复但最小的示例开始。我们没有你的代码。您没有显示如何编译和链接等 pp。

以上是关于犰狳 C++ 找不到矩阵逆的主要内容,如果未能解决你的问题,请参考以下文章

Armadillo C++ 和 BLAS 和 ATLAS 在 mingw32 下找不到 lapack blas

在 C++ 中存储大矩阵(犰狳)

C++犰狳稀疏矩阵类型转换

在 C++ 中返回多个矩阵(犰狳库)

C++:犰狳列矩阵初始化不明确

C++ 中矩阵的动态名称(犰狳库)