\(LU\)分解は、方程式\(Ax = b\)の解を計算に工夫が必要な逆行列を求める方法でなく、機械的に簡単な計算で求められる方法です。
ではどのように\(A = LU\)へと分解するのか、具体的に計算を行いながら分解アルゴリズムを見てみましょう。Pivot付きの計算も行うので少し複雑ですが、実装してみれば簡単なことが分かります。
LU分解の基本的な方法
まずは基本的な行列で\(LU\)分解を行ってみます。
\(A = LU \)の行列を(1)式のように置いて考えます。
$$
\left(\begin{array}{cccc}
a_{11} & a_{12} & a_{13} & a_{14} \\
a_{21} & a_{22} & a_{23} & a_{24} \\
a_{31} & a_{32} & a_{33} & a_{34} \\
a_{41} & a_{42} & a_{43} & a_{44}
\end{array}\right) =
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
l_{21} & 1 & 0 & 0 \\
l_{31} & l_{32} & 1 & 0 \\
l_{41} & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14} \\
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{1}
$$
1段目
この(1)式のA行列の1行目の計算から、
$$
\left(\begin{array}{cccc}
a_{11} & a_{12} & a_{13} & a_{14} \\
\hline
a_{21} & a_{22} & a_{23} & a_{24} \\
a_{31} & a_{32} & a_{33} & a_{34} \\
a_{41} & a_{42} & a_{43} & a_{44}
\end{array}\right) =
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
\hline
l_{21} & 1 & 0 & 0 \\
l_{31} & l_{32} & 1 & 0 \\
l_{41} & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|c|c|c}
u_{11} & u_{12} & u_{13} & u_{14} \\
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right)
$$
U行列の1行目は(2)式のように求まります。
$$
\begin{eqnarray}
a_{11} &=& u_{11} \\
a_{12} &=& u_{12} \\
a_{13} &=& u_{13} \\
a_{14} &=& u_{14}
\end{eqnarray} \tag{2}
$$
続いてA行列の1列目から
$$
\left(\begin{array}{c|ccc}
a_{11} & a_{12} & a_{13} & a_{14} \\
a_{21} & a_{22} & a_{23} & a_{24} \\
a_{31} & a_{32} & a_{33} & a_{34} \\
a_{41} & a_{42} & a_{43} & a_{44}
\end{array}\right) =
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\ \hline
l_{21} & 1 & 0 & 0 \\ \hline
l_{31} & l_{32} & 1 & 0 \\ \hline
l_{41} & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
u_{11} & u_{12} & u_{13} & u_{14} \\
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right)
$$
L行列の1列目は(3)式のように求まります。
$$
\begin{eqnarray}
a_{11} = l_{11} u_{11} &\Rightarrow& l_{11} = a_{11} / u_{11} = 1 \\
a_{21} = l_{21} u_{11} &\Rightarrow& l_{21} = a_{21} / u_{11} \\
a_{31} = l_{31} u_{11} &\Rightarrow& l_{31} = a_{31} / u_{11} \\
a_{41} = l_{41} u_{11} &\Rightarrow& l_{41} = a_{41} / u_{11}
\end{eqnarray} \tag{3}
$$
ここで\(l_1, u_1\)を(4)式のように定義すると
$$
l_1 = (1, l_{21}, l_{31}, l_{41})^T, u_1 = (u_{11}, u_{12}, u_{13}, u_{14}) \tag{4}
$$
\(l_1 u_1\)は(5)式となるので、
$$
\begin{eqnarray}
l_1 u_1 &=&
\left(\begin{array}{c}
1 \\ l_{21} \\ l_{31} \\ l_{41}
\end{array}\right)
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14}
\end{array}\right) \\ &=&
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14} \\
l_{21} u_{11} & l_{21} u_{12} & l_{21} u_{13} & l_{21} u_{14} \\
l_{31} u_{11} & l_{31} u_{12} & l_{31} u_{13} & l_{31} u_{14} \\
l_{41} u_{11} & l_{41} u_{12} & l_{41} u_{13} & l_{41} u_{14}
\end{array}\right)\\ &=&
\left(\begin{array}{cccc}
a_{11} & a_{12} & a_{13} & a_{14} \\
a_{21} & l_{21} u_{12} & l_{21} u_{13} & l_{21} u_{14} \\
a_{31} & l_{31} u_{12} & l_{31} u_{13} & l_{31} u_{14} \\
a_{41} & l_{41} u_{12} & l_{41} u_{13} & l_{41} u_{14}
\end{array}\right)
\end{eqnarray} \tag{5}
$$
\(A – l_1 u_1 = A_{(2)}\)として、\(A_{(2)}\)は(6)式となります。
$$
A_{(2)} =
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & a_{22(2)} & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) \tag{6}
$$
以上の関係から\(A = A_{(1)}\)として、\(A_{(1)} = l_1 u_1 + A_{(2)}\)となります。
2段目
\(A_{(2)}\)は\(A_{(1)}\)から一つ縮小した関係なので、これをさらにLU分解を行います。\(A_{(2)}\)より、LUも(7)式のように一つ縮小した形を考えます。
$$
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & a_{22(2)} & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right)=
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 1 & 0 & 0 \\
0 & l_{32} & 1 & 0 \\
0 & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{7}
$$
この(7)式より、1段目と同じようにU行列の2行目は(8)式、L行列の2列目は(9)式のように求まります。
$$
\begin{eqnarray}
a_{22(2)} &=& u_{22} \\
a_{23(2)} &=& u_{23} \\
a_{24(2)} &=& u_{24}
\end{eqnarray} \tag{8}
$$
$$
\begin{eqnarray}
a_{22(2)} = l_{22} u_{22} &\Rightarrow& l_{22} = a_{22(2)} / u_{22} = 1 \\
a_{32(2)} = l_{32} u_{22} &\Rightarrow& l_{32} = a_{32(2)} / u_{22} \\
a_{42(2)} = l_{42} u_{22} &\Rightarrow& l_{42} = a_{42(2)} / u_{22}
\end{eqnarray} \tag{9}
$$
ここで、\(l_2, u_2\)を(10)式のように定義して、
$$
l_2 = (0, 1, l_{32}, l_{42})^T, u_1 = (0, u_{22}, u_{23}, u_{24}) \tag{10}
$$
\(A_{(2)} – l_2 u_2 = A_{(3)}\)とすると\(A_{(3)}\)は(11)式のよう一つ縮小した形になります。
$$
A_{(3)} =
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{33(3)} & a_{34(3)} \\
0 & 0 & a_{43(3)} & a_{44(3)}
\end{array}\right) \tag{11}
$$
\(A_{(2)} = l_2 u_2 + A_{(3)}\)より、\(A_{(1)} = l_1 u_1 + l_2 u_2 + A_{(3)}\)という関係になります。
3段目
\(A_{(2)}\)から一つ縮小した\(A_{(3)}\)をさらにLU分解を行います。\(A_{(3)}\)の関係から\(LU\)行列も(12)式のようになります。
$$
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{33(3)} & a_{34(3)} \\
0 & 0 & a_{43(3)} & a_{44(3)}
\end{array}\right)=
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 1 & 0 \\
0 & 0 & l_{43} & 1
\end{array}\right)
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{12}
$$
(12)式の関係から\(U\)行列の3行目は(13)式、\(L\)行列の3列目は(14)式のよう求まります。
$$
\begin{eqnarray}
a_{33(3)} &=& u_{33} \\
a_{34(3)} &=& u_{34}
\end{eqnarray} \tag{13}
$$
$$
\begin{eqnarray}
a_{33(3)} = l_{33} u_{33} &\Rightarrow& l_{33} = a_{33(3)} / u_{33} = 1 \\
a_{43(3)} = l_{43} u_{33} &\Rightarrow& l_{43} = a_{43(3)} / u_{33}
\end{eqnarray} \tag{14}
$$
ここで、\(l_3, u_3\)を(15)式のように定義して、
$$
l_3 = (0, 0 , 1 , l_{43}) ^T , u_3 = (0, 0 , u_{33}, u_{34}) \tag{15}
$$
\(A_{(3)} – l_3 u_3 = A_{(4)}\)とすると\(A_{(4)}\)は(16)式のように一つ縮小した形になります。
$$
A_{(4)} =
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & a_{44(4)}
\end{array}\right) \tag{16}
$$
\(A_{(3)} = l_3 u_3 + A_{(4)}\)より、\(A_{(1)} = l_1 u_1 + l_2 u_2 + l_3 u_3 + A_{(4)}\)という関係になります。
4段目
\(A_{(3)}\)から一つ縮小した\(A_{(4)}\)をさらにLU分解を行います。\(A_{(4)}\)の関係から\(LU\)行列も(17)式のようになります。
$$
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & a_{44(4)}
\end{array}\right)=
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & 1
\end{array}\right)
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{17}
$$
(17)式の関係から\(U\)行列の4行目は(18)式、\(L\)行列の4列目は(19)式のよう求まります。
$$
\begin{eqnarray}
a_{44(4)} &=& u_{44}
\end{eqnarray} \tag{18}
$$
$$
\begin{eqnarray}
a_{44(4)} = l_{44} u_{44} &\Rightarrow& l_{44} = a_{44(4)} / u_{44} = 1 \\
\end{eqnarray} \tag{19}
$$
ここで、\(l_4, u_4\)を(20)式のように定義して、
$$
l_4 = (0, 0 , 0 , 1) ^T , u_3 = (0, 0 , 0, u_{44}) \tag{20}
$$
\(A_{(4)} – l_4 u_4 = A_{(5)}\)とすると\(A_{(5)}\)は(21)式のようにゼロ行列になります。
$$
A_{(5)} =
\left(\begin{array}{cccc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0
\end{array}\right) \tag{21}
$$
\(A_{(5)}\)はゼロ行列なので分解できないので、ここでLUへの分解は終了します。
\(A_{(4)} = l_4 u_4\)より、\(A_{(1)} = l_1 u_1 + l_2 u_2 + l_3 u_3 + l_4 u_4\)という関係になります。
LU行列
これまでの計算で \(A_{(1)} = l_1 u_1 + l_2 u_2 + l_3 u_3 + l_4 u_4\)と分解が出来ました。それから\( A_{(1)} = A = LU\)という(1)式の関係がありましたので、(4)式、(10)式、(15)式、(20)式から、L行列とU行列は(22)式のように構成できます。
$$
\begin{eqnarray}
L &=& (l_1 , l_2 , l_3 , l_4 ) \\
U &=& (u_1 , u_2, u_3, u_4 ) ^T
\end{eqnarray} \tag{22}
$$
以上が基本的なA行列をLU行列へ分解するアルゴリズムです。1段目から4段目まで同じ手順で分解していきましたので、アルゴリズムとしてOKですね。
計算上の問題と対策
これまで代数で計算したので現れなかったのですが、\(L\)行列の要素を計算する(3)式、(9)式、(14)式、(19)式は\(U\)行列の対角要素、つまり\(A_{(i)}\)行列の左上の対角要素で割った計算を行っていました。
例えば、2段目の計算で(23)式のように\(A_{(2)}\)行列の左上の要素がゼロになってしまった場合、
$$
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right)=
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 1 & 0 & 0 \\
0 & l_{32} & 1 & 0 \\
0 & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{23}
$$
\(u_{22} = 0 \)となり、L行列の要素計算で(24)式のように\(\infty\)となってしまい、計算エラーとなってしまいます。
$$
\begin{eqnarray}
a_{22(2)} = l_{22} u_{22} &\Rightarrow& l_{22} = a_{22(2)} / u_{22} = \infty \\
a_{32(2)} = l_{32} u_{22} &\Rightarrow& l_{32} = a_{32(2)} / u_{22} = \infty \\
a_{42(2)} = l_{42} u_{22} &\Rightarrow& l_{42} = a_{42(2)} / u_{22} = \infty
\end{eqnarray} \tag{24}
$$
この計算エラーを\(Pivot\)という方法で乗り越えます!
ここでようやく半分です。もう少しだけ頑張っていきましょう。
Pivot付きのLU分解
1段目
1段目は普通に計算し、\(l_1, u_1\)が求められたとします。
$$
\left(\begin{array}{cccc}
a_{11(1)} & a_{12 (1) } & a_{13 (1) } & a_{14 (1) } \\
a_{21(1)} & a_{22 (1) } & a_{23 (1) } & a_{24 (1) } \\
a_{31(1)} & a_{32 (1) } & a_{33 (1) } & a_{34 (1) } \\
a_{41(1)} & a_{42 (1) } & a_{43 (1) } & a_{44 (1) }
\end{array}\right) =
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
l_{21} & 1 & 0 & 0 \\
l_{31} & l_{32} & 1 & 0 \\
l_{41} & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14} \\
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right)
$$
\(A_{(1)} – 1_l u_1 = A_{(2)}\)の計算で(25)式のように、左上の対角要素がゼロになったとします。
$$
A_{(2)} = \left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) \tag{25}
$$
とりあえずこの段階では、\(A_{(1)} = l_1u_1 + A_{(2)}\)です。
2段目
\(A_{(2)}\)の左上の対角要素がゼロとなっていますので、(26)式をそのまま計算すると、Lの要素が \(\infty\) となってしまいます。
$$
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) =
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 1 & 0 & 0 \\
0 & l_{32} & 1 & 0 \\
0 & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{26}
$$
そこでLの要素が\(\infty\)とならないように、値がゼロでない行と入替え(Pivot)を行います。例えば2行目と3行目をPivotするとします。
Pivot(行を入れ替える)方法は例えば2行目と3行目を入れ替える場合、(27)式の\(S_{2,3}\)を\(A_{(1)} = l_1 u_1 + A_{(2)}\)の左側から掛けることで、
$$
S_{2,3} =
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1
\end{array}\right) \tag{27}
$$
$$
\begin{eqnarray}
S_{2,3} A_{(1)} &=& S_{2,3} l_1 u_1 + S_{2,3} A_{(2)} \\
&=&
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1
\end{array}\right)
\left(\begin{array}{c}
1 \\ l_{21} \\ l_{31} \\ l_{41}
\end{array}\right)
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14}
\end{array}\right) \\
&&+
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) \\
&=&
\left(\begin{array}{c}
1 \\ l_{31} \\ l_{21} \\ l_{41}
\end{array}\right)
\left(\begin{array}{cccc}
u_{11} & u_{12} & u_{13} & u_{14}
\end{array}\right)
+
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) \tag{28}
\end{eqnarray}
$$
(28)式のように、\(A_{(2)}\)の左上の対角要素がゼロではなくなります。このとき、Pivotは関係する全体にかかるので、1段目で計算した\(l_1\)も(28)式のように入れ替わることになります。
このPivotを行った\(S_{2,3} A_{(2)}\)を以下の関係で分解し、\(l_2, u_2\)を計算します。
$$
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & a_{32(2)} & a_{33(2)} & a_{34(2)} \\
0 & 0 & a_{23(2)} & a_{24(2)} \\
0 & a_{42(2)} & a_{43(2)} & a_{44(2)}
\end{array}\right) =
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & 1 & 0 & 0 \\
0 & l_{32} & 1 & 0 \\
0 & l_{42} & l_{43} & 1
\end{array}\right)
\left(\begin{array}{c|ccc}
0 & 0 & 0 & 0 \\ \hline
0 & u_{22} & u_{23} & u_{24} \\
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right)
$$
すると\(S_{2,3}A_{(1)} = S_{2,3} l_1 u_1 + l_2 u_2 + A_{(3)}\)となります。\(l_2 u_2\)以降は\(S_{2,3}\)が掛かっていませんが、\(l_2, u_2 , A_{(3)}\)を計算するときに既にかかっているので内包していると考えます。
3段目
3段目の計算で\(A_{(3)}\)の左上の対角要素がゼロとなってしまったとします。
$$
A_{(3)} = \left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & a_{34(3)} \\
0 & 0 & a_{43(3)} & a_{44(3)}
\end{array}\right) \tag{28}
$$
ここで3行目と4行目を入れ替える\(S_{3,4}\)を左から掛けることで、
$$
\begin{eqnarray}
S_{3,4} S_{2,3} A &=& S_{3,4} S_{2,3}l_1 u_1 + S_{3,4} l_2 u_2 +
\left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 &1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0
\end{array}\right)
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & a_{34(3)} \\
0 & 0 & a_{43(3)} & a_{44(3)}
\end{array}\right) \\
&=& S_{3,4} S_{2,3}l_1 u_1 + S_{3,4} l_2 u_2 +
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{43(3)} & a_{44(3)} \\
0 & 0 & 0 & a_{34(3)}
\end{array}\right) \tag{29}
\end{eqnarray}
$$
(29)式のように対角要素がゼロでない\(S_{3,4}A_{(3)}\)となります。また、このとき既に計算した\(l_1, l_2\)もPivotが行われます。
この\(S_{3,4}A_{(3)} \)で以下の関係で分解を行うことで、\(l_3, u_3\)を求めることが出来ます。
$$
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & a_{43(3)} & a_{44(3)} \\
0 & 0 & 0 & a_{34(3)}
\end{array}\right) =
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 1 & 0 \\
0 & 0 & l_{43} & 1
\end{array}\right)
\left(\begin{array}{cc|cc}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & u_{33} & u_{34} \\
0 & 0 & 0 & u_{44}
\end{array}\right)
$$
ここまでの関係は \(S_{3,4} S_{2,3} A = S_{3,4} S_{2,3}l_1 u_1 + S_{3,4} l_2 u_2 + l_3 u_3 + A_{(4)}\)です。
4段目
4段目は(30)式の関係で分解を行い、\(l_4, u_4\)が求まったとします。
$$
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & a_{44(4)}
\end{array}\right)=
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & 1
\end{array}\right)
\left(\begin{array}{ccc|c}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & u_{44}
\end{array}\right) \tag{30}
$$
そうするとLUへの分解が終了し、Pivotを行った最終的な式は(31)式のようになります。
$$
S_{3,4}S_{2,4} A = S_{3,4} S_{2,3} l_1 u_1 + S_{3,4} l_2 u_2 + l_3 u_3 + l_4 u_4 \tag{31}
$$
LU分解後の処理
\(P = S_{3,4} S_{2,4}\)とし、\( L= (S_{3,4} S_{2,3} l_1 , S_{3,4} l_2 , l_3, l_4) \)、\(U = (u_1, u_2, u_3, u_4)^T \)とすると、Pivotを行ったLU分解は(32)式のようになります。
$$
PA = L U \tag{32}
$$
入替えの入替えは元に戻るという関係:\(P^2 = I\)より、\(P^{-1} = P\)となるので、(32)式を(33)式になります。
$$
A = P LU \tag{33}
$$
\(A \boldsymbol{x} = \boldsymbol{b}\)の関係があるので、これに(33)式を代入すると(34)式となり、
$$
P L U \boldsymbol{x} = \boldsymbol{b} \tag{34}
$$
(34)式は(35)式となるので、この関係から解\(\boldsymbol{x}\)を求めます。
$$
L U \boldsymbol{x} = P\boldsymbol{b} \tag{35}
$$
プログラムコード – Python
LU行列から方程式を求めるコードも再掲して、LU分解により方程式を求める全体のコードを掲載します。
ここに到達するまですごく長かったですが、プログラムコードは非常にスッキリしています。
Pivotの関数
import numpy as np # Pivotの影響を受けるA, L P行列をk行を基準に入替え def Pivot(A, L , k , P): n = A.shape[0] n_max = abs(A[k,k]) pivot_n = k for i in range(k+1, n): # Pivotを行うため、最大の行を探索 if n_max < A[i,k]: n_max = A[i,k] pivot_n = i # Pivot行列の入替え P_k = np.copy(P[k,:]) # '='だけでは参照渡しになるので copyを使用する P[k, :] = P[pivot_n, :] P[pivot_n, :] = P_k # A行列の入替え A_k = np.copy(A[k, :]) # '='だけでは参照渡しになるので copyを使用する A[k, :] = A[pivot_n, :] A[pivot_n, :] = A_k # L行列の入替え L_k = np.copy(L[k, :]) # '='だけでは参照渡しになるので copyを使用する L[k, :] = L[pivot_n, :] L[pivot_n, :] = L_k return A, L , P
LU分解の関数
import numpy as np # A行列をLU分解 def LU_decomposition(A): # 配列の作成 L = np.zeros(A.shape) U = np.zeros(A.shape) P = np.eye(A.shape[0], A.shape[1]) for i in range(A.shape[0]): # Pivot実行 A, L, P = Pivot(A, L , i, P) # L, U 行列の計算 for j in range(i, A.shape[1]): U[i, j] = A[i, j] # U行列 i 行目を算出 L[j, i] = A[j ,i] / U[i, i] # L行列 i 列目を算出 # 次のA行列を計算 for j in range(A.shape[0]): for k in range(A.shape[1]): A[j,k] =A[j,k] - L[j, i] * U[i, k] return L, U, P
LU行列から方程式を解く関数
import numpy as np # step 1 計算 def solve_z(L, b): z = np.zeros(b.shape) for i in range(z.shape[0]): r = 0 for j in range(0, i): r += L[i,j] * z[j] z[i] = b[i] - r return z # step 2 計算 def solve_x(U, z): x = np.zeros(z.shape) for i in reversed(range(x.shape[0])): r = 0 for j in range(i + 1, x.shape[0]): r += U[i,j] * x[j] x[i] = (z[i] - r)/U[i,i] return x
実行
# A行列の定義 A = np.array([[1.0,2.0,3.0], [2.0,4.0,-9.0], [5.0,8.0,1.0]]) # A行列をLU行列へ分解、Pivot行列Pも出力 [L, U, P] = LU_decomposition(A) # b行列の定義 b = np.array([1,2,3]) # b行列をP行列でPivot pb = np.dot(P, b) # 方程式の解を求める z = solve_z(L, pb) x = solve_x(U, z) # 求めた解を出力 print(x) # 出力:[-1. 1. 0.]
コメント