Fortran 95とLAPACKを使用した実際の非対称行列の行列指数


10

最近、スキューエルミート行列について同じ質問をしました。その質問の成功に触発され、数時間壁に頭をぶつけた後、本当の非対称行列の行列指数を調べています。固有値と固有ベクトルを見つける方法はやや複雑で、迷ってしまったようです。

背景:先ほど、私は理論物理学SEについてこの質問をしました。その結果、マスター方程式を実際の非対称行列として表現できます。時間に依存しないケースでは、マスター方程式はこの行列をべき乗することによって解かれます。時間に依存するケースでは、統合が必要になります。現時点では、時間に依存しないことだけに関心があります。

様々なサブルーチンを見ている時に、私は私が呼び出しされるべきだと思う(?gehrd?orghr?hseqr ...)それから行列をキャストする方が簡単だろう場合、それは不明であるreal*8complex*16、これらのルーチンの複雑な二重のバージョンでと進み、またはreal*8、私の配列の数を2倍にして、後でそれらの複雑な行列を作成するという制限を守ってください。

では、どのルーチンを(どのような順序で)呼び出す必要があり、実際のdoubleバージョンまたは複素doubleバージョンを使用する必要がありますか?以下は、実際のダブルバージョンでこれを行う試みです。の固有値と固有ベクトルを見つけるのに行き詰まっていL*tます。

function time_indep_master(s,L,t)
  ! s is the length of a side of L, which is square.
  ! L is a real*8, asymmetric square matrix.
  ! t is a real*8 value corresponding to time.
  ! This function (will) compute expm(L*t).

  integer, intent(in)    :: s
  real*8,  intent(in)    :: L(s,s), t
  real*8                 :: tau(s-1), work(s), wr(s), wi(s), vl
  real*8, dimension(s,s) :: time_indep_master, A, H, vr
  integer                :: info, m, ifaill(2*s), ifailr(2*s)
  logical                :: sel(s)

  A = L*t
  sel = .true.

  call dgehrd(s,1,s,A,s,tau,work,s,info)
  H = A
  call dorghr(s,1,s,A,s,tau,work,s,info)
  call dhseqr('e','v',s,1,s,H,s,wr,wi,A,s,work,s,info)
  call dhsein('r','q','n',sel,H,s,wr,wi,vl,1,vr,s,2*s,m,work,ifaill,ifailr,info)

  ! Confused now...

end function

回答:


8

最初に、マトリックスが本当に完全に恣意的であるかどうかについて真剣に考えます:エルミートになるような変換はありますか?物理学は、行列が対角化可能であることを保証しますか(合理的に条件付けられた固有ベクトル行列で)?

実際に利用する対称性がないことが判明した場合は、まず、標準参照であるNineteen Dubious Ways to Compute the Matrix Exponentialを読むことから始めてください(MATLABの作成者とG&vLの共著者によって書かれています)。 。


1
2×24×4

1
私はこの答えが好きです。非対称のケースには十分な落とし穴があり、非対称の行列ではなく対称行列につながる問題の定式化があるかどうかを検討する価値があります。
JM

@ MarkS.Everitt:あなたはほとんどそこにいるようです...行列はどのくらい大きいですか?再び36 x 36ですか?
ジャックポールソン

16×1636×36

2
@ MarkS.Everitt:つまり、問題は事実上、4x4行列をべき乗する方法です。これは、漸近分析が無関係であるためには十分に小さいので、答えは値に完全に依存します。リンクされた物理学の投稿を線形代数に変換しない限り、私はもう言うことはできません(スーパーオペレーターとは何ですか?!?)。
Jack Poulson、2012

7

ジャックが言ったことを踏まえて、ソフトウェアで使用されているように見える標準的なアプローチ(前の質問で述べたEXPOKITなど)は、スケーリングと二乗の後にパデ近似(方法2および3)またはクリロフ部分空間法(方法20)。特に、指数積分器を検討している場合は、クリロフ部分空間法を検討し、指数積分器に関する論文を検討する必要があります(Moler&van Loanの論文では、方法20とともにいくつかの参照が言及されています)。

固有ベクトルを使用することに熱心な場合は、固有ベクトルの三角システム(方法15)の使用を検討してください。行列が非対角化できない可能性があるため、このアプローチは最善ではないかもしれませんが、固有ベクトルと固有値を直接計算するよりも優れています(つまり、方法14)。

ヘッセンベルク形式への還元は良い考えではありません(方法13)。

Fortranの複雑な演算は高速ですが、オーバーフロー/アンダーフローが発生する可能性があるため、実際の演算と複雑な演算のどちらが適しているかはわかりません(「Fortranコンパイラーは本当にどれほど優れているか」を参照)。

方法5〜7(ODEソルバーベースの方法は非効率的)、方法8〜13(高価)、方法14(大規模な行列の固有ベクトルの計算は、特別な構造がなければ困難であり、悪条件のケースでは数値エラーが発生しやすい)を無視しても安全です。 、および方法16(行列のジョーダン分解の計算は数値的に不安定です)。方法17〜19は実装が難しくなります。特に、方法17と18では、さらに多くの資料が必要になります。方法1は、パデ近似がうまく機能しない場合のスケーリングと二乗のフォールバックオプションです。

編集#1:ジャックの答えに応じたコメントに基づいて、ブロックの対角化はオプションのように見えます。その場合、方法18(ブロックの三角形の対角化)のようなものが非常に使用する方法です。質問でこの構造が指定されていなかったため、最初はお勧めしませんでしたが、マトリックスを対角化する変換を行うと、アプローチの複雑さがほとんどなくなります。各ブロックの対角行列次のように分解するGW Stewartのトリックを使用していることを確認してください。Bj

Bj=γj+Ej

γjjEj


1
O2O(n3

間違いなく彼らは自分が何をしているか知っています。LAPACKの実装については心配していません。Fortranコンパイラーの振る舞いにもっと驚きました。
Geoff Oxberry

2
ええ、コンパイラーはよく書かれたLAPACKよりも問題になるかもしれません。コンパイラーによって使用される絶対値と除算の実装が失敗したためにのみプログラムが失敗したことを見つけるのは当惑することがあります...
JM

-1

任意の行列の指数を計算する単純なFortranサブルーチンがあります。Matlabコマンドで確認したところ、問題ありません。スケーリングと二乗に基づいています。数年前に書いた。

gams.nist.govからダウンロードしたような、別のサブルーチンを見つけたいと思います。しかし、まだ運はありません。

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