当然ここでも,連立方程式
ここで,ある計算により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;
}