|TOP Page|


LU Factorization

LU分解




Last Update:2009年06月03日


目次

概要

行列を解くのに直接法の一種であるLU分解を使うことが多い.LU分解とは係数行列を下三角行列と上三角行列の積で表す方法である.LU分解の後は三角行列であることを利用して,前進・後退代入を使って高速に連立一次方程式を解くことができる.ここではLU分解の方法について簡単に述べる.LU分解を説明するにあたって,ブロックLU分解をまず説明する.LU分解はブロックLU分解の特殊な場合を何度も繰り返すことで得られる.

ブロックLU分解

ブロックLU分解

次のような行列を考えよう.

\[\begin{array}{l}\b{A} & \b{B}\\ \b{C} & \b{E}\end{array}\]

この行列は次のように分解できることが簡単にわかる.

\[\begin{array}{l}\b{A} & \b{B}\\ \b{C} & \b{E}\end{array}\] = \[\begin{array}{l}\b{I} & 0\\ \b{C}\b{A}^{-1} & I\end{array}\]\[\begin{array}{l}\b{A} & \b{B}\\ 0 & \b{E} - \b{C}\b{A}^{-1}\b{B}\end{array}\]

これはブロックLU分解の一種(下行列の対角ブロックが単位行列となるもの)で,呼ぶ.ブロック上三角行列の右下に現れる項

\b{E} - \b{C}\b{A}^{-1}\b{B} = \b{S}

をシュール補元(Shur Complement)と呼び,\b{S}と書くこともある.

ブロック下三角行列の逆行列

\[\begin{array}{l}\b{I} & 0\\ \b{C}\b{A}^{-1} & I\end{array}\]\[\begin{array}{l}\b{I} & 0\\ -\b{C}\b{A}^{-1} & \b{I}\end{array}\]  = \[\begin{array}{l}\b{I} & 0\\ 0 & \b{I}\end{array}\]

が成り立つことから,

\[\begin{array}{l}\b{I} & 0\\ \b{C}\b{A}^{-1} & I\end{array}\]^{-1} = \[\begin{array}{l}\b{I} & 0\\ -\b{C}\b{A}^{-1} & \b{I}\end{array}\]

であることが分かる.

連立一次方程式のブロックごとの計算による求解

次のような連立一次方程式を考えよう.

\[\begin{array}{l}\b{A} & \b{B}\\ \b{C} & \b{E}\end{array}\]\{x_A\\ x_B\} = \{y_A\\ y_B\}

係数行列についてブロックLU分解をすると,次のようになる.但しShur Complementを\b{S}と書いた.

\[\begin{array}{l}\b{I} & 0\\ \b{C}\b{A}^{-1} & I\end{array}\]\[\begin{array}{l}\b{A} & \b{B}\\ 0 & \b{S}\end{array}\]\{x_A\\ x_B\} = \{y_A\\ y_B\}

左から下三角行列の逆行列を掛けて,

\[\begin{array}{l}\b{A} & \b{B}\\ 0 & \b{S}\end{array}\]\{x_A\\ x_B\} = \[\begin{array}{l}\b{I} & 0\\ -\b{C}\b{A}^{-1} & I\end{array}\]\{y_A\\ y_B\}

よって,次のように解が求まる

\b{x}_B = \b{S}^{-1}\{-\b{C}\b{A}\b{y}_A + \b{y}_B\}

\b{x}_A = \b{A}^{-1}\{\b{y}_A - \b{B} \b{x}_B\}

逆をとっているのは,\b{A}\b{S}である.Aの逆が簡単に取れるような状況(例えばAが対角行列)ではこのようなブロック分解における解法は解く行列の次数を減らすことができて効率が良い.

ブロック三角行列の固有値

上のブロックLU分解の結果である,次のブロック上三角行列の固有値を求めてみよう.

\[\begin{array}{l}\b{A} & \b{B}\\ 0 & \b{S}\end{array}\]\phi = \lambda \phi

特性方程式は次のとおり

\det\[\begin{array}{l}\b{A}-\lambda\b{I} & \b{B}\\ 0 & \b{S}-\lambda\b{I}\end{array}\] = 0 \\ \Leftright \det(\b{A}-\lambda\b{I})\det(\b{S}-\lambda\b{I})=0

