가우스 소거법으로 역행렬 구하는 알고리즘
📂행렬대수 가우스 소거법으로 역행렬 구하는 알고리즘 알고리즘 Input
가역행렬 M ∈ R n × n M \in \mathbb{R}^{n \times n} M ∈ R n × n 이 주어져 있다고 하자.
Step 1. 초기화
M M M 과 같은 사이즈의 항등행렬 X X X 를 만든다.
Step 2. 에쉘론 폼
가우스 소거법을 통해 M M M 을 에쉘론 폼으로 만든다. 원래 에쉘론 폼이라고 하면 상삼각행렬 의 꼴이면 충분하지만, 역행렬 계산 알고리즘에서는 그냥 대각행렬 까지 계산한다. 단, 이 때 M M M 에 취해지는 행연산을 X X X 에도 똑같이 취한다.
Output
M X = X M = E n MX = XM = E_{n} MX = XM = E n 을 만족하는, 즉 M M M 의 역행렬인 X X X 를 얻는다.
예시 구구절절 설명을 듣는 것보다 예시 하나를 보는 게 낫다.
Input
행렬 M = [ 1 0 1 1 2 0 1 0 − 2 3 4 0 − 5 5 6 0 ] M = \begin{bmatrix} 1 & 0 & 1 & 1\\ 2 & 0 & 1 & 0\\ -2& 3 & 4 & 0\\ -5& 5 & 6 & 0\end{bmatrix} M = 1 2 − 2 − 5 0 0 3 5 1 1 4 6 1 0 0 0 이 주어져 있다고 하자.
Step 1. 초기화
[ 1 0 1 1 2 0 1 0 − 2 3 4 0 − 5 5 6 0 ] ⋯ [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ]
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 2 & 0 & 1 & 0
\\ -2& 3 & 4 & 0
\\ -5& 5 & 6 & 0
\end{bmatrix} \cdots \begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 1 & 0 & 0
\\ 0 & 0 & 1 & 0
\\ 0 & 0 & 0 & 1
\end{bmatrix}
1 2 − 2 − 5 0 0 3 5 1 1 4 6 1 0 0 0 ⋯ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
주어진 행렬과 같은 사이즈의 항등행렬을 만든다. 위에서 좌측이 M M M , 우측이 후에 역행렬이 될 X X X 다.
Step 2. 에쉘론 폼
엄밀히 따졌을 때, 이 포스트에서 소개하는 방법으로 에쉘론 폼을 만들지는 않는다. 계산의 편의를 위해 대각행렬 을 먼저 만들고, 각 행을 피벗으로 나눌 것이다.
[ 1 0 1 1 2 0 1 0 − 2 3 4 0 − 5 5 6 0 ] ⋯ [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] → [ 1 0 1 1 0 0 − 1 − 2 0 3 6 2 0 5 11 5 ] ⋯ [ 1 0 0 0 − 2 1 0 0 2 0 1 0 5 0 0 1 ]
\begin{align*}
& \begin{bmatrix}
1 & 0 & 1 & 1
\\ 2 & 0 & 1 & 0
\\ -2& 3 & 4 & 0
\\ -5& 5 & 6 & 0
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 1 & 0 & 0
\\ 0 & 0 & 1 & 0
\\ 0 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 0 & -1 & -2
\\ 0 & 3 & 6 & 2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ -2 & 1 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\end{align*}
→ 1 2 − 2 − 5 0 0 3 5 1 1 4 6 1 0 0 0 1 0 0 0 0 0 3 5 1 − 1 6 11 1 − 2 2 5 ⋯ ⋯ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 − 2 2 5 0 1 0 0 0 0 1 0 0 0 0 1
M M M 에 행연산을 취하면서 X X X 에도 똑같이 취한다는 것은 것은 위와 같이 M M M 의 첫번째 행에 − 2 , 2 , 5 -2, 2, 5 − 2 , 2 , 5 를 곱해 두번째, 세번째, 네번째 행에 더하는 연산을 X X X 에서도 똑같이 한다는 것이다.
[ 1 0 1 1 0 0 − 1 − 2 0 3 6 2 0 5 11 5 ] ⋯ [ 1 0 0 0 − 2 1 0 0 2 0 1 0 5 0 0 1 ] → [ 1 0 1 1 0 3 6 2 0 0 − 1 − 2 0 5 11 5 ] ⋯ [ 1 0 0 0 2 0 1 0 − 2 1 0 0 5 0 0 1 ]
\begin{align*}
& \begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 0 & -1 & -2
\\ 0 & 3 & 6 & 2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ -2 & 1 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 3 & 6 & 2
\\ 0 & 0 & -1 & -2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\end{align*}
→ 1 0 0 0 0 0 3 5 1 − 1 6 11 1 − 2 2 5 1 0 0 0 0 3 0 5 1 6 − 1 11 1 2 − 2 5 ⋯ ⋯ 1 − 2 2 5 0 1 0 0 0 0 1 0 0 0 0 1 1 2 − 2 5 0 0 1 0 0 1 0 0 0 0 0 1
피벗pivot 이 0 0 0 인 경우, 즉 M i i = 0 M_{ii} = 0 M ii = 0 이면 M j i ≠ 0 M_{ji} \ne 0 M ji = 0 인 j j j 번째 행과 i i i 번째 행을 서로 바꾼다. M j i ≠ 0 M_{ji} \ne 0 M ji = 0 를 만족하는 j j j 행의 존재성은 M M M 이 가역행렬이라는 가정에 의해 보장된다. 당연히 이 행교환 연산 역시 X X X 에 똑같이 취해주어야한다.
[ 1 0 1 1 0 3 6 2 0 0 − 1 − 2 0 5 11 5 ] ⋯ [ 1 0 0 0 2 0 1 0 − 2 1 0 0 5 0 0 1 ] → [ 1 0 1 1 0 3 6 2 0 0 − 1 − 2 0 0 1 5 / 3 ] ⋯ [ 1 0 0 0 2 0 1 0 − 2 1 0 0 5 / 3 0 − 5 / 3 1 ] → [ 1 0 0 1 0 3 0 − 10 0 0 − 1 − 2 0 0 0 − 1 / 3 ] ⋯ [ − 1 1 0 0 − 10 6 1 0 − 2 1 0 0 − 1 / 3 1 − 5 / 3 1 ] → [ 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1 / 3 ] ⋯ [ 0 − 2 5 − 3 0 − 24 51 − 30 0 − 5 10 − 6 − 1 / 3 1 − 5 / 3 1 ]
\begin{align*}
& \begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 3 & 6 & 2
\\ 0 & 0 & -1 & -2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 3 & 6 & 2
\\ 0 & 0 & -1 & -2
\\ 0 & 0 & 1 & 5/3
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ 5/3 & 0 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 1
\\ 0 & 3 & 0 & -10
\\ 0 & 0 & -1 & -2
\\ 0 & 0 & 0 & -1/3
\end{bmatrix} & \cdots & \begin{bmatrix}
-1 & 1 & 0 & 0
\\ -10 & 6 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ -1/3 & 1 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 3 & 0 & 0
\\ 0 & 0 & -1 & 0
\\ 0 & 0 & 0 & -1/3
\end{bmatrix} & \cdots & \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -24 & 51 & -30
\\ 0 & -5 & 10 & -6
\\ -1/3 & 1 & -5/3 & 1
\end{bmatrix}
\end{align*}
→ → → 1 0 0 0 0 3 0 5 1 6 − 1 11 1 2 − 2 5 1 0 0 0 0 3 0 0 1 6 − 1 1 1 2 − 2 5/3 1 0 0 0 0 3 0 0 0 0 − 1 0 1 − 10 − 2 − 1/3 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1/3 ⋯ ⋯ ⋯ ⋯ 1 2 − 2 5 0 0 1 0 0 1 0 0 0 0 0 1 1 2 − 2 5/3 0 0 1 0 0 1 0 − 5/3 0 0 0 1 − 1 − 10 − 2 − 1/3 1 6 1 1 0 1 0 − 5/3 0 0 0 1 0 0 0 − 1/3 − 2 − 24 − 5 1 5 51 10 − 5/3 − 3 − 30 − 6 1
M M M 이 대각행렬 이 될 때까지 반복한다. 원래는 상삼각행렬의 꼴로 만든 후 행을 피벗으로 나누어 에쉘론 폼으로 만든 후, 다른 행의 피벗 이후 성분들을 소거시키는 식으로 하지만 코드 작성에서 번거롭기 때문에 그냥 순서를 바꾼 것이다. 이렇게 순서를 바꿔도 무방한 이유는 가우스 소거법의 이론적인 배경에서 찾을 수 있다.
[ 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1 / 3 ] ⋯ [ 0 − 2 5 − 3 0 − 24 51 − 30 0 − 5 10 − 6 − 1 / 3 1 − 5 / 3 1 ] → [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] ⋯ [ 0 − 2 5 − 3 0 − 8 17 − 10 0 5 − 10 6 1 − 3 5 − 3 ]
\begin{align*}
& \begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 3 & 0 & 0
\\ 0 & 0 & -1 & 0
\\ 0 & 0 & 0 & -1/3
\end{bmatrix} & \cdots & \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -24 & 51 & -30
\\ 0 & -5 & 10 & -6
\\ -1/3 & 1 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 1 & 0 & 0
\\ 0 & 0 & 1 & 0
\\ 0 & 0 & 0 & 1
\end{bmatrix} & \cdots & \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -8 & 17 & -10
\\ 0 & 5 & -10 & 6
\\ 1 & -3 & 5 & -3
\end{bmatrix}
\end{align*}
→ 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1/3 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ⋯ ⋯ 0 0 0 − 1/3 − 2 − 24 − 5 1 5 51 10 − 5/3 − 3 − 30 − 6 1 0 0 0 1 − 2 − 8 5 − 3 5 17 − 10 5 − 3 − 10 6 − 3
대각행렬을 완성했다면 각 행을 각각의 피벗으로 나누어준다. 이제 M M M 은 항등행렬의 꼴이어야한다.
Output
X = [ 0 − 2 5 − 3 0 − 8 17 − 10 0 5 − 10 6 1 − 3 5 − 3 ]
X = \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -8 & 17 & -10
\\ 0 & 5 & -10 & 6
\\ 1 & -3 & 5 & -3
\end{bmatrix}
X = 0 0 0 1 − 2 − 8 5 − 3 5 17 − 10 5 − 3 − 10 6 − 3
X X X 는 M M M 의 역행렬이다. 지금까지의 과정를 요약하면 다음과 같다.
[ 1 0 1 1 2 0 1 0 − 2 3 4 0 − 5 5 6 0 ] ⋯ [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] → [ 1 0 1 1 0 0 − 1 − 2 0 3 6 2 0 5 11 5 ] ⋯ [ 1 0 0 0 − 2 1 0 0 2 0 1 0 5 0 0 1 ] → [ 1 0 1 1 0 3 6 2 0 0 − 1 − 2 0 5 11 5 ] ⋯ [ 1 0 0 0 2 0 1 0 − 2 1 0 0 5 0 0 1 ] → [ 1 0 1 1 0 3 6 2 0 0 − 1 − 2 0 0 1 5 / 3 ] ⋯ [ 1 0 0 0 2 0 1 0 − 2 1 0 0 5 / 3 0 − 5 / 3 1 ] → [ 1 0 0 1 0 3 0 − 10 0 0 − 1 − 2 0 0 0 − 1 / 3 ] ⋯ [ − 1 1 0 0 − 10 6 1 0 − 2 1 0 0 − 1 / 3 1 − 5 / 3 1 ] → [ 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1 / 3 ] ⋯ [ 0 − 2 5 − 3 0 − 24 51 − 30 0 − 5 10 − 6 − 1 / 3 1 − 5 / 3 1 ] → [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] ⋯ [ 0 − 2 5 − 3 0 − 8 17 − 10 0 5 − 10 6 1 − 3 5 − 3 ]
\begin{align*}
& \begin{bmatrix}
1 & 0 & 1 & 1
\\ 2 & 0 & 1 & 0
\\ -2& 3 & 4 & 0
\\ -5& 5 & 6 & 0
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 1 & 0 & 0
\\ 0 & 0 & 1 & 0
\\ 0 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 0 & -1 & -2
\\ 0 & 3 & 6 & 2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ -2 & 1 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 3 & 6 & 2
\\ 0 & 0 & -1 & -2
\\ 0 & 5 & 11 & 5
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ 5 & 0 & 0 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 1 & 1
\\ 0 & 3 & 6 & 2
\\ 0 & 0 & -1 & -2
\\ 0 & 0 & 1 & 5/3
\end{bmatrix} & \cdots & \begin{bmatrix}
1 & 0 & 0 & 0
\\ 2 & 0 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ 5/3 & 0 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 1
\\ 0 & 3 & 0 & -10
\\ 0 & 0 & -1 & -2
\\ 0 & 0 & 0 & -1/3
\end{bmatrix} & \cdots & \begin{bmatrix}
-1 & 1 & 0 & 0
\\ -10 & 6 & 1 & 0
\\ -2 & 1 & 0 & 0
\\ -1/3 & 1 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 3 & 0 & 0
\\ 0 & 0 & -1 & 0
\\ 0 & 0 & 0 & -1/3
\end{bmatrix} & \cdots & \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -24 & 51 & -30
\\ 0 & -5 & 10 & -6
\\ -1/3 & 1 & -5/3 & 1
\end{bmatrix}
\\ \to &
\begin{bmatrix}
1 & 0 & 0 & 0
\\ 0 & 1 & 0 & 0
\\ 0 & 0 & 1 & 0
\\ 0 & 0 & 0 & 1
\end{bmatrix} & \cdots & \begin{bmatrix}
0 & -2 & 5 & -3
\\ 0 & -8 & 17 & -10
\\ 0 & 5 & -10 & 6
\\ 1 & -3 & 5 & -3
\end{bmatrix}
\end{align*}
→ → → → → → 1 2 − 2 − 5 0 0 3 5 1 1 4 6 1 0 0 0 1 0 0 0 0 0 3 5 1 − 1 6 11 1 − 2 2 5 1 0 0 0 0 3 0 5 1 6 − 1 11 1 2 − 2 5 1 0 0 0 0 3 0 0 1 6 − 1 1 1 2 − 2 5/3 1 0 0 0 0 3 0 0 0 0 − 1 0 1 − 10 − 2 − 1/3 1 0 0 0 0 3 0 0 0 0 − 1 0 0 0 0 − 1/3 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 − 2 2 5 0 1 0 0 0 0 1 0 0 0 0 1 1 2 − 2 5 0 0 1 0 0 1 0 0 0 0 0 1 1 2 − 2 5/3 0 0 1 0 0 1 0 − 5/3 0 0 0 1 − 1 − 10 − 2 − 1/3 1 6 1 1 0 1 0 − 5/3 0 0 0 1 0 0 0 − 1/3 − 2 − 24 − 5 1 5 51 10 − 5/3 − 3 − 30 − 6 1 0 0 0 1 − 2 − 8 5 − 3 5 17 − 10 5 − 3 − 10 6 − 3
코드 다음은 가우스 소거법 으로 역행렬을 구하는 줄리아 코드다.
using LinearAlgebra
M = [
1 0 1 1
2 0 1 0
-2 3 4 0
-5 5 6 0
]
inv_M = inv(M)
n = size(M)[1 ]
M = Float64 .(M)
X = Matrix (1.0 I,n,n)
for j = 1 :n
if iszero(M[j,j])
for i = j:n
if !iszero(M[i,i])
M[[j,i],:] = M[[i,j],:]
X[[j,i],:] = X[[i,j],:]
break
end
end
end
pivot = M[j,j]
for i = 1 :n
if i == j continue end
r = (- M[i,j] / pivot)
M[i,:] += r*M[j,:]
X[i,:] += r*X[j,:]
end
end
for i = 1 :n
pivot = M[i,i]
M[i,:] /= pivot
X[i,:] /= pivot
end
M
X
inv_M