не Там будет не встроенная команда, которая соответствует lu
в Matlab, но мы можем написать простую обертку для dgetrf
в LAPACK, так что интерфейс похож на lu
, например,
module linalg
implicit none
integer, parameter :: dp = kind(0.0d0)
contains
subroutine lufact(A, L, U, P)
!... P * A = L * U
!... http://www.netlib.org/lapack/explore-3.1.1-html/dgetrf.f.html
!... (note that the definition of P is opposite to that of the above page)
real(dp), intent(in) :: A(:,:)
real(dp), allocatable, dimension(:,:) :: L, U, P
integer, allocatable :: ipiv(:)
real(dp), allocatable :: row(:)
integer :: i, n, info
n = size(A, 1)
allocate(L(n, n), U(n, n), P(n, n), ipiv(n), row(n))
L = A
call DGETRF(n, n, L, n, ipiv, info)
if (info /= 0) stop "lufact: info /= 0"
U = 0.0d0
P = 0.0d0
do i = 1, n
U(i, i:n) = L(i, i:n)
L(i, i:n) = 0.0d0
L(i, i) = 1.0d0
P(i, i) = 1.0d0
enddo
!... Assuming that P = P[ipiv(n),n] * ... * P[ipiv(1),1]
!... where P[i,j] is a permutation matrix for i- and j-th rows.
do i = 1, n
row = P(i, :)
P(i, :) = P(ipiv(i), :)
P(ipiv(i), :) = row
enddo
endsubroutine
end module
Тогда мы может проверить процедуру с матрицей 3х3, показанной на странице Matlab для лу():
program test_lu
use linalg
implicit none
real(dp), allocatable, dimension(:,:) :: A, L, U, P
allocate(A(3, 3))
A(1, :) = [ 1, 2, 3 ]
A(2, :) = [ 4, 5, 6 ]
A(3, :) = [ 7, 8, 0 ]
call lufact(A, L, U, P) !<--> [L,U,P] = lu(A) in Matlab
call show("A =", A)
call show("L =", L)
call show("U =", U)
call show("P =", P)
call show("P * A =", matmul(P, A))
call show("L * U =", matmul(L, U))
call show("P' * L * U =", matmul(transpose(P), matmul(L, U)))
contains
subroutine show(msg, X)
character(*) :: msg
real(dp) :: X(:,:)
integer i
print "(/,a)", trim(msg)
do i = 1, size(X,1)
print "(*(f8.4))", X(i, :)
enddo
endsubroutine
end program
который дает ожидаемый результат:
A =
1.0000 2.0000 3.0000
4.0000 5.0000 6.0000
7.0000 8.0000 0.0000
L =
1.0000 0.0000 0.0000
0.1429 1.0000 0.0000
0.5714 0.5000 1.0000
U =
7.0000 8.0000 0.0000
0.0000 0.8571 3.0000
0.0000 0.0000 4.5000
P =
0.0000 0.0000 1.0000
1.0000 0.0000 0.0000
0.0000 1.0000 0.0000
P * A =
7.0000 8.0000 0.0000
1.0000 2.0000 3.0000
4.0000 5.0000 6.0000
L * U =
7.0000 8.0000 0.0000
1.0000 2.0000 3.0000
4.0000 5.0000 6.0000
P' * L * U =
1.0000 2.0000 3.0000
4.0000 5.0000 6.0000
7.0000 8.0000 0.0000
Здесь обратите внимание, что инверсия P
задается ее транспонированием (т. Е. inv(P) = P' = transpose(P)
), поскольку P
является произведением (элементарных) матриц перестановок.
Что вы хотите сказать? Почему DGBTRF не подходит для LAPACK? –
Мой вопрос: Есть ли команда или подпрограмма, которая имеет в качестве входных данных квадратную матрицу A и выводит матрицы L и U факторизации LU? Я не знал о DGBTRF. Я попытаюсь использовать это. Тем не менее, это немного надуманно для моей конкретной пурпуры. Что-то простое, как MatLab's [L, U] = lu (A) было бы лучше, нет? Я не вижу, как хранение матриц L и U в одном и том же массиве является преимуществом (это то, что сделано, в соответствии с документацией, которую я только что искал) – Qwertuy
Это преимущество, потому что вы сохраняете много Память. Кстати, нахождение DGBTRF заняло у меня менее минуты за счет googling «LAPACK LU». –