よって,固有値\lambda\b{A}の固有値,\b{S}の固有値に等しくなる.ブロック三角行列の固有値は対角に位置する行列の固有値に等しいことが分かる.また,対角行列が単位行列であるブロック三角行列の固有値は1であることがわかる.以上から,もとの行列の固有値は\b{A}と,\b{S}の固有値に等しくなる,Shur ComplementSは元の行列の性質を保持しているので非常に重要である.

ブロックLDU分解

LU分解のブロック上三角行列をさらに次のように分解してみよう.

\[\begin{array}{l}\b{A} & \b{B}\\ 0 & \b{E} - \b{C}\b{A}^{-1}\b{B}\end{array}\] = \[\begin{array}{l}\b{A} & 0 \\ 0 & \b{E} - \b{C}\b{A}^{-1}\b{B}\end{array}\]\[\begin{array}{l}\b{I} & \b{A}^{-1}\b{B}\\ 0 & \b{I}\end{array}\]

これを用いると次のように対称に書ける.

\[\begin{array}{l}\b{A} & \b{B}\\ \b{C} & \b{E}\end{array}\] = \[\begin{array}{l}\b{I} & 0\\ \b{C}\b{A}^{-1} & I\end{array}\]\[\begin{array}{l}\b{A} & 0 \\ 0 & \b{S}\end{array}\]\[\begin{array}{l}\b{I} & \b{A}^{-1}\b{B}\\ 0 & \b{I}\end{array}\]

LL^T分解のブロックでの計算

もとの行列が正定値対称行列である場合を考える.つまり,

\b{A}^T = \b{A}

\b{C} = \b{B}^T

\b{E}^T = \b{E}

もとの行列の固有値は\b{A}\b{S}の固有値に等しいので,もとの行列が正定値であるということは\b{A}\b{S}も正定値ということである.このとき次のような実行列L_A,L_Sによる分解が可能である.

A=L_A L_A^T,   S=L_S L_S^T

これを使うとLDU分解の対角ブロック行列は次のように分解できる.

\[\begin{array}{l}\b{A} & 0 \\ 0 & \b{S}\end{array}\] = \[\begin{array}{l}\b{L}_A & 0 \\ 0 & \b{L}_S\end{array}\]\[\begin{array}{l}L_A^T & 0 \\ 0 & L_S^T\end{array}\]

これを上に代入して,

\[\begin{array}{l}\b{A} & \b{B}\\ \b{B}^T & \b{D}\end{array}\] = \[\begin{array}{l}\b{I} & 0\\ \b{B}^T\b{A}^{-1} & I\end{array}\]\[\begin{array}{l}\b{L}_A & 0 \\ 0 & \b{L}_S\end{array}\]\[\begin{array}{l}L_A^T & 0 \\ 0 & L_S^T\end{array}\]\[\begin{array}{l}\b{I} & \b{A}^{-1}\b{B}\\ 0 & \b{I}\end{array}\]\\ \;\;\;\;\;\;\; = \[\begin{array}{l}\b{L}_A & 0\\ \b{B}^T\b{L}_A^{-T} & \b{L}_S\end{array}\]   \[\begin{array}{l}\b{L}_A^T & \b{L}_A^{-T}\b{B} \\ 0 & \b{L}_S^T\end{array}\]\\ \;\;\;\;\;\;\; = \[\begin{array}{l}\b{L}_A & 0\\ \b{B}^T\b{L}_A^{-T} & \b{L}_S\end{array}\] \[\begin{array}{l}\b{L}_A & 0\\ \b{B}^T\b{L}_A^{-T} & \b{L}_S\end{array}\]^T

よって,もとの行列を下三角行列とその転置の形で表すことができた.

LU分解

前節ではブロックLU分解について解説した.ここではそれを用いてLU分解を説明する.LU分解を説明するためにまず,LDU分解について解説する.LDU分解は処理に対称性があるので,理解しやすい.LDU分解した後にDをUにかけたり,DをLにかけたりすることで,LU分解が得られる.LDU分解はブロックLDU分解の特殊な場合を繰り返した物として考えることができるので,ここではそれを使って解説する.

LDU分解

