二つの行列
と
を記憶するには、
行列ちょうど
個分の
個の成分を記憶できれば十分である。
つまり
上の例で
そこで実際のプログラムでは、 次のようなコーディングをする。
| 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];
|