マトリックスバランスアルゴリズム


9

私は制御システムのツールボックスをゼロから作成し、純粋にPython3(恥知らずなプラグイン:)で作成していharoldます。私の過去の調査から、Riccatiソルバーについて、care.m技術的/無関係な理由で常に不満を持っています。

したがって、私は自分の一連のルーチンを作成しています。私が回避策を見つけることができない1つのことは、少なくともと同等の高性能バランシングアルゴリズムを取得することbalance.mです。言及する前に、xGEBALファミリはScipyで公開されており、基本的には次のようにScipyから呼び出すことができます。float型の2D配列があるとしますA

import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A, scale=1 , permute=1 , overwrite_a=0 )

次のテストマトリックスを使用する場合

array([[ 6.      ,  0.      ,  0.      ,  0.      ,  0.000002],
       [ 0.      ,  8.      ,  0.      ,  0.      ,  0.      ],
       [ 2.      ,  2.      ,  6.      ,  0.      ,  0.      ],
       [ 2.      ,  2.      ,  0.      ,  8.      ,  0.      ],
       [ 0.      ,  0.      ,  0.000002,  0.      ,  2.      ]])

私は得る

array([[ 8.      ,  0.      ,  0.      ,  2.      ,  2.      ],
       [ 0.      ,  2.      ,  0.000002,  0.      ,  0.      ],
       [ 0.      ,  0.      ,  6.      ,  2.      ,  2.      ],
       [ 0.      ,  0.000002,  0.      ,  6.      ,  0.      ],
       [ 0.      ,  0.      ,  0.      ,  0.      ,  8.      ]])

ただし、これをに渡すとbalance.m

>> balance(A)

ans =

    8.0000         0         0    0.0625    2.0000
         0    2.0000    0.0001         0         0
         0         0    6.0000    0.0002    0.0078
         0    0.0003         0    6.0000         0
         0         0         0         0    8.0000

順列パターンをチェックすると、それらは同じですが、スケーリングはオフです。gebalは1のスケーリングを与えますが、MATLABは次の2のべき乗を与えます[-5,0,8,0,2]

明らかに、これらは同じ機械を使用していません。Lemonnier、Van Doorenの両面スケーリング、オリジナルのParlett-Reinschなどのさまざまなオプションを試しましたSPBALANCE。また、の密集バージョンなど、あまり知られていない方法もあります。

私が強調するかもしれない一つのポイントは、私はベナーの仕事を知っているということです。特にこの目的のためのハミルトニアン行列のシンプレクティックバランシング。ただし、このタイプの処理はgcare.m(一般化されたRiccatiソルバー)内で行われ、バランシングはを介して直接行われることに注意してくださいbalance.m。したがって、実際の実装を誰かに教えていただければ幸いです。


開示:私はmathworksコードをリバースエンジニアリングしようとはしていません:この質問の動機を含むさまざまな理由のため、実際にそれから離れたいと思っています。昔の時間の。私の意図は、通常のソルバーの上にニュートン反復法を実装できるように、CAREXの例を渡すことができる満足のいくバランスアルゴリズムを取得することです。

回答:


7

これを理解するのにかなり時間がかかりましたが、いつものように、犯人を見つけた後に明らかになります。

David S. Watkinsで報告された問題のあるケースを確認した後 バランスが悪い場合。電子。トランス。数値。Anal、23: 1–4、2006 、およびここで議論(どちらもarXiv:1401.5766v1で引用されています)では、MATLABは最初に対角要素を分離することによってバランスを使用していることがわかります。

私の最初の考えは、LAPACK関数に関する古典的な限定ドキュメントに従って、GEBALがこれを自動的に実行することでした。ただし、作者が対角要素を無視することで何を意味するかは、行/列の合計からそれらを削除することではないと思います。

実際、配列から対角線を手動で削除すると、両方の結果が一致します。

import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A - np.diag(np.diag(A)), scale=1 , permute=1 , overwrite_a=0 )  

と同じ結果が得られbalance.mます(もちろん、対角エントリはありません)。

Fortranに詳しいユーザーがdgebal.fをチェックしてこれを確認できれば、ありがたいです。

編集:上記の結果は、これが唯一の違いであることを意味するものではありません。対角線を分離した後でも、GEBALとbalance.mが異なる結果を生成する別の行列も作成しました。

私は違いが何であるかについてかなり興味がありますが、それはMATLABの組み込みであり、したがって閉じたコードであるため、知る方法がないようです。

EDIT2:matlabは古いバージョンのLAPACK(おそらく3.5.0より前)を使用しており、2016bまでに新しいバージョンにアップグレードされるようです。これで、テストできる限り結果は一致します。それで問題は解決したと思います。古いLAPACKバージョンでテストする必要がありました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.