LDU分解は行列を下三角行列,対角行列,上三角行列の積に分けることである.ブロックLDU分解は,もとの行列を大きくブロックに分けて,ブロックごとの計算で全体の分解を行った.ブロックの分け方を代えて,サイズが1のブロックと,n-1のブロックに分けるようなブロックLDU分解を考える.これを繰り返すことでLDU分解が得られる.

\b{S}_0=\[\begin{array}{l}a_0 & \b{b}^T_0\\ \b{c}_0 & \b{E}_0\end{array}\] = \[\begin{array}{l}1 & 0\\ \frac{1}{a_0}\b{c}_0 & \b{I}\end{array}\]\[\begin{array}{l}a_0 & 0\\ 0 & \b{E}_0 - \frac{1}{a}\b{c}_0\b{b}_0^T\end{array}\]\[\begin{array}{l}1 & \frac{1}{a_0}\b{b}_0^T\\ 0 & \b{I}\end{array}\] = \b{L}_1 \b{D}_1 \b{U}_1

さて,

\b{D}_1 = \[\begin{array}{l}a_0 & 0\\ 0 & \b{S}_1\end{array}\],\;\;\;\b{S}_1 = \b{E}_0 - \frac{1}{a_0}\b{c_0}\b{b_0}^T

であった.この右下の(n-1)次の正方行列である\b{S}_1 =\b{E}_0 - \frac{1}{a_0}\b{c_0}\b{b_0}^Tが次のようにLDU分解されるとする.

\b{S}_1=\[\begin{array}{l}a_1 & \b{b}^T_1\\ \b{c}_1 & \b{E}_1\end{array}\] = \[\begin{array}{l}1 & 0\\ \frac{1}{a_1}\b{c}_1 & \b{I}\end{array}\]\[\begin{array}{l}a_1 & 0\\ 0 & \b{E}_1 - \frac{1}{a_1}\b{c}_1\b{b}_1^T\end{array}\]\[\begin{array}{l}1 & \frac{1}{a_1}\b{b}_1^T\\ 0 & \b{I}\end{array}\] = \bar{\b{L}}_2 \bar{\b{D}}_2 \bar{\b{U}}_2

これを使うと,もとの行列\b{D}_1は次のように書ける.

\b{D}_1 = \[\begin{array}{l}a_0 & 0\\ 0 & \bar{\b{L}}_2\bar{\b{D}}_2\bar{\b{U}}_2\end{array}\] = \[\begin{array}{l}1 & 0\\ 0 & \bar{\b{L}}_2\end{array}\]\[\begin{array}{l}a_0 & 0\\ 0 & \bar{\b{D}}_2\end{array}\]\[\begin{array}{l}1 & 0\\ 0 & \bar{\b{U}}_2\end{array}\] = \tilde{\b{L}}_2\b{D}_2\tilde{\b{U}}_2

これを代入すると,もとの行列\b{S}_0は次のように書ける

\b{S}_0 = (\tilde{\b{L}}_1 \tilde{\b{L}}_2) \b{D}_2 (\tilde{\b{U}}_2 \tilde{\b{U}}_1)

ここで,\b{L}_2=\tilde{\b{L}}_1\tilde{\b{L}}_2について具体的に計算してみよう.

\b{L}_2 = \tilde{\b{L}}_1\tilde{\b{L}}_2 = \[\begin{array}{l}1 & 0\\ \frac{1}{a_0}\b{c}_0 & \b{I}\end{array}\]\[\begin{array}{l}1 & 0\\ 0 & \bar{\b{L}}_2\end{array}\] = \[\begin{array}{l}1 & 0\\ \frac{1}{a_0}\b{c}_0 & \bar{\b{L}}_2\end{array}\] = \[\begin{array}{l}1 & 0\\ \frac{1}{a_0}\b{c}_0 & \[\begin{array}{l}1 & 0\\ \frac{1}{a_1}\b{c}_1 & \b{I}\end{array}\]  \end{array}\]

これは単位行列の前2列の対角より下が埋まった下三角行列になっていることがわかる.同様にして,\b{D}_2\b{U}_2について具体的に書くと次のとおり,

