LU分解で連立一次方程式を解いてみた。

#使用環境など
この記事ではWindows10にインストールしたmingw32-gfortranを使っています。
言語は、fortran95を使っています。

#LU分解とは
LU分というのは、行列Aを2つの行列LとUに分解することを言います。
これを用いることで、連立一次方程式の計算や行列式計算ができるようになります。
LU分解を使って連立一次方程式Ax=bを解くことのメリットとしては、一度AをLU分解をしたらそのAについての解をbの値を変えるだけで、解を求めることができます。

#LUを用いて連立一次方程式を解く方法
先ず、
$$ A\vec{x} = \vec{b} $$
をLU分解します。つまり、以下の式が求まります。
$$ LU\vec{x} = \vec{b} $$
この式を以下のように考えます。
$$ L\vec{y} = \vec{b} $$
$$ U\vec{x} = \vec{y} $$
下の式を上の式に代入することで、解を簡単に求めることができます。

#ソースコード
```fortran:LU_decomposition.f95
program main
	implicit none
	real(8), allocatable, dimension(:,:) :: a,L,U
	real(8), allocatable, dimension(:) :: b,x,y
	real(8) temp, alpha, reserve, sum1, sum2
	integer i, j, k, m, n, dim, maxline

	print *, 'input the number of dimension'
	read(*,*) dim
	allocate (a(dim, dim), b(dim), L(dim,dim), U(dim,dim),x(dim),y(dim))

!	Initialize ------------------------------------------------------
	a = 0.0
	b = 0.0
	L = 0.0
	U = 0.0

!	Input -----------------------------------------------------------
!	A
	do i = 1, dim
		do j = 1, dim
			print *,"x(",i,',',j,')'
			read *,a(i,j)
		end do
	end do
!	b
	do i = 1, dim
		print *,"b(",i,')'
		read *,b(i)
	end do

!	print the input -----------------------------------------------
	print *, 'A'
	do i = 1, dim
		print *, a(i, 1:dim)
	end do

	print *, 'B'
	print *, b(1:dim)

!	Solve the problem------------------------------------------------
!	LU --------------------------------------------------------------

	do k = 1, dim
		L(k,k) = 1.0
	end do

	do i = 1, dim
		do j = 1, dim
			if ( i .le. j ) then
				sum1 = 0.0
				do m = 1, i -1
					sum1 = sum1 + L(i,m) * U(m,j)
				end do
				U(i,j) = a(i,j) - sum1
			end if
			if (i .gt. j) then
				sum2 = 0.0
				do n = 1, j-1
					sum2 = sum2 + L(i,n) * U(n,j)
				end do
				L(i,j) = (a(i,j) - sum2) / U(j,j)
			end if
		end do
	end do

!	----------------------------------------------------------------

!	print for check-------------------------------------------------
	print *, 'L'
	do i = 1,dim
		print *, L(i,1:dim)
	end do

	print *, 'U'
	do i = 1, dim
		print *, U(i,1:dim)
	end do

!   solve the problem-----------------------------------------------
!   Ly=b------------------------------------------------------------
    do i = 1, dim
        y(i) = b(i)
    end do

	do j = 1, dim - 1
        do i = j + 1, dim
          y(i) = y(i) - y(j) * L(i,j)
        end do
    end do

!   Ux=y------------------------------------------------------------
    do i = 1, dim
        x(i) = y(i)
    end do

	do j = dim, 1, -1
        x(j) = x(j) / U(j,j)
        do i = 1, j - 1
          x(i) = x(i) - U(i,j) * x(j)
        end do
      end do
!   ----------------------------------------------------------------

!   print-----------------------------------------------------------
    print *, 'x'
    do i = 1, dim
		print *, x(i)
	end do
!   ----------------------------------------------------------------

	deallocate (a,b,L,U,x,y)
end
```

#実行結果
```cmd:LUdecomposition.exe
 input the number of dimension
2
 x(           1 ,           1 )
1
 x(           1 ,           2 )
2
 x(           2 ,           1 )
3
 x(           2 ,           2 )
1
 b(           1 )
2
 b(           2 )
1
 A
   1.0000000000000000        2.0000000000000000
   3.0000000000000000        1.0000000000000000
 B
   2.0000000000000000        1.0000000000000000
 L
   1.0000000000000000        0.0000000000000000
   3.0000000000000000        1.0000000000000000
 U
   1.0000000000000000        2.0000000000000000
   0.0000000000000000       -5.0000000000000000
 x
   0.0000000000000000
   1.0000000000000000
```

参考文献：
「物理のかぎしっぽ」http://hooktail.org/computer/index.php?LU%CA%AC%B2%F2
「numerical algorithms group」http://www.nag-j.co.jp/fortran/