LU分解求解線性代數方程組

!//---------------原方程-------------
!//     x + 2y - z = 3
!//    2x + y -2z = 3
!//    -3x + y + z = -6
!//----------------------------------
!// 本代實現了LU分解,但是並不是所有的矩陣都能進行LU分解
!// 後面會介紹PA=LU,可以解決所有問題
!// 爲什麼要進行LU分解
!// 使用LU分解方法代替高斯消去法的主要原因是由於如下系統的存在
!// Ax=B1, Ax=B2, Ax=B3,...,Ax=Bk。一般稱A爲結構矩陣
!// 經典高斯消去法對每一個Ax=B都要分解,但是因爲系統有相同的A,LU分解將Bk獨立出來,只進行一次LU分解即可
Module mod 
  Implicit none 
  Integer, parameter :: m = 3  !// 方程的階數
  Real(kind=8) :: a(m,m) = [ 1.d0, 2.d0, -3.d0, 2.d0, 1.d0, 1.d0, -1.d0, -2.d0, 1.d0 ]
  Real(kind=8) :: origin_b(m) = [ 3.d0, 3.d0, -6.d0 ] 
  Real(kind=8) :: c(m) = 0.d0, x(m) = 0.d0 
  Real(kind=8) :: U(m,m) = 0.d0, L(m,m) = 0.d0
  !// origin_b存放初始右端項,用來計算Lc = b,計算c
  !// 然後利用Ux = c,求解x
Contains
Subroutine GetLU ( )  
  Implicit none 
  Integer :: i, j, k 
  Real(kind=8), parameter :: eps = 1.d-5  !// 當主元小於這個數時,程序退出
  Real(kind=8) :: mult

  Write ( *,'(1x,a)' ) '原係數矩陣a爲:'
  Do i = 1, m 
    Write ( *,'(*(f12.5))' ) ( a(i,j), j = 1, m )
  End do 
  
  !// 對下三角矩陣對角線賦值
  forall ( i = 1:m, j = 1:m, i == j ) L(i,j) = 1.d0
  
  !// 計算上三角矩陣和下三角矩陣
  U = a
  Do j = 1, m - 1
    If ( abs(U(j,j)) < eps ) Then
      Write ( *,'(1x,a)' ) ' The pivot is zero!'
      stop 
    End if 
    Do i = j + 1, m
      mult = U(i,j) / U(j,j)
      L(i,j) = mult
      Do k = j, m 
        U(i,k) = U(i,k) - mult * U(j,k)
      End do 
    End do 
  End do 
  
  !// 得到上三角矩陣
  Write ( *,'(1x,a)' ) '上三角矩陣爲:'
  Do i = 1, m
    Write ( *,'(*(f12.5))' ) ( U(i,j), j = 1, m )
  End do
  
  Write ( *,'(1x,a)' ) '下三角矩陣爲:'
  Do i = 1, m
    Write ( *,'(*(f12.5))' ) ( L(i,j), j = 1, m )
  End do
  
End subroutine GetLU 

Subroutine BackSubstitution ( )
  Implicit none 
  Integer :: i, j 
  
  !// 求c: Lc = origin_b
  Do i = 1, m
    Do j = 1, i-1
      origin_b(i) = origin_b(i) - L(i,j) * c(j)
    End do 
    c(i) = origin_b(i) / L(i,i)
  End do
  
  !// 求x: Ux = c
  Do i = m, 1, -1
    Do j = i + 1, m 
      c(i) = c(i) - U(i,j) * x(j)
    End do 
    x(i) = c(i) / U(i,i)
  End do 
  
  Write ( *,'(1x,a)' ) '原方程解爲:'
  Do i = 1, m 
    Write ( *,'(f12.5)' ) x(i) 
  End do 
  
End subroutine BackSubstitution

End module mod 


Program LU_Factorization
  Use mod 
  Implicit none 
  call GetLU ( )
  call BackSubstitution ( )
