MATLAB に基づく線形方程式の反復解法 (完全なコードとアルゴリズムを使用)

序文

前回の記事では、一次方程式の基本的な解法と大きな方程式の分解を更新しました。このセクションでは、連立一次方程式の反復解法について説明します。

1. 3つの変革

線形方程式系の反復解法では、係数行列 A の上三角行列対角行列下三角行列が使用されます。これら 3 つの変更は、MATLAB の関数を使用して直接実現できます。

1.1 上三角変換

triu(A,1)

1.2 対角変換

diag(A)

1.3 下三角変換

tril(A,-1)

このような行列の説明については、次の記事を参照してください。

MATLAB: 行列の基礎_いや! ブログ-CSDN ブログ

例1

これら 3 つの変換を次の行列 A に対して実行します。

A=\begin{bmatrix}1&2&-2\\1&1&1\\2&2&1 \end{}

ほどく:

MATLAB コードは次のとおりです。

clc;clear;
A=[1 2 -3;1 1 1;2 2 1];

%上三角变换
up=triu(A,1)

%对角变换
diag=diag(A)

%下三角变换
down=tril(A,-1)

操作結果:

上 =

     0 2 -3
     0 0 1
     0 0 0


診断 =

     1
     1
     1


下 =

     0 0 0
     1 0 0
     2 2 0
分析:

2. シルベスター方程式

 シルベスター方程式の形式は次のとおりです。

AX+XB=C

この式では、A はm\times行列、B はn\回n行列、C と X は両方ともm\回n行列です。

MATLAB では、次のように関数を直接呼び出して問題を解決できます。

X=sylvester(A,B,C)

例 2

シルベスター方程式 AX+XB=C の解 X を求めます。ここで、A、B、および C 行列は次のとおりです。

A=\begin{bmatrix}1&0&2&3\\ 4&1&0&2\\ 0&5&5&6\\ 1&7&9&0 \end{}B=\begin{bmatrix}0&-1\\1&0 \end{}C=\begin{bmatrix}1&0\\2&0\\0&3\\1&1 \end{}

ほどく:

MATLAB コードは次のとおりです。

clc;clear;
A=[1 0 2 3;4 1 0 2;0 5 5 6;1 7 9 0];
B=[0 -1;1 0];
C=[1 0;2 0;0 3;1 1];

X=sylvester(A,B,C)

操作の結果は次のようになります。

X =

    0.4732 -0.3664
   -0.4006 0.3531
    0.3305 -0.1142
    0.0774 0.3560

3. ヤコビ反復法

元の方程式系 Ax=b の行列 A は次のように記述できます。

A=DLU

上の式では、-L と -U は厳密には A 行列の下三角部分と上三角部分であり、もちろん対角要素は含まれません。行列 D の式は次のとおりです。

D=diag[a_{11},a_{22},\cdots,a_{nn}]

反復の考え方によれば、x は次の式を取得できます。

x^{(k+1)}=Bx^{(k)}+f

上式の B と f は次のように理解されます。

B=D^{-1}(L+U)=ID^{-1}A,\;f=D^{-1}b

この反復形式をよりよく理解するために、元の線形方程式を完全に次のように記述します。

係数行列が非特異値の場合、つまりa_{ii}\neq0\quad (i=1,2,\cdots,n)、次のようになります。 

反復公式を使用するとx^{(k+1)}=Bx^{(k)}+g\quad (k=0,1,2,\cdots)、最終的な連立方程式は次のようになります。 

jacobi() 関数を呼び出す前に、事前にコーディングする必要があるので、jacobi 関数の内部構造を以下のように見てみましょう。

