Gaussian Elimination & LU Decomposition
連立一次方程式の数値解法アルゴリズム
1. ガウスの消去法 (Gaussian Elimination)
連立一次方程式 $\boldsymbol{A}\boldsymbol{x} = \boldsymbol{b}$ を解くための最も基本的な直接法です。行列を上三角化する「前進消去」と、解を求める「後退代入」で構成されます。
① 前進消去 (Forward Elimination)
第 $k$ ステップにおいて、第 $k$ 行を用いてそれより下の行($i > k$)の要素を消去します。
倍率 $m_{ik}$ の計算:
\[ m_{ik} = \frac{a_{ik}^{(k)}}{a_{kk}^{(k)}} \]要素の更新:
\[ a_{ij}^{(k+1)} = a_{ij}^{(k)} - m_{ik} a_{kj}^{(k)} \quad (j = k+1, \dots, n) \] \[ b_{i}^{(k+1)} = b_{i}^{(k)} - m_{ik} b_{k}^{(k)} \]② 後退代入 (Backward Substitution)
変形された上三角行列から、下の変数から順に値を決定します。
2. ピボット演算 (Pivoting)
数値計算の精度と安定性を保つための必須の処理です。
部分選択法 (Partial Pivoting):
前進消去の各ステップ $k$ で、第 $k$ 列の $|a_{kk}|$ から $|a_{nk}|$ の中で絶対値が最大の要素を持つ行を探し、$k$ 行目と入れ替えます。これにより、小さな値での除算による桁落ち(丸め誤差)を防ぎます。
3. LU分解 (LU Decomposition)
ガウスの消去法の計算過程を整理し、行列 $\boldsymbol{A}$ を下三角行列 $\boldsymbol{L}$ と上三角行列 $\boldsymbol{U}$ の積に分解する手法です($\boldsymbol{A} = \boldsymbol{LU}$)。
Doolittle法による漸化式:
一度LU分解を行えば、右辺ベクトル $\boldsymbol{b}$ が変わっても代入操作のみで高速に解けるため、ニュートン法などの反復解法に最適です。
4. スパース行列処理の数学的背景
回路行列などの大規模系では、非ゼロ要素の配置(構造)を数学的に最適化することが計算効率の鍵となります。
① グラフ理論による構造解析
行列 $\boldsymbol{A}$ のスパース構造は、隣接行列を持つ有向グラフ $G(\boldsymbol{A}) = (V, E)$ として表現できます。消去過程におけるピボット選択は、グラフにおける「ノードの除去」と、それに伴う「エッジの追加(フィルイン)」に対応します。
定理:消去グラフ (Elimination Graph)
ノード $v_k$ を消去する際、そのノードに隣接していた全てのノード間にエッジが存在しない場合、それらを結ぶ新しいエッジ(フィルイン)が生成される。このグラフの完全グラフ化を避けることが、スパース性維持の数学的本質である。
② Markowitz Criterion の数理
第 $k$ ステップにおいて、要素 $a_{ij}$ をピボットに選んだ際のフィルイン発生数の上界は、以下の **Markowitz Product** によって与えられます。
ここで、$r_i^{(k)}$ は第 $i$ 行の非ゼロ要素数、$c_j^{(k)}$ は第 $j$ 列の非ゼロ要素数です。消去ごとに $M_{ij}$ を最小化する選択(局所最適化)を行うことで、全体としての $O(N^3)$ の計算量を劇的に削減します。
③ シンボリック分解 (Symbolic Factorization)
数値計算(定数計算)を開始する前に、行列の構造(インデックス)のみを用いて、どの位置にフィルインが発生するかをあらかじめ決定します。これにより、以下のメリットが得られます:
-
静的メモリ割り当て:
実際の数値計算中に動的なメモリ確保を排除し、キャッシュ効率を最大化する。 -
演算のスケジューリング:
依存関係のない演算を特定し、並列計算への最適化を可能にする。
数学的には Markowitz Product が最小の要素を選ぶべきですが、数値的安定性(ピボットの絶対値が小さすぎないこと)も考慮する必要があります。実装上は、安定性を担保する閾値を設けつつ、その範囲内で最小の Markowitz 積を持つ要素を選択する「Threshold Pivoting」が一般的です。
5. 具体的な計算例 (2変数)
以下の系を、ピボット選択を含むガウスの消去法で解きます。
\[ \begin{cases} 1x_1 + 2x_2 = 5 \\ 3x_1 + 4x_2 = 11 \end{cases} \]Step 1: ピボット選択
$|3| > |1|$ のため、1行目と2行目を入れ替えます。
Step 2: 前進消去
1行目を $1/3$ 倍して2行目から引きます。
Step 3: 後退代入
$0.667x_2 = 1.333 \Rightarrow x_2 = 2$
$3x_1 + 4(2) = 11 \Rightarrow 3x_1 = 3 \Rightarrow x_1 = 1$
結果: $x_1 = 1, x_2 = 2$