可能在大多数情况下得到的A会是一个规模较大且较为稀疏的矩阵。当然,这里可以自己写程序来求解,但能用经过验证的库岂不更好?UMPACK就是求解类似于Ax=b这样问题的一个库,来自佛罗里达州立大学。可以直接到http://www.cise.ufl.edu/research/sparse/umfpack/去下载对应的包然后编译得到Windows下的lib,包含到自己的工程就Okay了。原始文件需要对makefile编译生成lib,觉得不方便的话可以到这里下载已经生成好的。
关于它的使用就很简单了,package里边也有相应的doc可以参考,这里简单说明一下。一个最简单的使用程序如下:
#include "umfpack.h" int n = 5 ; int Ap [ ] = {0, 2, 5, 9, 10, 12} ; int Ai [ ] = { 0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4} ; double Ax [ ] = {2.0, 3.0, 3.0, -1.0, 4.0, 4.0, -3.0, 1.0, 2.0, 2.0, 6.0, 1.0} ; double b [ ] = {8.0, 45.0, -3.0, 3.0, 19.0} ; double x [5] ; int main() { double *null = (double *) NULL ; int i ; void *Symbolic, *Numeric ; (void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null) ; (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null) ; umfpack_di_free_symbolic (&Symbolic) ; (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null) ; umfpack_di_free_numeric (&Numeric) ; // ... 从x中得到最终的解并使用即可 return (0) ; }
其中对应的A原型为:
UMFPACK中求解各种Symboli以及Numeric我们就不需要关心了,主要来看一下UMFPack中矩阵的表示方法。一般情况下,对于大型的稀疏矩阵,采用压缩的方法来表示更能节省空间,UMFPACK里用的压缩方法也比较简单直白(UMFPACK采用列主的矩阵索引):
另外,注意函数umfpack_di_solve中使用的宏UMFPACK_A,它用来说明要求解的矩阵方程的类型,对应关系为:
UMFPACK_A: Ax = b
UMFPACK_At: A'x=b
UMFPAC_Aat: A.'x=b
...
其它更多的可以参考umfpack.h中的定义。
最后看一下效率:实际应用中解一个矩阵A的规模为4611x4611的方程,平均每行有七个左右的非0元素(最多9个;最少4个),UMFPACK对该方程的计算时间为0.025ms,性能还是蛮不错。