Matlab チュートリアル (6) - 線形方程式の解法

        科学技術計算における最も重要な問題の 1 つは、連立一次方程式の解法です。行列表記では、一般的な質問は次のような形式になります。2 つの行列 A と b が与えられた場合、Ax = b または xA = b となるような一意の行列 x は存在しますか?
        1 次元の例を考えると有益です。たとえば、次の方程式
        7x = 21
        独自の解決策はありますか?
        答えはもちろん「はい」です。この方程式には一意の解 x = 3 があります。解は割り算で簡単に見つかります。
        x = 21/7 = 3。
         通常、7 の逆数を計算する、つまり 7 –1 = 0.142857... を計算してから 7 –1 に 21 を乗算する ことによっては、解は見つかりません。これにはより多くの作業が必要となり、 限られた桁数で 7 –1 を表す場合は精度が低くなります。同様の考慮事項が、複数の未知数を含む線形方程式系にも当てはまります。MATLAB は、そのような方程式を解くときに逆行列を計算しません。
        これは標準的な数学表記ではありませんが、MATLAB はスカラー例で一般的な除算項を使用して、一般的な連立方程式系の解を記述します。2 つの除算記号、スラッシュ / およびバックスラッシュ \ は、それぞれ MATLAB 関数 mrdivide および mldivideに対応します。未知の行列が係数行列の左側または右側に現れる場合は、2 つの演算子がそれぞれ使用されます。
x = b/A
は、 mrdivide         を使用して 取得された行列方程式 xA = b の解を表します。
x = A\b
は、 mldivide を使用して取得された行列方程式 Ax = b の解        を表します。
        方程式 Ax = b または xA = b の両辺を A で「割る」ことを考えてみましょう。係数行列A は 常に「分母」にあります。
        x = A\bの次元互換性条件では、 2 つの行列 A b の行数が同じであることが必要です。したがって、解 x は b と同じ数の列を持ち 、その行次元はAの列次元と等しくなります。x = b/Aの場合、行と列の役割が逆になります。
        実際、Ax=b の形式の連立一次方程式の方が、xA=b の形式の連立一次方程式よりも一般的です。したがって、バックスラッシュはスラッシュよりもはるかに頻繁に使用されます。このセクションの残りの部分では、バックスラッシュ演算子に焦点を当てます。スラッシュ演算子の対応するプロパティは、次のアイデンティティから推測できます。
(b/A)' = (A'\b')。
        係数行列Aは 正方行列である必要はない。 A のサイズが m×nの場合 、次の 3 つのケースがあります。
        m = n
        正方行列方程式。正確な解決策を見つけてください。
        m > n
        過剰決定方程式系とは、方程式の数が未知数の数よりも多いことを意味します。最小二乗解を求めます。
        m < n
        過小決定方程式系、つまり方程式の数が未知数の数より少ない。最大 m 個の非ゼロ成分を使用して基本的な解を求めます。

1ml除算アルゴリズム

        mldivide演算子は、係数行列のタイプごとに異なるソルバーを使用します。係数行列を調べることにより、さまざまな状態が自動的に診断されます。
        線形方程式系 Ax = b の一般解は、考えられるすべての解を記述します。一般的な解決策は次のようにして見つけることができます。
        1対応する一次方程式系 Ax = 0 の解を求めます。 これを行うには、 null (A)と入力してnullコマンドを使用します。これにより、解空間の基底ベクトルが Ax=0 に復元されます。どの解も基底ベクトルの線形結合です。
        2不均一方程式系 Ax = b の具体的な解を求めます。Ax = b の解は、ステップ 2 の Ax = b の特定の解とステップ 1 の基底ベクトルの線形結合の合計として記述できます。このセクションの残りの部分では、手順 2 で説明したように、MATLAB を使用して Ax = b の特定の解を見つける方法について説明します。

2 つの正方行列方程式

        最も一般的なケースには、正方係数行列A と右側の単一列ベクトル b が含まれます。

2.1非特異係数行列

        行列Aが特異でない場合、解 x = A\bは b と同じサイズになります 例えば:
A = pascal(3);
u = [3; 1; 4];
x = A\u
x =
10
-12
5
A*x が u と正確に等しい         ことが確認できますAbが正方行列で同じサイズの場合、 x = A\bも同じサイズになります。
b = magic(3);
X = A\b
X =
19-3-1
-17 4 13
6 0 -6
A*x が b と正確に等しい         ことが確認できます上の 2 つの例には正確な整数解があります。これは、係数行列がフルランク (非特異数) であるpascal(3)に選択されているためです。

2.2 特異係数行列

        正方行列 A は、線形に独立した列を含まない場合、特異になります。A が単数の場合、解 Ax = b は存在しないか、一意になります。 バックスラッシュ演算子A\bは、 A が特異点に近い 場合、または完全な特異点が検出された場合に警告します。A が単数で、Ax = b に解がある場合、一意ではない特定の解は次のように入力して見つけることができます。
