当然ここでも,連立方程式
ここで,ある計算によりn回目で求められたものを とする.そして,計算回数を増やして,
(14) |
この様な方法は,行列 を と分解するだけで,容易に作ることが できる.たとえば,
(16) |
(17) |
(18) |
そこで, の各成分の計算が終わると,それを直ちに使うことが考えば, メモリーは半分で済む.即ち, を計算するときに,
(19) |
具体的な計算手順は,次のようにする.ここでは,ガウス・ザイデル法の式 (20)を用いて,得られた近似解を としている.
ここで,問題なのが加速緩和係数の値の選び方である.明らかに,それが1の場 合,ガウス・ザイデル法となりメリットは無い.また,1以下だと,ガウス・ザイデル法 よりも収束が遅い.ただし,ガウス・ザイデル法で収束しないような問題には使える.
従って,1以上の値にしたいわけであるが,余り大きくすると,発散するのは目に見えて いる.これについては,2を越えると発散することが分かっている.最適値となると,だ いたい1.9くらいが選ばれることが多い.
式(20)の漸化式に従うプログラム例を以下に示す.
#include <stdio.h> #include <math.h> #define N (3) // 連立方程式の大きさ #define EPS (1e-15) // 計算誤差の許容値 int main(void){ double a[N+1][N+1], x[N+1], b[N+1]; double dx, absx, sum, new; int i,j; a[1][1]=3.0; a[1][2]=2.0; a[1][3]=1.0; // 係数行列 a[2][1]=1.0; a[2][2]=4.0; a[2][3]=1.0; a[3][1]=2.0; a[3][2]=2.0; a[3][3]=5.0; b[1]=10.0; // 同次項 b[2]=12.0; b[3]=21.0; x[1]=0.0; // 近似解の初期値 x[2]=0.0; x[3]=0.0; do{ // 反復計算のループ dx=0.0; absx=0.0; for(i=1;i<=N;i++){ sum=0; for(j=1;j<=N;j++){ if(i != j){ sum+=a[i][j]*x[j]; } } new=1.0/a[i][i]*(b[i]-sum); // 反復計算後の近似解 dx+=fabs(new-x[i]); // 近似解の変化量を加算 absx+=fabs(new); // 近似解の総和計算 x[i]=new; // 新しい近似解を代入 } }while(dx/absx > EPS); // 計算終了条件 for(i=1;i<=N;i++){ printf("x[%d]=%25.20f\n",i,x[i]); } return 0; }