大矩阵求逆方法

时间:2010-07-28 20:24:13

标签: c++ algorithm math linear-algebra matrix-inverse

您好我一直在研究矩阵求逆(线性代数),我想对算法使用C ++模板编程,我发现有很多方法,如:Gauss-Jordan消除或LU分解我找到了函数LU_factorize(c ++ boost library)

  1. 我想从程序员或数学家的角度来了解是否有其他方法,哪一方更好(优点/缺点)?

  2. 如果没有其他更快的方法,那么在boost库中已经存在(矩阵)反转功能? ,因为我搜索了很多,但没有找到任何。

5 个答案:

答案 0 :(得分:5)

正如您所提到的,标准方法是执行LU分解,然后求解身份。这可以使用LAPACK库实现,例如,使用dgetrf(因子)和dgetri(计算逆)。大多数其他线性代数库具有大致相同的函数。

当矩阵是单数或近似单数时,有一些较慢的方法会更优雅地降级,并且由于这个原因而被使用。例如,如果矩阵是可逆的,则Moore-Penrose pseudoinverse等于逆,并且即使矩阵不可逆,通常也是有用的;它可以使用奇异值分解来计算。

答案 1 :(得分:3)

我建议您查看Eigen源代码。

答案 2 :(得分:2)

请在Google或维基百科下面的流行语。

首先,确保你真的想要逆。解决系统需要反转矩阵。可以通过求解n个系统来执行矩阵求逆,其中单位基矢量作为右手侧。所以我将专注于解决系统,因为它通常是你想要的。

这取决于“大”意味着什么。基于分解的方法通常必须存储整个矩阵。一旦分解了矩阵,就可以同时求解多个右侧(从而轻松地反转矩阵)。我不会在这里讨论分解方法,因为你可能已经知道了它们。

请注意,当矩阵很大时,其条件数很可能接近于零,这意味着矩阵“在数值上是不可逆的”。补救措施:预处理。检查维基百科。这篇文章写得很好。

如果矩阵很大,您不想存储它。如果它有很多零,那么它是稀疏矩阵。它有结构(例如带对角块矩阵,......),你有专门的方法来解决涉及这种矩阵的系统,或者它没有。< / p>

当你面对一个没有明显结构的稀疏矩阵,或者你不想存储的矩阵时,你必须使用迭代方法。它们只涉及矩阵向量乘法,它不需要特定的存储形式:您可以在需要时计算系数,或者按照您想要的方式存储非零系数等。

方法是:

  • 对称正定矩阵:共轭梯度法。简而言之,求解Ax = b的量最小化为1/2 x ^ T A x - x ^ T b。
  • 一般矩阵的Biconjugate梯度法。虽然不稳定。
  • 最小残留方法,或最佳,GMRES。有关详细信息,请查看维基百科文章。您可能希望在重新启动算法之前尝试迭代次数。

最后,您可以使用稀疏矩阵执行某种分解,使用专门设计的算法来最小化要存储的非零元素的数量。

答案 3 :(得分:1)

取决于矩阵实际上有多大,您可能需要在任何给定时间仅在内存中保留一小部分列。这可能需要覆盖对矩阵元素的低级写入和读取操作,我不确定Eigen是否是一个非常不错的库,它将允许你使用。

对于矩阵非常大的非常狭窄的情况,有StlXXL库设计用于内存访问主要存储在磁盘中的数组

编辑更准确地说,如果您的矩阵无法在可用内存中修复,首选方法是执行blockwise inversion。递归地分割矩阵,直到每个矩阵确实适合RAM(当然这是算法的调整参数)。这里棘手的部分是避免在矩阵的CPU被拉入和退出磁盘时使矩阵的CPU瘫痪。这可能需要在适当的并行文件系统中进行调查,因为即使使用StlXXL,这也可能是主要的瓶颈。虽然,让我重复一句口头禅; 过早优化是所有编程邪恶的根源。这种邪恶只能通过编码,执行和个人资料

的清洁仪式来消除

答案 4 :(得分:0)

您可能希望在LAPACK周围使用C ++包装器。 LAPACK是非常成熟的代码:经过充分测试,优化等等。

一个这样的包装器是Intel Math Kernel Library