\b{D}_2 = \[\begin{array}a_0 & 0 & 0\\ 0 & a_1 & 0 \\ 0 & 0 & \b{E}_1-\frac{1}{a_1}\b{c}_1\b{b}_1^T\end{array}\]    \b{U}_2 = \tilde{\b{U}}_2\tilde{\b{U}}_1 = \[\begin{array}{l}1 & \frac{1}{a_0}\b{b}^T_0\\ 0 & \[\begin{array}{l}1 & \frac{1}{a_1}\b{b}^T_1\\ 0 & \b{I}\end{array}\]  \end{array}\]

\b{D}_2は対角ブロック行列で,始めの2つは対角行列で,以降はブロック行列となっている.\b{U}_2については単位行列の前2行の対角より右がうまった上三角行列になっていることがわかる.

アルゴリズム

これらの作業をもとの行列の次数であるn回繰り返せば,\b{D}_nが対角行列になる.n回繰り返した時にLDU分解が得られる.

もとの行列をS_0とするとき,順番にこれらを求めるアルゴリズムは次のとおり

  1. i=0とする
  2. S_iは(n-i)次の正方行列である.S_iの1行1列目の成分をa_iとする.S_iの1行目で2列目以降の成分をベクトル表記して\b{b}^T_iとする.同様にS_iの1列で2行目以降の成分をベクトル表記して\b{c}_iとする.\b{b}_i,\b{c}_iは(n-i-1)次のベクトルである.またS_iの2行目以降,2列目以降からなる(n-i-1)次の正方行列を\b{E}_iとする.S_{i+1} = \b{E}_i - \frac{1}{a_i}\b{c}_i\b{b}^T_iとする.
  3. a_i\b{D}のi番目の対角に代入.\frac{1}{a_i}\b{c}_i\b{L}のi列目の対角の下に並べる.\frac{1}{a_i}\b{b}^T_i\b{U}のi行目の対角から右に並べる
  4. i<nならiに1を加えて2へ戻る.


これを図示すると下の図のようになる.元の行列\b{S}_0から始まり,右下へ向けて逐次的に計算を進めていく.



図1.LDU分解のアルゴリズム



成分の計算

上のアルゴリズムを成分毎に書いてみよう.元の行列\b{A}として,LDU分解した行列の成分は次のようになる.

但し,A,L,D,Uのij成分をそれぞれa_{ij}のように書くとする.

