1. ホーム
  2. matlab

[解決済み] Ax = B の形の行列を解く ==> エラー。行列が特異に近い、またはスケールが悪い

2022-02-18 13:57:37

質問

Ax=B の形の方程式を解くのに苦労している。

このシステムの解は、次のようになるはずです。

x = inv(A)*B

しかし、これではうまくいきません。

上記のコードの行を試すと、以下のようなエラーメッセージが表示されます。

Warning: Matrix is close to singular or badly scaled.
     Results may be inaccurate. RCOND = 1.156482e-018. 

matlabは私が指定した行列を反転させるのに苦労しているようです。inv(A)*A と入力して、逆関数が正しく動作しているかどうか確認してみました。

これは恒等式行列を与えるはずですが、同じエラーといくつかのゴミ数字が出ました。

これは、私が使っているA行列です。

A = [5/2   1/2  -1     0     0    -1/2  -1/2   0     0
     1/2   1/2   0     0     0    -1/2  -1/2   0     0 
    -1     0     5/2  -1/2  -1     0     0    -1/2   1/2
     0     0    -1/2   1/2   0     0     0     1/2  -1/2
     0     0    -1     0     3/2  -1/2   1/2   0     0
    -1/2  -1/2   0     0    -1/2   2     0    -1     0  
    -1/2  -1/2   0     0     1/2   0     1     0     0 
     0     0    -1/2   1/2   0    -1     0     2     0 
     0     0     1/2  -1/2   0     0     0     0     1]

なぜこれがうまくいかないのか、何か思い当たることはありませんか?また、Aをスパース行列に変換して(sparse(A))、逆コマンドを実行することも試みました。ダメでした。

解決するには?

問題は、あなたの数学にあります。あなたが提供した行列はフルランクではないので、反転可能ではありません。 手動で検証することもできますが(時間がなくてできません)、MATLABはすでにこの警告を表示することでそれを指摘しています。

浮動小数点数を扱うので、これは時々他の微妙な問題を引き起こしますが、そのうちの1つは det(A) の順になっています。 1e-16 つまり、機械精度か、実際には0である。

この Matrix がフルランクでないことは,以下のようにしてわかります. rank 関数を使用します。 rank(A) = 8 . については 9x9 の行列の場合、これは確かにこの行列が倍数に対して反転しないことを意味します。 rank 関数は機械精度を考慮します)。

MATLAB を使って手動計算に相当する結果を得たい場合は、Symbolic Toolbox とその vpa (可変精度演算)により、計算速度が遅くなる代わりに、起こりうる数値問題を回避することができます。

B = [5  1 -2  0  0 -1 -1  0  0;
     1  1  0  0  0 -1 -1  0  0;
    -2  0  5 -1 -2  0  0 -1  1;
     0  0 -1  1  0  0  0  1 -1;
     0  0 -2  0  3 -1  1  0  0;
    -1 -1  0  0 -1  4  0 -2  0;
    -1 -1  0  0  1  0  2  0  0;
     0  0 -1  1  0 -2  0  4  0;
     0  0  1 -1  0  0  0  0  2];
A = B/2;
size(A)    % = [9 9]
det(A)     % = -1.38777878078145e-17
rank(A)    % = 8
C = vpa(A);
det(C)     % = 0.0
rank(C)    % = 8

VPAでも浮動小数点数でも、ランクは8、サイズは[9 9]、行列式は実質的に0、つまり特異か不可逆であることがわかります。いくつかのエントリを変更することで、行列を正則化(非特異行列)することができるかもしれませんが、それがうまくいくとは限りませんし、別の問題を解決することになります。

実際の問題を解決するには A*x=b に対して x を使用することができます。 mldivide (バックスラッシュ演算子)またはムーア・ペンローズ擬似逆行列を使用します。

x1 = A\b;
x2 = pinv(A)*b;

しかし、このようなシステムは一意な解を持たないので、擬似逆行列もバックスラッシュ演算子も非常に異なる解を返す可能性がある(この場合はそうなる)ことを覚えておいてください。