逆行列を求めるプログラム

プログラムで行列演算をしていると逆行列が必要になることがしばしばあります。 2×2の逆行列なら簡単に求まるからいいんですが、それより大きな行列になると公式らしい公式が見当たらないので仕方なくLU分解のルーチンを組む、なんてことを私は何回か経験しました。

ただ、そのLU分解のルーチンが結構厄介で、ピボット操作などもちゃんとルーチンに組み込んでおかないとゼロ除算とかが発生していまい、本当は逆行列が存在するにもかかわらず算出できない、なんてことになってしまいます。 そもそもこのテの数値演算のアルゴリズムは数式上では正確でもコンピュータに計算させると大きな誤差が発生してしまうので困ったもんです。

ごちゃごちゃしたプログラムを組まなくても逆行列が出せないかなぁ、と思ってちょっと考察してみました。

2×2行列の逆行列

単純な計算で済みます。

高校の教科書にも載っているので覚えてしまっている人も結構いるのでは。 (でも最近の教科書に行列演算ってあるのかな?)

この程度の数式ならそのままコーディングしてしまった方がいいはずです。

3×3行列の逆行列

3×3行列の逆行列を「公式」という形で記載しているものは私の調べた限りでは本でもWeb上でも見つけられませんでした。ガウスの消去法でがんばって計算してみた結果、

というのが出てきました。 ちなみに行列式detA
というような感じで1 / detAでかける前の逆行列の要素を使って数パターンのまとめ方ができます。 行列式だけを求めようとするとそこそこの計算量を必要とするのですが、逆行列を計算する過程で使いまわしのできる項があるので多少抑えられそうです。

2×2行列の逆行列に比べると計算が面倒なのは一目瞭然ですが、LU分解とどっちがマシかというと微妙な線です。 ちゃんと調べていないのでわかりませんが、LU分解の演算の数と比べると同じ位になりそうな気がします。 ピボット操作なんてやらなくていい分こっちの方が気楽な位です。

逆行列の公式

3×3行列の逆行列を計算していたら、なんか逆行列の公式ってちゃんとしたものがあったような気になってきて、調べてみたらやっぱりありました。テキトーに書くとこんな感じです。

ここでAi jというのは小行列というもので、行列Aからi行目とj列目を抜き取った行列をさします(i行j列目の要素のことではないので注意)。

これを素直に計算すると多分精度の良い逆行列は出てくると思いますが、行列の大きさが大きいとLU分解とは比べ物にならないくらいメチャクチャ時間がかかるはずです。

4×4行列の逆行列

逆行列の公式を使って4×4行列の逆行列の式を書くと

だとして
てな風になります。 行列式detA
で求められます。

biiの項を求めるときに使い回しできる部分は結構たくさんあるはずなので、若干高速化の余地はあります。

ここまでくるとステップ数をちゃんと数える気にならないなぁ...