使用MKL求解矩阵的行列式值与逆

      在FORTRAN下有很多求矩阵行列式值以及逆的方法,这些方法包括自己写程序求解,使用如IMSL和MKL等下面的库函数求解。一般来说,使用IMSL求解矩阵的行列式值和逆最简单且速度适中,但是IMSL现在属于商业库,如果程序自己用可以通过一些方法来免费使用 使用MKL求解矩阵的行列式值与逆 ,但是若涉及版权,买的话还是挺贵的。使用MKL的话,从在我电脑上的测试来看,速度最快,但是用起来稍微复杂一些,如果你是非商业目的(non-commercial)在Linux下是免费的。(注意非商业目的可能并不包括学术目的,这个可以在Intel的声明中查看)
      对于使用MKL来求解行列式以及矩阵逆实际操作起来并不复杂,但是对于这个方面的中文说明较少(我自己理解是大牛们都不屑与写这么简单的东西),我就把我最近写的一些东西分享出来。有些地方可能是粗浅且错误的,需要自己留意鉴别。
      先说行列式求解,对于这个问题,使用的sgetrf函数,这个函数是对矩阵进行LU分解,函数的命名规则是这样的,s代表single也就是单精度,ge代表一般矩阵,f代表factorization。函数的具体参数如下:

call sgetrf( m, n, a, lda, ipiv, info )

输入参数为以下:
m :代表输入矩阵a的行数
n :代表输入矩阵a的列数
a :代表输入矩阵
lda :就是矩阵a的第一个维度,一般是m
输出参数为:
a :被经过LU分解后的矩阵覆盖
ipiv : 是一个数组,维度一般是 max(1,min( m n )),具体英文说明是The pivot indices; for  1   i   min(m, n), row  i  was interchanged with row  ipiv(i).
info:执行标示符,成功是0,其他为失败标识,具体查看mkl帮助。
      行列式值的计算程序基本上就是在ipiv上做文章,我个人开始猜测它代表的是行之间的交换,交换一次行列式求解时要变号,于是便可以根据这个来进行行列式值的求解。
      现在以一个4*4维的矩阵为例,给出求解程序:
call sgetrf( n, n, a, n,ipiv,info)
res = 1d0
do i = 1,4
  if(ipiv(i) .ne. i) then
   res = -res*a(i,i)
  else
   res = res*a(i,i)
  end if
end do
其中,n=4。
      我多次验证过这个程序,没有发现问题,但是也不排除出问题的可能性,使用需谨慎,另外使用的时候最好写个function,把代码封装到function里面,在引用的时候调用这个function就可以了。
      现在再说矩阵求逆,我看到大部分矩阵求逆都是使用sgetrf + sgetri的组合来求解的,
      在实际应用中我发现,直接求逆时如果lwork这个参数设置不好的话可能得到的结果是错误的,这点我不知道为什么?所以一般来说我使用sgetrf + sgetrs来求解矩阵逆。在这里以n*n矩阵为例来说明下求解过程。
      关于sgetrf我在上面说过了,现在来说sgetrs这个函数:

call sgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info )


输入参数为以下:
trans :代表求解什么样的方程组,trans = 'N'代表求解 A*X  =  B
n :代表输入矩阵a的秩,一般就是行数
nrhs:一般代表B的行数,这里是n
a :代表输入矩阵
lda :就是矩阵a的第一个维度,这里是n
ldb :就是矩阵b的第一个维度,这里是n
ipiv:就是上面LU分解后输出的ipiv
输出参数为:
b :会被求解后的X所覆盖。
info:执行标示符,成功是0,其他为失败标识,具体查看mkl帮助。
      在这里,如果我把B设置为单位矩阵,那么X便是A矩阵的逆了,这样最终返回的B便会被X的值也就是A的逆所覆盖了,这样就成功的将A的逆求解出来了。具体的求解程序为:
call sgetrf( n, n, a, n,ipiv,info1)
call sgetrs( trans, n, nrhs, a, lda, ipiv, b, ldb, info2 )
输出的b便是a的逆,记得b要先设置成n*n的单位矩阵。
      求解矩阵的逆的时候我强烈建议你将他们封装到一个function中,然后再把这个function放到module中,便于主程序引用。我开始并没有把这两个函数放到function中,而是在程序中直接引用,从而造成了求解结果错误。我不知道这是为什么?可能是数据太大也可能是其他原因?我将这个问题反馈到了Intel论坛,只是现在没有得到答复。

你可能感兴趣的:(使用MKL求解矩阵的行列式值与逆)