ls_jacobi.eq1.gifが大きいと,ガウスの消去法では時間がかかりすぎる(ls_jacobi.eq2.gif).これに対して,ガウスの消去法のように直接解くのではなく,適当な初期値から出発して計算を反復することで解に近づけていく方法を反復法と呼ぶ.ここでは最も基本的な反復法であるヤコビ(Jacobi)反復法について述べる.

以下に示す3元連立方程式を考える.

ls_jacobi.eq3.gif

係数行列の対角成分ls_jacobi.eq4.gifならば,

ls_jacobi.eq5.gif

が導かれる. ls_jacobi.eq6.gifを初期値として与え,上式に基づきls_jacobi.eq7.gifと計算していく. 反復回数をls_jacobi.eq8.gifとし,ls_jacobi.eq8.gifを十分大きくするとls_jacobi.eq9.gifは解に収束する. n元連立1次方程式の場合は以下となる.

ls_jacobi.eq10.gif

ここで,ls_jacobi.eq11.gifである.

このようにして解を求める方法がヤコビ反復法である. 解が収束したかどうかはls_jacobi.eq9.gifls_jacobi.eq12.gifの値を比べて,その差が許容誤差内に収まったかどうかで判断する. 絶対誤差を用いる場合の収束条件は以下となる.

ls_jacobi.eq13.gif

また,相対誤差を用いた場合は,

ls_jacobi.eq14.gif

ここでls_jacobi.eq15.gifは許容誤差であり,ユーザが任意の値を設定する. 計算量は反復回数をls_jacobi.eq8.gifとするとls_jacobi.eq16.gifとなり, ls_jacobi.eq8.gifをなるべく小さくすることが計算量を減らすために重要となる.

また,反復法で問題となるのは収束するための条件である. そもそも収束しないのであれば反復を繰り返しても解が発散するだけである. 収束条件を上記の反復式から導出する. まず,反復式を以下のような形で表す.

ls_jacobi.eq17.gif

反復回数が十分大きい数ls_jacobi.eq18.gifであるとき,以下の式が成り立つ.

ls_jacobi.eq19.gif

この2つの式から以下が導かれる.

ls_jacobi.eq20.gif

ls_jacobi.eq21.gifls_jacobi.eq22.gifステップでの誤差, ls_jacobi.eq23.gifls_jacobi.eq8.gifステップでの誤差である. つまり,反復を繰り返すと1ステップごとに誤差がls_jacobi.eq24.gif倍になるということである. そのため,解が収束するためには以下の条件を満たす必要がある.

ls_jacobi.eq25.gif

反復式から係数行列の要素を使って表すと,

ls_jacobi.eq26.gif

この式より,係数行列ls_jacobi.eq27.gifの各行において対角要素の絶対値が非対角要素の絶対値の和より大きい場合に収束する.このような条件を対角優位(diagonal dominant)と呼ぶ.

ヤコビ反復法の実装

ヤコビ反復法をC++で実装した例を以下に示す.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51

int JacobiIteration(vector< vector<double> > &A, int n, int &max_iter, double &eps)
{
    vector<double> x(n, 0.0);        vector<double> y(n, 0.0);
 
    double e = 0.0;
    int k;
    for(k = 0; k < max_iter; ++k){
                for(int i = 0; i < n; ++i){
            y[i] = A[i][n];
            for(int j = 0; j < n; ++j){
                y[i] -= (j != i ? A[i][j]*x[j] : 0.0);
            }
            y[i] /= A[i][i];
        }
 
                e = 0.0;
        for(int i = 0; i < n; ++i){
            e += fabs(y[i]-x[i]);                        }
        if(e <= eps){
            break;
        }
 
        swap(x, y);
    }
 
    max_iter = k;
    eps = e;
 
    for(int i = 0; i < n; ++i){
        A[i][n] = y[i];
    }
 
    return 1;
}

添付ファイル: filels_jacobi.eq4.gif 785件 [詳細] filels_jacobi.eq2.gif 804件 [詳細] filels_jacobi.eq26.gif 869件 [詳細] filels_jacobi.eq7.gif 779件 [詳細] filels_jacobi.eq5.gif 969件 [詳細] filels_jacobi.eq27.gif 924件 [詳細] filels_jacobi.eq18.gif 1233件 [詳細] filels_jacobi.eq24.gif 835件 [詳細] filels_jacobi.eq23.gif 856件 [詳細] filels_jacobi.eq17.gif 794件 [詳細] filels_jacobi.eq9.gif 740件 [詳細] filels_jacobi.eq6.gif 748件 [詳細] filels_jacobi.eq8.gif 709件 [詳細] filels_jacobi.eq15.gif 812件 [詳細] filels_jacobi.eq3.gif 822件 [詳細] filels_jacobi.eq20.gif 802件 [詳細] filels_jacobi.eq25.gif 860件 [詳細] filels_jacobi.eq21.gif 784件 [詳細] filels_jacobi.eq14.gif 807件 [詳細] filels_jacobi.eq16.gif 810件 [詳細] filels_jacobi.eq22.gif 804件 [詳細] filels_jacobi.eq19.gif 810件 [詳細] filels_jacobi.eq13.gif 794件 [詳細] filels_jacobi.eq10.gif 945件 [詳細] filels_jacobi.eq1.gif 908件 [詳細] filels_jacobi.eq11.gif 950件 [詳細] filels_jacobi.eq12.gif 787件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-11-30 (水) 13:48:12