P = pinv(A)*b
        pinv(A)は A の擬似逆関数です。Ax = b の正確な解がない場合、 pinv(A) は 最小二乗解を返します。例えば:
A = [ 1 3 7 ; -1 4 4 ; 1 10 18 ] は特異行列であり、次のように入力して検証できます。
rank(A)
答え =
2
        A はフルランクではないため、ゼロに等しいいくつかの特異値があります。 b =[5;2;12] の場合 、方程式 Ax = b の厳密な解は次のようになります。
pinv(A)*b
答え =
0.3850
-0.1103
0.7066
        次のように入力して、pinv(A)*b が 正確な解であることを確認します。
A*pinv(A)*b
答え =
5.0000
2.0000
12.0000
        ただし、 b = [3;6;0] の場合、 Ax = b には正確な解がありません。この場合、 pinv(A)*b は 最小二乗を返します。
乗算ソリューション。タイプ
A*pinv(A)*b
答え =
-1.0000
4.0000
2.0000
        その場合、元のベクトルbは返されません。拡張行列 [A b]の縮小行階層形式を取得することにより、Ax = b が厳密な解を持つかどうかを判断できます。これを行うには、この例では次のように入力します。
rref([A b])
答え =
1.0000 0 2.2857 0
0 1.0000 1.5714 0
0 0 0 1.0000
        一番下の行は (最後の項を除いて) すべて 0 であるため、方程式には解がありません。この場合、pinv(A) は最小二乗解を返します。

3 過剰決定方程式

        この例は、実験データへのさまざまな曲線近似において、過剰決定方程式系がどのように一般的に発生するかを示します。 y は、時間 t のいくつかの異なる値で測定され、次の観測値が生成されます。次のステートメントを使用して、テーブルにデータを入力および表示できます。
t = [0 .3 .8 1.1 1.6 2.3]';
y = [.82 .72 .63 .60 .55 .50]';
B = table(t,y)
B=6×2テーブル
タイ
___ ___
0 0.82
0.3 0.72
0.8 0.63
1.1 0.6
1.6 0.55
2.3 0.5
        指数関数的減衰関数を使用してデータをモデル化してみる
 
        前の式は、ベクトルy が他の 2 つのベクトルの線形結合によって近似される必要があることを示しています。1 つはすべて 1 を持つ定数ベクトルで、もう 1 つはコンポーネント exp(-t) を持つベクトルです。未知の係数 c 1 および c 2 は、モデルからのデータの偏差の二乗和を最小化する最小二乗フィットを実行することによって計算できます。2 つの未知の係数の場合、6×2 行列で表される 6 つの方程式が存在します。
E = [ones(size(t)) exp(-t)]
E = 6×2
1.0000 1.0000
1.0000 0.7408
1.0000 0.4493
1.0000 0.3329
1.0000 0.2019
1.0000 0.1003
        バックスラッシュ演算子を使用して最小二乗解を取得します。
c = E\y
c = 2×1
0.4760
0.3413
        つまり、データに適合する最小二乗法は次のようになります。
 
次のステートメントは、一定のt 増分        間隔で モデルを評価し、結果を元のデータと並べてプロットします。
T = (0:0.1:2.5)';
Y = [ones(size(T)) exp(-T)]*c;
plot(T,Y,'-',t,y,'o')

        E*cは y と正確に等しいわけではありませんが、その差は生データの測定誤差よりもはるかに小さい可能性があります。長方形行列 A は、 線形に独立した列を持たない場合、ランクが不足しています。 A がランク不足の場合 AX = Bの最小二乗解は一意ではありません。A がランク不足の場合 A\B は 警告を発行し、最小二乗解を生成します。 lsqminnorm を使用すると、すべての解の中で最小のノルムを持つ解 X を見つけることができます。

4 過小決定方程式

        この例は、過小決定方程式系の解が一意ではないことを示しています。線形方程式の過小決定系には、方程式よりも多くの未知数が含まれます。MATLAB 行列の左除算演算は、基本的な最小二乗解を求めます。m × n 係数行列の場合、最大でも m 個の非ゼロ成分が含まれます
簡単なランダムな例を次に示します。
R = [6 8 7 3; 3 5 4 1]
rng(0);
b = randi(8,2,1)
R =
6 8 7 3
3 5 4 1
b =
7
8
連立一次方程式 Rp = b には 2 つの方程式と 4 つの未知数があります。 係数行列には小さい整数が含まれているため、 formatコマンドを使用して解を有理形式で表示するのが適切です。具体的な解決策は次のコマンドで取得できます。
format rat
p = R\b
p =
0
7/17
0
-29/7
R(:,2) は最大のノルムを持つR の列であるため、         非ゼロ成分の 1 つはp(2)です。R(:,4) はR(:,2)を削除した後に制御するため、もう 1 つの非ゼロ成分はp(4)です。過小決定方程式系の完全な一般解は、pに任意の null 空間ベクトルの線形結合を加えたもので表すことができ、null関数 (有理基底を要求するオプション付き) を使用して計算できます。
Z = null(R,'r')
Z =
-1/2 -7/6
-1/2 1/2
1 0
0 1
R*Z がゼロであり、残差 R*x - b がどのベクトル x ( x = p + Z*q)  よりもはるかに小さいこと         が確認できます。Z の列はゼロ空間ベクトルであるため、 Z *qは次のベクトル線形結合です。
        これを説明するには、任意のqを選択して x を構成し、残差のノルムを計算します。
