web-dev-qa-db-ja.com

Matlabのmldivide(別名バックスラッシュ演算子 "\")を実装する方法

私は現在、小さな行列指向の数学ライブラリを開発しようとしています(行列データの構造と操作に Eigen を使用しています)。広く使用されているような便利なMatlab関数を実装したいと思いました。線形システム(行列形式で表される)の解を計算するためのバックスラッシュ演算子( mldivide と同等)。

これをどのように達成できるかについて、詳細な説明はありますか? (私はすでにムーア-ペンローズ疑似逆関数 pinv 関数を古典的なSVD分解で実装しましたが、_A\b_が常にpinv(A)*bであるとは限らないことをどこかで読みました、少なくともマタルブは単にそれをしません)

ありがとう

19
maddouri

にとって 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 (完全およびスパースの場合)を参照してください。

mldivide_full

これらのアルゴリズムはすべて、 [〜#〜] 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 を使用しています。

そのすべてを自分で実装したいのであれば、それはかなり難しい注文です:)

36
Amro