私は現在、小さな行列指向の数学ライブラリを開発しようとしています(行列データの構造と操作に Eigen を使用しています)。広く使用されているような便利なMatlab関数を実装したいと思いました。線形システム(行列形式で表される)の解を計算するためのバックスラッシュ演算子( mldivide と同等)。
これをどのように達成できるかについて、詳細な説明はありますか? (私はすでにムーア-ペンローズ疑似逆関数 pinv 関数を古典的なSVD分解で実装しましたが、_A\b
_が常にpinv(A)*b
であるとは限らないことをどこかで読みました、少なくともマタルブは単にそれをしません)
ありがとう
にとって x = A\b
、 バックスラッシュ 演算子は、さまざまな種類の入力行列を処理するために、いくつかの アルゴリズム を包含します。したがって、行列A
が診断され、その特性に従って実行パスが選択されます。
次の ページ は、A
が完全な行列である場合の擬似コードで説明しています。
if size(A,1) == size(A,2) % A is square
if isequal(A,tril(A)) % A is lower triangular
x = A \ b; % This is a simple forward substitution on b
elseif isequal(A,triu(A)) % A is upper triangular
x = A \ b; % This is a simple backward substitution on b
else
if isequal(A,A') % A is symmetric
[R,p] = chol(A);
if (p == 0) % A is symmetric positive definite
x = R \ (R' \ b); % a forward and a backward substitution
return
end
end
[L,U,P] = lu(A); % general, square A
x = U \ (L \ (P*b)); % a forward and a backward substitution
end
else % A is rectangular
[Q,R] = qr(A);
x = R \ (Q' * b);
end
非正方行列の場合、 QR分解 が使用されます。平方三角行列の場合、単純な 前方/後方置換 を実行します。正方対称の正定行列の場合、 コレスキー分解 が使用されます。それ以外の場合、 LU分解 が一般的な正方行列に使用されます。
更新:MathWorksは、
mldivide
のドキュメントページの アルゴリズムセクション を更新しました。いくつかの素敵なフローチャート。 here および here (完全およびスパースの場合)を参照してください。
これらのアルゴリズムはすべて、 [〜#〜] lapack [〜#〜] に対応するメソッドがあり、実際にはおそらくMATLABが実行していることです(MATLABの最近のバージョンには最適化された Intel MKL 実装)。
異なる方法を使用する理由は、最も具体的なアルゴリズムを使用して、係数行列のすべての特性を利用する連立方程式を解こうとするためです(より高速であるか、数値的に安定しているため)。したがって、一般的なソルバーを使用することはできますが、最も効率的ではありません。
実際、A
がどのようなものかを事前に知っている場合は、 linsolve
を呼び出してオプションを直接指定することで、追加のテストプロセスをスキップできます。
A
が長方形または特異値の場合、 [〜#〜] pinv [〜#〜] を使用して、最小ノルム最小二乗解(実装済み)を見つけることもできます。 SVD分解 )を使用:
x = pinv(A)*b
上記のすべては密行列に当てはまりますが、疎行列はまったく別の話です。通常、 反復ソルバー がこのような場合に使用されます。 MATLABは、直接ソルバー用にSuiteSpaseパッケージの [〜#〜] umfpack [〜#〜] およびその他の関連ライブラリを使用していると思います。
スパース行列を操作する場合、診断情報をオンにして、 spparms
を使用して実行されたテストと選択されたアルゴリズムを確認できます。
spparms('spumoni',2)
x = A\b;
さらに、バックスラッシュ演算子は gpuArray でも機能します。この場合、バックスラッシュ演算子は cuBLAS と [〜#〜]マグマ[〜#〜] をGPUで実行します。
また、分散コンピューティング環境で動作する 分散配列 にも実装されます(各ワーカーが配列の一部しか持たないコンピューターのクラスター間で作業が分割され、マトリックス全体ができない場合もあります)。一度にメモリに保存されます)。基礎となる実装は、 ScaLAPACK を使用しています。
そのすべてを自分で実装したいのであれば、それはかなり難しい注文です:)