function y=jacobi(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
B=D\(L+U);
f=D\b;
y=B*x0+f;
n=1;
while(norm(y-x0))>=1.0e-6
x0=y;
y=B*x0+f;
n=n+1;
end
n
end

例 3

x0=0 と仮定すると、精度は であり10^{-6}、ヤコビ法を使用して次の方程式を解きます。

\begin{件}10x_1-x_2=9\\-x_1+10x_2-2x_3=7\\-2x_2+10x_3=6 \end{}

ほどく:

MATLAB コードは次のとおりです。


clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
jacobi(a,b,[0;0;0])  %注意初始值也为一个矩阵

%对jacobi函数的定义
function y=jacobi(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
B=D\(L+U);
f=D\b;
y=B*x0+f;
n=1;
while(norm(y-x0))>=1.0e-6
x0=y;
y=B*x0+f;
n=n+1;
end
n
end

操作結果:


n =

    11


答え =

    0.9958
    0.9579
    0.7916

4. ガウス・ザイデル反復法

ヤコビの方法を利用すると、反復方程式は次の形式にすることもできます。

x^{(k+1)}=Gx^{(k)}+f

同様に、-L と -U はそれぞれ A の下三角部分と上三角部分であり、対角要素は含まれません。G、f、D は次のように定義されます。

G=(DL)^{-1}U,\;f=(DL)^{-1}b,\;D=diag[a_{11},a_{22},\cdots,a_{nn}]

この反復について洞察を得るには、行列内の要素をリストします。

反復計算プロセス中、2 つの近似解x^{(k)}ベクトルの合計を同時に保持する必要がありますx^{(k+1)}したがって、反復公式は次のように書き換えることができます。

備考:表示の都合上、上式中の「L」は省略記号を表します。

したがって、seidel() 関数は MATLAB で次のようにコーディングできます。

function y=seidel(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G=(D-L)\U;
f=(D-L)\b;
y=G*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G*x0+f;
    n=n+1;
end
n
end

 例 4

x0=0 と仮定すると、精度は であり10^{-6}、次の方程式を解くためにガウス・ザイデル法が使用されます。

 \begin{件}10x_1-x_2=9\\-x_1+10x_2-2x_3=7\\-2x_2+10x_3=6 \end{}

ほどく:

MATLAB コードは次のとおりです。

clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
seidel(a,b,[0;0;0])

function y=seidel(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G=(D-L)\U;
f=(D-L)\b;
y=G*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G*x0+f;
    n=n+1;
end
n
end

操作結果:

n =

     7


答え =

    0.9958
    0.9579
    0.7916

分析: この例は直接解くことができます。また、ザイデル反復を使用すると、結果が収束しない場合もあります。

5. SOR反復法

場合によっては、ヤコビ法とガウス・ザイデル法の収束プロセスが遅い場合がありますが、これをさらに改善するために、新しい反復法である Success Over Relaxation ( Success Over Relaxation)、略して SQR 法を導入できます。

反復計算式は次のとおりです。

X^{(k+1)}=(D-wL)^{-1}((1-w)D+wU)x^{(k)}+w(D-wL)^{-1}b

上式では、状況に応じて、w の最適値は通常 [1,2) の間になります。

緩和法の主な考え方は、補正項目としてパラメータ係数\デルタxwを乗算して、新たな近似解を求めることです。反復公式は次のようになります。

x^{(k+1)}=x^{(k)}+w\デルタx

上記の式の計算は\デルタx次のようになります。

これから、反復単純化プロセスは次のように取得できます。

上式に従って Ax=b の近似解列を計算する方法は緩和法と呼ばれます。ここで w は緩和係数です。w<1 の場合は低緩和と呼ばれ、w>1 の場合は超緩和と呼ばれ、w=1 の場合は実際にはガウス・ザイデル反復となります。

関数 sor を構築する上記のプロセスに従って、MATLAB コードは次のようになります。

function y=sor(a,b,w,x0)
D=diag(diag(a)); %形成对角矩阵,其余元素为0
U=-triu(a,1);
L=-tril(a,-1);
M=(D-w*L)\((1-w)*D+w*U);
f=(D-w*L)\b*w;
y=M*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=M*x0+f;
    n=n+1;
end
n
end

例5

 x0=0、精度は10^{-6}w=1.103 とし、SOR 法を使用して次の方程式を解きます。

\begin{件}10x_1-x_2=9\\-x_1+10x_2-2x_3=7\\-2x_2+10x_3=6 \end{}

ほどく:

MATLAB コードは次のとおりです。

clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
sor(a,b,1.103,[0;0;0])

%函数部分
function y=sor(a,b,w,x0)
D=diag(diag(a)); %形成对角矩阵,其余元素为0
U=-triu(a,1);
L=-tril(a,-1);
M=(D-w*L)\((1-w)*D+w*U);
f=(D-w*L)\b*w;
y=M*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=M*x0+f;
    n=n+1;
end
n
end

操作結果:

n =

     8


答え =

    0.9958
    0.9579
    0.7916

6. 2 段階の反復法

線形方程式の係数行列が対称で正定値である場合、特別な反復法、つまり 2 段階反復法を使用して解くこともできます。反復式は次のとおりです。

最初に利用可能になるのは:

(DL)x^{(k+\frac{1}{2})}=Ux^{(k)}+b

(DU)x^{(k+1)}=Lx^{(k+\1)}=Lx^{(k+\frac{1}{2})}+b

さらに導出することができます。

x^{(k+\frac{1}{2})}=(DL)^{-1}Ux^{(k)}+(DL)^{-1}b

x^{(k+1)}=(DU)^{-1}Lx^{(k+\frac{1}{2})}+(DU)^{-1}b

上記の計算プロセスに従って、twostp() 関数を記述することができます。MATLAB コードは次のとおりです。

function y=twostp(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G1=(D-L)\U;f1=(D-L)\b;
G2=(D-U)\L;f2=(D-U)\b;
y=G1*x0+f1;
y=G2*y+f2;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G1*x0+f1;
    y=G2*y+f2;
    n=n+1;
end
n
end

例6

2 段階の方法を使用して、次の連立方程式を解きます。

\begin{pmatrix}10&-1&2&0\\ -1&11&-1&3\\ 2&-1&10&-1\\ 0&3&-1&8\ \end{}\begin{pmatrix}x_1\\x_2\\x_3\\x_4 \end{} =\begin{pmatrix}6\\25\\-11\\15 \end{}

ほどく:

MATLAB コードは次のとおりです。

clc;clear;
a=[10 -1 2 0;-1 11 -1 3;2 -1 10 3;0 3 -1 8];
b=[6;25;-11;15];
twostp(a,b,[0;0;0;0])

function y=twostp(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G1=(D-L)\U;f1=(D-L)\b;
G2=(D-U)\L;f2=(D-U)\b;
y=G1*x0+f1;
y=G2*y+f2;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G1*x0+f1;
    y=G2*y+f2;
    n=n+1;
end
n
end

操作結果:

n =

     7


答え =

    1.0791
    1.9824
   -1.4044
    0.9560

おすすめ

転載: blog.csdn.net/forest_LL/article/details/124247588