End program LU_Factorization

!// 對另一方程組進行驗證。x=[1,2,3,4]  
!//---------------原方程-------------
!//     x + y + z + w = 10
!//    2x + 3y + z + w = 15
!//    3x - y + 2z - w = 3
!//    4x + y -3z + 2w = 5
!//----------------------------------
!Module mod 
!  Implicit none 
!  Integer, parameter :: m = 4  !// 方程的階數
!  Real(kind=8) :: a(m,m) = [ 1.d0, 2.d0, 3.d0, 4.d0, 1.d0, 3.d0, -1.d0, 1.d0, 1.d0, 1.d0, 2.d0, -3.d0, 1.d0, 1.d0, -1.d0, 2.d0 ]
!  Real(kind=8) :: origin_b(m) = [ 10.d0, 15.d0, 3.d0, 5.d0 ] 
!  Real(kind=8) :: c(m) = 0.d0, x(m) = 0.d0 
!  Real(kind=8) :: U(m,m) = 0.d0, L(m,m) = 0.d0
!  !// origin_b存放初始右端項,用來計算Lc = b,計算c
!  !// 然後利用Ux = c,求解x
!Contains
!Subroutine GetLU ( )  
!  Implicit none 
!  Integer :: i, j, k 
!  Real(kind=8), parameter :: eps = 1.d-5  !// 當主元小於這個數時,程序退出
!  Real(kind=8) :: mult
!
!  Write ( *,'(1x,a)' ) '原係數矩陣a爲:'
!  Do i = 1, m 
!    Write ( *,'(*(f12.5))' ) ( a(i,j), j = 1, m )
!  End do 
!  
!  !// 對下三角矩陣對角線賦值
!  forall ( i = 1:m, j = 1:m, i == j ) L(i,j) = 1.d0
!  
!  !// 計算上三角矩陣和下三角矩陣
!  U = a
!  Do j = 1, m - 1
!    If ( abs(U(j,j)) < eps ) Then
!      Write ( *,'(1x,a)' ) ' The pivot is zero!'
!      stop 
!    End if 
!    Do i = j + 1, m
!      mult = U(i,j) / U(j,j)
!      L(i,j) = mult
!      Do k = j, m 
!        U(i,k) = U(i,k) - mult * U(j,k)
!      End do 
!    End do 
!  End do 
!  
!  !// 得到上三角矩陣
!  Write ( *,'(1x,a)' ) '上三角矩陣爲:'
!  Do i = 1, m
!    Write ( *,'(*(f12.5))' ) ( U(i,j), j = 1, m )
!  End do
!  
!  Write ( *,'(1x,a)' ) '下三角矩陣爲:'
!  Do i = 1, m
!    Write ( *,'(*(f12.5))' ) ( L(i,j), j = 1, m )
!  End do
!  
!End subroutine GetLU 
!
!Subroutine BackSubstitution ( )
!  Implicit none 
!  Integer :: i, j 
!  
!  !// 求c: Lc = origin_b
!  Do i = 1, m
!    Do j = 1, i-1
!      origin_b(i) = origin_b(i) - L(i,j) * c(j)
!    End do 
!    c(i) = origin_b(i) / L(i,i)
!  End do
!  
!  !// 求x: Ux = c
!  Do i = m, 1, -1
!    Do j = i + 1, m 
!      c(i) = c(i) - U(i,j) * x(j)
!    End do 
!    x(i) = c(i) / U(i,i)
!  End do 
!  
!  Write ( *,'(1x,a)' ) '原方程解爲:'
!  Do i = 1, m 
!    Write ( *,'(f12.5)' ) x(i) 
!  End do 
!  
!End subroutine BackSubstitution
!
!End module mod 
!
!
!Program LU_Factorization
!  Use mod 
!  Implicit none 
!  call GetLU ( )
!  call BackSubstitution ( )
!End program LU_Factorization
!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章