C++
 Computer >> コンピューター >  >> プログラミング >> C++

ガウス・ザイデル法をC++で実装するプログラム【連立一次方程式を反復法で解く】


ガウス・ザイデル法(Gauss–Seidel法)は、連立一次方程式を反復計算によって数値的に解くための古典的な手法の一つです。ヤコビ法と並ぶ代表的な反復法であり、各反復ステップで更新したばかりの新しい近似値を、そのまま同じ反復内の次の計算に利用できる点が大きな特徴です。この記事では、ガウス・ザイデル法を実装したC++プログラムを紹介します。

ガウス・ザイデル法の基本原理

n元の連立一次方程式 Ax = b を解く場合、ガウス・ザイデル法では各変数を次の式で順番に更新していきます。

xi = (bi − Σj≠i aij xj) / aii

ポイントは、右辺に現れる他の変数 xj のうち、すでに同じ反復内で新しい値に更新済みのものは即座に使い、まだ更新されていないものには前回の反復の値を使うことです。この仕組みにより、すべての変数を同時に更新するヤコビ法よりも、一般により速く解に収束します。

アルゴリズム

開始
    行列の次元 p とその要素を入力として受け取る
    x の初期値と反復回数 q を入力として受け取る
    q > 0 の間、以下を繰り返す
        i = 0 ~ p−1 のループ
            n[i] = (b[i] / a[i][i]) で初期化
            j = 0 ~ p−1 のループ
                j ≠ i のとき
                    n[i] = n[i] − ((a[i][j] / a[i][i]) × m[j])
                m[i] = n[i]
        q を 1 減らす
    /*
        a[i][j] : 入力された係数行列
        b[i]    : 方程式の右辺の値を格納する配列
        m[i]    : x の初期値を格納する配列
    */
    return 0
終了

C++による実装例

以下は、ユーザーから係数行列・方程式の右辺・初期値・反復回数を入力し、指定した回数だけ反復計算を行って近似解を出力するC++プログラムです。

#include<iostream>
#include<conio.h>
using namespace std;
int main(void) {
    float a[10][10], b[10], m[10], n[10];
    int p = 0, q = 0, i = 0, j = 0;
    cout << "Enter size of 2D array : ";
    cin >> p;
    for (i = 0; i < p; i++) {
        for (j = 0; j < p; j++) {
            cout << "a[" << i << ", " << j << " ]=";
            cin >> a[i][j];
        }
    }
    cout << "\nEnter values to the right side of equation\n";
    for (i = 0; i < p; i++) {
        cout << "b[" << i << ", " << j << " ]=";
        cin >> b[i];
    }
    cout << "Enter initial values of x\n";
    for (i = 0; i < p; i++) {
        cout << "x:[" << i << "]=";
        cin >> m[i];
    }
    cout << "\nEnter the no. of iteration : ";
    cin >> q;
    while (q> 0) {
        for (i = 0; i < p; i++) {
            n[i] = (b[i] / a[i][i]);
            for (j = 0; j < p; j++) {
                if (j == i)
                    continue;
                n[i] = n[i] - ((a[i][j] / a[i][i]) * m[j]);
                m[i] = n[i];
            }
            cout<<"x"<<i + 1 << "="<<n[i]<<" ";
        }
        cout << "\n";
        q--;
    }
    return 0;
}

実行結果

Enter size of 2D array : 2
a[0, 0 ]=1
a[0, 1 ]=2
a[1, 0 ]=3
a[1, 1 ]=4

Enter values to the right side of equation
b[0, 2 ]=1
b[1, 2 ]=2
Enter initial values of x
x:[0]=0
x:[1]=0

Enter the no. of iteration : 3
x1 = 1. x2 = -0.25
x1 = 1.5 x2 = -0.625
x1 = 2.25 x2 = -1.1875

上記の例では、2×2の連立一次方程式に対して初期値 x1 = 0、x2 = 0 から出発し、3回の反復計算を行っています。反復を重ねるごとに近似値が徐々に真の解へと近づいていく様子が確認できます。

収束条件に関する注意点

ガウス・ザイデル法が確実に収束するための十分条件として、「係数行列が対角優位であること」が知られています。これは、各行において対角成分の絶対値が、それ以外の成分の絶対値の合計よりも大きいことを意味します。対角優位でない行列に対しては、反復計算が発散したり、正しい解に収束しない可能性があるため、実際に適用する前に係数行列の性質を確認しておきましょう。

まとめ

ガウス・ザイデル法は、反復計算によって連立一次方程式を効率的に解けるシンプルで強力な手法です。本記事で紹介したC++プログラムは、行列のサイズや反復回数を自由に変更して試せるので、ぜひ手元で動かしながら収束の様子を観察してみてください。


  1. C++でAVL木(AVLツリー)を実装する方法:回転操作とサンプルコードを徹底解説

    AVL木とは AVL木(AVL Tree)は、自己平衡型二分探索木(Self-balancing Binary Search Tree)の一種です。すべてのノードにおいて、左部分木と右部分木の高さの差が「1以下」に保たれるという性質を持っています。この平衡条件により、木が片側に偏って成長することを防ぎ、検索・挿入・削除といった操作を常に効率的(O(log n))に行うことができます。 木の回転(Tree Rotation)とは 木の回転とは、要素の順序(ソート順)を崩すことなく木の構造を変更する操作のことです。あるノードを一段上へ移動させ、別のノードを一段下へ移動させることで実現されます。 回

  2. 【C++】STLのset_symmetric_differenceで集合の対称差を実装するプログラム

    本記事では、C++の標準テンプレートライブラリ(STL)に含まれる set_symmetric_difference 関数を使って、2つの集合の「対称差」を求めるプログラムを紹介します。 対称差とは、2つの集合のうち「どちらか一方にだけ存在し、両方には存在しない」要素から構成される集合のことです。 主な集合演算の種類 和集合(Union):どちらか一方に含まれるすべての要素 積集合(Intersection):両方に共通して含まれる要素 対称差(Symmetric Difference / 排他的論理和 XOR):片方にのみ含まれる要素 差集合(Difference / 減算):一方から他方