q = [-2; 1];
x = p + Z*q;
format short
norm(R*x - b)
答え =
2.6645e-15
        解が無限にある場合、最小ノルム解は特別な意味を持ちます。lsqminnormを使用して、最小ノルム最小二乗解を計算できます。この解では、 Norm(p) の可能な最小値が得られます。
p = lsqminnorm(R,b)
p =
-207/137
365/137
79/137
-424/137

5 複数の右辺を持つ一次方程式の解

        特定の問題には、同じ係数行列A を使用して、右辺 b が異なる連立一次方程式を解くことが含まれます。 b の異なる値を同時に使用できる場合は、 b を複数列の行列として構築し、単一のバックスラッシュ コマンドX = A\[b1 b2 b3 …] ですべての連立方程式を解くことができます ただし、 bの異なる値を同時にすべて利用できない場合があります。つまり、複数の連立方程式を連続して解く必要があります。連立方程式の 1 つがスラッシュ (/) またはバックスラッシュ (\) を使用して解かれる場合、オペレーターは係数行列Aを分解し、この行列分解を使用して解きます。ただし、その後、異なるbを使用して同様の連立方程式を解くたびに、演算子はAの同じ因数分解を実行しますが、これは冗長な計算です。この問題の解決策は、Aの分解を事前計算し、係数を再利用してbのさまざまな値を解決することです。ただし、実際には、問題を解決するためにどの分解 (LU、LDL、コレスキーなど) を計算するか、および分解をどのように因数分解するかを知る必要があるため、この方法で分解を事前計算するのは困難な場合があります。たとえば、LU 分解を使用して、元の連立方程式 Ax = b を解くには、2 つの連立一次方程式を解く必要があります。
[L,U] = lu(A);
x = U \ (L \ b);
        いくつかの連続した右辺を持つ連立一次方程式の場合は、分解オブジェクトを使用して解くことをお勧めします。これらのオブジェクトを使用すると、行列因数の使用方法を理解していなくても、事前計算された行列因数分解のパフォーマンス上の利点を活用できます。以前の LU 分解を次のように置き換えることができます。
dA = decomposition(A,'lu');
x = dA\b;
        どの分解を使用すればよいかわからない場合は、バックスラッシュと同様に、 decomposition(A) は A のプロパティに基づいて 正しい型を選択します。
        次の簡単なテストは、このアプローチによって考えられるパフォーマンス上の利点を示しています。このテストでは、バックスラッシュ (\) と分解をそれぞれ使用して、同じ疎一次方程式系を 100 回解きます。
n = 1e3;
A = sprand(n,n,0.2) + speye(n);
b = ones(n,1);
% Backslash solution
tic
for k = 1:100
x = A\b;
end
toc
経過時間は 9.006156 秒です。
% decomposition solution
tic
dA = decomposition(A);
for k = 1:100
x = dA\b;
end
toc
経過時間は 0.374347 秒です。
        この問題については、 構文が単純であるにもかかわらず、バックスラッシュを単独で使用するよりも分解のほうがはるかに速く解決できます。

6 反復法

        係数行列 A が大きくて疎な場合、通常、分解方法は効果的ではありません。反復アプローチにより、一連の近似解が生成されます。MATLAB には、大規模で疎な入力行列を処理するための反復メソッドがいくつか用意されています。

7 マルチスレッドコンピューティング

        MATLAB ソフトウェアは、多くの線形代数関数および要素ごとの数値関数のマルチスレッド計算をサポートしています。これらの関数は複数のスレッドで自動的に実行されます。関数または式を複数の CPU でより高速に実行するには、いくつかの条件を満たす必要があります。
1関数によって実行される操作は、同時に実行する複数の部分に簡単に分割できます。これらの部分は、プロセス間の通信をほとんどまたはまったく行わずに実行できなければなりません。シーケンス操作はほとんど必要ありません。
2データ サイズは、データを分割して個々の実行スレッドを管理するのに必要な時間を上回る、同時実行の利点を得るのに十分な大きさです。たとえば、ほとんどの関数は、配列に数千以上の要素が含まれている場合にのみ速度が向上します。
3操作はメモリに束縛されず、処理時間はメモリ アクセス時間によって制御されません。一般に、複雑な関数は単純な関数よりも高速です。 inv lscov linsolve 、および mldivideでは、マルチスレッドが有効な場合、大きな倍精度配列 (約 10,000 要素以上) の速度が大幅に向上します。

 

おすすめ

転載: blog.csdn.net/weixin_44209907/article/details/132023229