二つの行列 と
を記憶するには、
行列ちょうど
個分の
個の成分を記憶できれば十分である。
つまり
上の例で
そこで実際のプログラムでは、 次のようなコーディングをする。
C 言語風疑似プログラム |
for (k = 1; k < n; k++) { /* (k,k) 成分で掃き出す */ for (i = k + 1; k <= n; k++) { /* q_{ik} = a_{ik} / a_{kk} を求める */ q = a[i][k] / a[k][k]; /* i 行から第 k 行の q 倍を引く (ただし計算は j (≧k+1) 列のみ実行) */ for (j = k + 1; j <= n; j++) a[i][j] -= q * a[k][j]; /* q_{ik} = L_{ik} を記憶しておく (記憶不要になったメモリーを利用) */ a[i][k] = q; } } |
この事情は、係数行列が疎行列の場合も基本的には変らない。 例えば三重対角行列を LU 分解し、 それを用いて連立1次方程式を解く プログラムを末尾に引用するが、 LU 分解の部分は
三重対角行列のLU分解 |
/* 前進消去 (forward elimination) */ for (k = 1; k < n; k++) { al[k + 1] /= ad[k]; /* a[i][k] /= a[k][k] */ ad[k + 1] -= au[k] * al[k + 1]; /* a[i][j] -= a[k][j] * q (jはk+1のみ) */ } |
以下、三重対角行列 の LU 分解が得られているとして、
連立1次方程式
をどうやって解くか述べる。
すでに説明したように、
,
という二つの方程式に分解する。
を解く部分は、
と、三重対角であることに注意すると
for (i = 2; i <= n; i++) b[i] -= al[i] * b[i-1]; |
次に を解く部分は
b[n] /= ad[n]; for (i = n-1; i >= 1; i--) b[i] = (b[i] - au[i] * b[i+1]) / ad[i]; |