为什么这个简单的 Fortran 矩阵反演代码没有返回 LAPACK 的预期值?

Why is this simple Fortran matrix inversion code not returning the expected value with LAPACK?

提问人:Leo 提问时间:5/17/2023 最后编辑:Leo 更新时间:5/17/2023 访问量:78

问:

我正在尝试使用LAPACK包来计算矩阵的逆函数。为此,我使用了例程 sgetrfsgetri。但是,在测试代码时,它不会返回反向的预期值,也不会返回(据我所知是)LU 分解的预期值。我用于反演的基本矩阵是任意的 4x4 矩阵。它是用 Fortran 90 编写的 Code::blocks 代码,并使用最新的 GNU 编译器和可用的 LAPACK 库。如果它完全相关,我正在使用 Windows 10。代码很简单,我相信直接在这里发布就足够了:

program test
    implicit none


    real, dimension(4,4)   :: R,R_inv


    integer                              :: info, ipiv
    real, dimension(4)                   :: lol


    R = reshape([real :: 1,0,0,0,          &
                         0,1.0/34.0,0,0,   &
                         0,0,1,2,          &
                         0,0,2,1]          &
                         ,shape(R), order = [2,1]                              )




R_inv = R
call sgetrf(4,4,R_inv,4,ipiv,info)

print *,info
print *, "_"
do pp = 1,4
print *, R_inv(pp,:)
end do
print *, "_"

call sgetri(2,R_inv,4,ipiv,lol,4,info)

print *,info
print *, "_"
print *, lol
print *, "_"
do pp = 1,4
print *, R_inv(pp,:)
end do
R_inv = matmul(R_inv,R)
print *, "_"
do pp = 1,4
print *, R_inv(pp,:)
end do
print *, "_"


end program 

到目前为止,这是我注意到的:

  • 第一个 info 输出返回 2。根据函数 sgetrf 的文档,这意味着因子 U(2,2) 正好是奇异的。但是,使用不同的 LU 因式分解计算器(例如 Matlab),我得到了有效(且不同)的因式分解结果。此外,我还使用在线计算器得到了不同的结果。该结果与通过Matlab获得的结果一致。

  • sgetri 函数似乎工作正常。

  • 如果矩阵是对角线的,则此代码工作正常。

  • LU 分解矩阵在对角线的前半部分似乎很好,但之后就变得很奇怪了。

  • 使用在线计算器和Matlab,矩阵R的逆矩阵存在并且没有明显的问题。也许负值以某种方式扰乱了问题?但我不知道为什么会这样。

  • 将值从实数切换到双精度并使用相应的 dgetrf 和 dgetri 例程对结果没有影响

总的来说,谁能说出这段代码有什么问题?关于例程的假设是错误的吗?我是否误解了我的结果应该是什么?如果是这样,如何在 Fortran 上使用 LAPACK 包计算逆数?

鉴于我对 Fortran 有点缺乏经验,我处理软件包安装和使用的方式可能会出现问题。如果这在您的机器上有效,请告诉我,因为我可能搞砸了那部分。

Fortran Fortran90 LAPACK 逆矩阵 分解

评论


答:

0赞 janneb 5/17/2023 #1

在使用 LAPACK 时出现两个错误:

  1. ipiv必须是 的整数数组,而不是标量。dimension(4)
  2. 在对 的调用中,第一个参数(矩阵顺序)应该是 4,而不是 2。sgetri

通过这些更改,矩阵反转可以正常工作。

但请注意,您的计算是以单精度(32 位浮点)完成的,而 matlab(可能还有您链接到的在线 LU 计算器)默认使用 64 位实数进行计算。因此,您的代码更容易出现精度问题,尤其是对于条件不佳的问题。

评论

0赞 Leo 5/17/2023
谢谢,奏效了!我完全误读了 IPIV 变量。我累了,只注意到“INTEGER”,错过了“array, dimension min(M,N)”。我想我会切换到更高精度的变量,我假设 Matlab 的默认大小与 Fortran 的“真实”大小相同,这有点牵强,不检查我现在意识到。