Fortran - результат обратной матрицы не совпадает, если десятичная дробь длиннее - PullRequest
0 голосов
/ 13 июня 2018

Мои настоящие данные - первый ввод, но обратный результат очень большой.Это те же данные, когда вы сравниваете с первым и вторым входом.Есть только разница десятичного размера.Почему есть другой результат?Потому что это одни и те же данные.Как они могут иметь другой результат?Вы можете увидеть результат и ввод.Это так странно.

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

1 Ответ

0 голосов
/ 13 июня 2018

Создание обратной матрицы не является сложной задачей.Я преобразовал ваш предыдущий пример в простой подход, основанный на исключении Гаусса с затененной матрицей тождества, который хорошо работает в большинстве случаев.Прикрепленная программа инвертирует вашу ранее симметричную матрицу, не прибегая к повороту строк.Для этого не нужен «черный ящик».

То, что вы получаете разные результаты с разными коэффициентами, вряд ли удивительно.С существенным изменением результатов для, по-видимому, небольших изменений входных значений, показывает чувствительность и, возможно, плохое согласование используемых соотношений уравнений.

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

Дополнительный ответ re "Первый ввод"

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

В этой последней ссылке (16-6) включены оба набора данных.В «Первом входе» ваши уравнения в основном являются строками 4: 6 и строками 1: 3 / 7.5 + small_noise.

В этом последнем примере кода есть проверки точности как во время инверсии матрицы, так и после нее.Во время проверочных проверок изменения строк корректны, тогда как последующими проверками являются «AA ^ -1 - I» и «A - (A ^ -1) ^ - 1», которые лучше указывают на низкую точность.

Интересно, что «Второй вход» (с большим количеством шума) сообщает о достаточно точном результате.Для того, чтобы получить обратный результат с 8-байтовыми реалами, нужна довольно надуманная матрица!Точно так же примеры полученных из случайных чисел коэффициентов показывают хорошую точность.

Эти примеры показывают, что тесты точности, которые я представил, не всегда идентифицируют плохо определенные отношения уравнения.Ваш инверсный анализ для выявления значительных отклонений в значениях также полезен.

Учитывая то, как, по-видимому, были определены уравнения, я не уверен, какого результата вы хотите.

...