d_{ij} = \{\begin{array}{ll} a_{ii} - \sum_{k=0}^{i-1}l_{ik} u_{ki} d_{kk}\;\; & (i=j)\\ 0 & (i\ne j)\end{array}\;\;\;\; (i=0,1,\ldots,n-1)

l_{ij} = \{\begin{array}{ll}\(a_{ij} - \sum_{k=0}^{j-1} l_{ik} u_{kj} d_{kk}\)/d_{jj}\;\; &  (i>j)\\ 1 &(i=j)\\ 0 & (i<j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

u_{ij} = \{\begin{array}{ll}\(a_{ij} - \sum_{k=0}^{i-1} l_{ik} u_{kj} d_{kk}\)/d_{ii}\;\; & (i<j)\\ 1 & (i=j)\\ 0 & (i>j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

LU分解

と下三角行列と上三角行列の積になる.これをLU分解という.\b{A}が非対称な場合はクラウト分解,対称の場合はコレスキー分解と呼ばれる.

LU分解その1(Lの対角が1な分解)

前節でLDU分解を用いて分解した行列を\b{A}=\b{L}\bar{D}\bar{U}とする.

\b{U} = \bar{D}\bar{U}

とすると,\b{U}は上三角行列となるので,

\b{A} = \b{L}\b{U}

LDU分解を参考にして上のアルゴリズムを成分毎に書いてみよう.元の行列\b{A}=\b{L}\bar{\b{D}}\bar{\b{U}}として,LDU分解した行列の成分は次のようになる.\b{U} = \bar{\b{D}}\bar{\b{U}}から成分ごとに得られる次の関係式

\bar{d}_{ii} = u_{ii},   u_{ij} = \bar{u}_{ij}\bar{d}_{ij}

を代入して,次が得られる.

l_{ij} = \{\begin{array}{ll}\(a_{ij} - \sum_{k=0}^{j-1} l_{ik} u_{kj}\)/u_{jj}\;\; &  (i>j)\\ 1 &(i=j)\\ 0 & (i<j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

u_{ij} = \{\begin{array}{ll}a_{ij} - \sum_{k=0}^{i-1} l_{ik} u_{kj}\;\; & (i\le j)\\ 0 & (i>j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

LU分解その2(Uの対角が1な分解)

前節でLDU分解を用いて分解した行列を\b{A}=\bar{\b{L}}\bar{D}\b{U}とする.

\b{L} = \bar{L}\bar{D}

とすると,\b{U}は上三角行列となるので,

\b{A} = \b{L}\b{U}

LDU分解を参考にして上のアルゴリズムを成分毎に書いてみよう.元の行列\b{A}=\bar{\b{L}}\bar{\b{D}}\b{U}として,LDU分解した行列の成分は次のようになる.\b{L} = \bar{\b{L}}\bar{\b{D}}から成分ごとに得られる次の関係式

\bar{d}_{ii} = u_{ii},   u_{ij} = \bar{u}_{ij}\bar{d}_{ij}

を代入して,次が得られる.

l_{ij} = \{\begin{array}{ll}a_{ij} - \sum_{k=0}^{j-1} l_{ik} u_{kj}\;\; &  (i\ge j)\\ 0 & (i<j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

u_{ij} = \{\begin{array}{ll}\(a_{ij} - \sum_{k=0}^{i-1} l_{ik} u_{kj}\)/l_{ii}\;\; & (i< j)\\ 1 & (i=j) \\ 0 & (i>j)\end{array}\;\;\;\; (i,j=0,1,\ldots,n-1)

これは行列のデータ構造として,CRSデータ形式を用いる場合に良く使われる.

連立一次方程式の求解

次のような連立一次方程式を解くとする.

\b{A}\b{x} = \b{y}

ここで係数が次のようにLU分解されているとすると,

\b{A} = \b{L}\b{U}

これを解く際には,次のようにベクトル\b{z}を導入して,まず下三角行列について解き,次に上三角行列について順番に解くことで得られる.下三角行列や,上三角行列について解くときには,後に述べるように前進代入,後退代入によって解が得られる.

\b{z} = \b{L}^{-1}\b{y}

\b{x} = \b{U}^{-1}\b{z}

Lz=yを解いてzを求める方法

前進代入を用いてできる

\b{L}\b{z} = \b{y}

l_{00}z_0 = y_0\;\;\; \Leftright\;\;\; z_0 = y_0/l_{00}

l_{10}z_0 + l_{11}z_1 = y_1\;\;\; \Leftright\;\;\; z_1 = \{y_1-l_{10}z_0\}/l_{11}

l_{20}z_0 + l_{21}z_1 + l_{22}z_2 = y_2\;\;\; \Leftright\;\;\; z_2 = \{y_2-l_{20}z_0-l_{21}z_1\}/l_{22}

\sum_{i=0}^k l_{ki}z_i = y_k\;\;\; \Leftright\;\;\; z_k = \{y_k-\sum_{i=0}^{k-1}l_{ki}z_i\}/l_{kk}\;\;\;\;(k=0,1,\ldots,n-1)

Ux=zを解いてxを求める方法

後退消去を用いて求めることができる.

\b{U}\b{x} = \b{z}

xの最後の要素から,順番に最初の要素に向けて求めていく

u_{(n-1,n-1)}x_{n-1} = z_{n-1}\;\;\; \Leftright\;\;\; x_{n-1} = z_{n-1}/u_{(n-1,n-1)}

u_{(n-2,n-2)}x_{n-2} + u_{(n-2,n-1)}x_{n-1} = z_{n-2}\;\;\; \Leftright\;\;\; x_{n-2} = \{z_{n-2}-u_{(n-2,n-1)}x_{n-1}\}/u_{(n-2,n-2)}

u_{(n-3,n-3)}x_{n-3} + u_{(n-3,n-2)}x_{n-2} + u_{(n-3,n-1)}x_{n-1} = z_{n-3}\\\;\;\;\;\;\;\;\; \Leftright\;\;\; x_{n-3} = \{z_{n-3}-u_{(n-3,n-1)}x_{n-1}-u_{(n-3,n-2)}x_{n-2}\}/u_{(n-3,n-3)}

\sum_{i=1}^k u_{(n-k,n-i)}x_{n-i} = z_{n-k}\;\;\; \Leftright\;\;\; x_{n-k} = \{\sum_{i=1}^k z_{n-k}-u_{(n-k,n-i)}x_{n-k}\}/u_{(n-k,n-k)}\;\;\;(k=1,2,\ldots,n)

圧縮表示と計算の高速化

分解する前のもとの行列\b{A}に加え,LとUを表現するためのメモリを別に確保することは効率が悪い.Lは下三角行列で,上半分は0であるし,Uは下三角行列で下半分は0である.もとの行列を変形して,上半分がUになるようにして,下半分がLになるようにすると,これらを1つの行列の中に表示することができる.

いまここで,Uの対角が1になるようにLU分解を行う場合を考える.つまりA=\(\bar{L}\bar{D}\)\b{U} = LUこのとき\b{A}を変形して次のような行列\b{A}'になるようにする.但し,\b{A}',\;\b{L},\;\b{U}のij成分をそれぞれa'_{ij}l_{ij}u_{ij}とする.

a'_{ij} = \{\begin{array}{ll}l_{ij} & (i>j)\\ 1/l_{ii} & (i=j) \\ u_{ij} & (i<j)\end{array}

A'の対角成分が\b{L}の対角成分の逆になっていることに注目されたい.これは\b{A}'の対角成分はLU分解や対角成分は前進代入の際に使われるが,常に逆の値として使われるので,逆の値を保存しておくことで高速化が期待できる.さて,Uの対角が1になるようなLU分解は行ごとの分解に向いている.これはCRSのような行ごとのデータ構造にとって,最も適した分解方法だと言える.このような行列\b{A}'を求めるアルゴリズムは次のとおりとなる.

LU分解(Uの対角が1のLU分解,対角が逆数の圧縮表示)

  1. for\;\; i=0,\ldots,n-1
  2. \;\;\;for\;\; j=0,\ldots,n-1
  3. \;\;\;\;\;\;a'_{ij} = a_{ij} - \sum_{k=0}^{j-1} a'_{ik} a'_{kj}
  4. \;\;\;end\; for
  5. \;\;\;a'_{ii} = 1/ a'_{ii}         (下三角行列の対角成分の逆数を計算して格納)
  6. \;\;\;for\;\; j=i+1,\ldots,n-1
  7. \;\;\;\;\;\; a'_{ij} = a'_{ij}\times a'_{ii}    (下三角行列の対角成分を掛けて上三角行列を作る)
  8. \;\;\;end\; for
  9. end\; for


さて,このように変形した行列に対する前進消去,後退代入は次のようになる.

前進代入(Uの対角が1のLU分解,対角が逆数の圧縮表示)

z_k = \{y_k-\sum_{i=0}^{k-1}a'_{ki}z_i\}a'_{kk}\;\;\;\;(k=0,1,\ldots,n-1)

後退代入(Uの対角が1のLU分解,対角が逆数の圧縮表示)

x_{n-k} = \sum_{i=1}^k z_{n-k}-a'_{(n-k,n-i)}x_{n-i}\;\;\;(k=1,2,\ldots,n)

LU分解アルゴリズム図(圧縮表示)

図2は,圧縮表示をした場合のLU分解アルゴリズムを示している.LU分解の種類や分解の手順に依存せず,だいたい次のような図のとおりになる.つまり,分解する要素a_{ij}があった場合に,対角要素a_{kk}a_{ij}が四角形を作れるように,その上a_{kj}や左a_{ik}分解が終わった要素全てを参照する.

図2.LとUの行列を圧縮表示した時のLU分解の図

参考にしたもの

Links

東京大学新領域創成科学研究科、久田・杉浦研究室、渡邊先生の講義資料
http://www.sml.k.u-tokyo.ac.jp/members/nabe/

Books

行列計算ソフトウェア―WS、スーパーコン、並列計算機 小国 力 (著)


Last Update:2009年06月03日
Made by Nobuyuki UMETANI  梅谷 信行
n.umetani@gmail.com