【问题标题】:Fortran- Inverse Matrix result not same if Decimal is longer如果十进制更长,Fortran-逆矩阵结果不同
【发布时间】:2018-06-13 09:21:06
【问题描述】:

我的真实数据是第一次输入,但结果的倒数太大了。当您与第一个和第二个输入进行比较时,它们是相同的数据。只有十进制大小不同。为什么会有不同的结果?因为它们是相同的数据。他们怎么会有不同的结果?您可以看到结果和输入。太奇怪了。

program test

Implicit none

double precision,allocatable,dimension(:,:)         :: A       
double precision,allocatable,dimension(:)           :: WORK
integer ,allocatable,dimension(:)       :: ipiv
integer                                 :: n,info,M
 external     DGETRF,DGETRI
M=8
allocate(A(M,M),WORK(M),IPIV(M))
!!! First Input !!!!
A(1,:)=(/3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
A(2,:)=(/0.0D0 , 3.740486048842566D-4, 0.0D0, 0.0D0, 4.987315029057229D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(3,:)=(/0.0D0 , 0.0D0 ,3.740486048842566D-4, 0.0D0 ,0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0/)
A(4,:)=(/4.987315029057229D-5 ,0.0D0 ,0.0D0 ,6.649753768432517D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
A(5,:)=(/0.0D0 , 4.987315029057229D-5, 0.0D0, 0.0D0 ,6.649753768432517D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
A(6,:)=(/0.0D0, 0.0D0, 4.987315029057229D-5, 0.0D0 ,0.0D0, 6.649753768432517D-6, 0.0D0 ,0.0D0 /)
A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.499999910593033D-11, 0.0D0 /)
A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.499999910593033D-11 /)
 !!!! Second Input !!!! 
!A(1,:)=(/3.74D-4, 0.0D0, 0.0D0, 4.98D-5, 0.0D0, 0.0D0, 0.0D0, 0.0D0/)
!A(2,:)=(/0.0D0 , 3.74D-4, 0.0D0, 0.0D0, 4.98D-5 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(3,:)=(/0.0D0 , 0.0D0 ,3.74D-4, 0.0D0 ,0.0D0, 4.98D-5, 0.0D0 ,0.0D0/)
!A(4,:)=(/4.98D-5 ,0.0D0 ,0.0D0 ,6.64D-6, 0.0D0 ,0.0D0, 0.0D0, 0.0D0 /)
!A(5,:)=(/0.0D0 , 4.98D-5, 0.0D0, 0.0D0 ,6.64D-6 ,0.0D0 ,0.0D0 ,0.0D0 /)
!A(6,:)=(/0.0D0, 0.0D0, 4.98D-5, 0.0D0 ,0.0D0, 6.64D-6, 0.0D0 ,0.0D0 /)
!A(7,:)=(/0.0D0, 0.0D0 ,0.0D0, 0.0D0 ,0.0D0 ,0.0D0 ,1.49D-11, 0.0D0 /)
!A(8,:)=(/0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0 ,0.0D0, 0.0D0 ,1.49D-11 /)


call DGETRF(M,M,A,M,IPIV,info)
if(info .eq. 0) then
Print *,'succeded'
else
Print *,'failed'
end if

call DGETRI(M,A,M,IPIV,WORK,M,info)
if(info .eq. 0) then
 Print *,'succeded'
else
Print *,'failed'
end if
Print *,A

deallocate(A,IPIV,WORK)

end 
!!!!! Second Input Result
!1.0e+10 *
! 0.0002     0       0   -0.0015       0      0        0   0
!     0      0.0002  0       0       -0.0015  0        0   0
!     0      0    0.0002     0         0     -0.0015   0   0
! -0.0015    0       0     0.0113      0      0        0   0
!     0     -0.0015  0       0       0.0113   0        0   0
!     0      0   -0.0015     0         0    0.0113     0   0
!     0      0       0       0         0      0     6.7114 0
!     0      0       0       0         0      0        0   6.7114

!!! First Input Result
!   1.0e+21 *

!-0.0238         0         0    0.1783         0         0         0         0
!     0   -0.0238         0         0    0.1783         0         0         0
!     0         0    0.0000         0         0   -0.0000         0         0
! 0.1783         0         0   -1.3375         0         0         0         0
!     0    0.1783         0         0   -1.3375         0         0         0
!     0         0   -0.0000         0         0    0.0000         0         0
!     0         0         0         0         0         0    0.0000         0
!     0         0         0         0         0         0         0    0.0000

【问题讨论】:

  • 你必须告诉我们它是什么意思“错误”。你的结果是什么?什么是正确的结果?尝试一个您知道确切解的简单矩阵,或者只是将您的结果与 Matlab 结果进行比较。但是给我们看看比较。
  • @VladimirF 谢谢我改了。问题是十进制大小。结果怎么改?
  • 但是应该是正确的结果吗?为什么你认为目前的结果是错误的?
  • 它们的数量相同,数量级几乎相同它们怎么可能不同?此外,差异是 10^10。
  • 几乎不一样,差别很大!

标签: matrix fortran fortran90 matrix-inverse fortran95


【解决方案1】:

创建矩阵逆不是一个难题。 我将您之前的示例转换为使用一种简单的方法,该方法基于带有阴影单位矩阵的高斯消元法,该方法适用于大多数情况。附加的程序会反转您之前的对称矩阵,而不需要对行进行旋转。它不需要“黑匣子”。

用不同的系数得到不同的结果并不奇怪。由于输入值的明显微小变化导致结果发生显着变化,表明您正在使用的方程关系的敏感性和可能较差的条件。

https://www.dropbox.com/s/ssotjx45yrz5sf9/dgetri.f90?dl=0

关于“第一个输入”的附加响应

https://www.dropbox.com/s/hximfoin977rmov/dgetri_piv4.f90?dl=0

此最新链接 (16-6) 包含两个数据集。在“第一个输入”中,您的方程式基本上是 4:6 行,即 1:3 / 7.5 + small_noise 行。

这个最新的代码示例在矩阵求逆期间和之后都进行了准确性检查。测试期间检查行更改是否正确,而后检查是“A.A^-1 - I”和“A - (A^-1)^-1”,这更好地表明准确性差。

有趣的是,“第二输入”(有更多噪音)报告了相当准确的结果。无法获得 8 字节实数的逆需要一个相当人为的矩阵!同样,随机数导出的系数示例也显示出良好的准确性。

这些示例表明,我提出的准确性测试并不总是能识别定义不明确的方程关系。您检查逆以识别值的大变化也很有用。

鉴于方程的定义方式,我不确定您想要的结果是什么。

【讨论】:

  • 感谢此代码。逆矩阵也是很好的例子。不需要使用黑盒:) 但我认为问题是ill-conditioned。因为,在我尝试获取 cholesky decomposition 之后,该矩阵是奇异的!
  • Cholesky 分解需要一个正定矩阵,因此可能具有限制性。您已经给出了多个示例矩阵,尽管我考虑的不是单数。我已经包含了部分旋转,这对于一般矩阵很有用,尽管我拥有的大多数实际矩阵都是对称且非奇异的。在 Fortran 90 之前,创建临时数组是一个问题,但因为大多数矩阵求逆都不是问题。倒置矩阵很方便,尤其是在最小二乘计算中。
  • 完全正确,cholesky 要求 posıtıve 确定,但矩阵不是 PD,所以我会检查 @kvantour 的评论。
  • @nobody 我使用 gFortran 7.2.0 64 位获得了 max error in A - (A^-1)^-1 = 1.9840899756484731E-017,使用 Silverfrost FTN95 32 位获得了max error in A - (A^-1)^-1 = 2.260561529632E-17
  • 我现在看了你的“第一个例子”:row_1 = 7.5 * row_4; row_2 = 7.5*row_5 & row_3 = 7.5*row_6,所以准确度测试显示有问题。包括这个数据集的新链接是link
猜你喜欢
  • 2021-02-23
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多