今回は車輪の再発明的な回。余因子行列を求めるコマンドを「自主開発」してしまいました。Maximaには adjoint() 関数あり、アイキャッチ画像のように一撃で求まります。英語力不足からこれを見落としとりました。しかしお陰でちょっと分かったような分からぬような。結局分かってないじゃん!
※「忘却の微分方程式」投稿順 index はこちら
前回、行列式はおしまいにして先に進むと書きつつ、今回も近くにとどまっております。先に進むのに余因子行列必要だったのです。英語で余因子ってなんというのだろう。調べたところが以下です。
-
- cofactor 余因子
- adjugate matrix 余因子行列
adjugate で検索したために引っかかりませんでした。Maxima様的には
adjoint
と呼ばれているようです。ところが間の悪いことに、以下のスタックオーバーフロー様のページでサイズきめうちの 余因子行列を求めている例を見つけてしまいました。
Access to i and j variables in Maxima’s matrixmap?
これを参考にさせていただき、いかなるサイズの行列に対しても余因子行列が求まる関数が作れるのでは、とやってみることに。
まずは余因子の自主計算から
上の例から、余因子を計算するのに「ピッタリ」な関数があることを知ってしまったのであります。
submatrix(i, M, j)
行列Mから行i, 列jを取り除いた行列を返す関数であります。引数の順番が妙なのは、複数の行や列にも対応、また行だけ、列だけ等にも対応という柔軟性のためかと。まずは、この関数の動きを確かめてみました。以下がそのときのコード。
A: matrix([a, b, c],[d, e, f],[g, h, i]); submatrix(1, A, 1); submatrix(2, A, 2); submatrix(3, A, 3);
Maximaの上で動かした結果が以下に。思いのままに取り出せますな。
こうして部分的な行列を取り出すことができれば、余因子を求める関数は指呼のうちであります。自主製作の余因子関数cofactorが以下に。
cofactor(i, j, M) := (-1)^(i+j)*determinant(submatrix(i, M, j))
実際に、関数を定義して、サンプルデータを食わせてみたところが以下に。一応あっている感じ。
余因子が求められるのであれば、これを「行と列を転置させながら」配列に詰め込んでいければ余因子行列となるはず。でも「行と列を転置させながら」配列に詰め込むところがチョイとテクがいりそう。例のお陰ですんなり解決。
とりあえず与えた行列と同じ大きさの行列を作って適当な数字を詰め込んでみます。
tstGM(M) := genmatrix(lambda([i, j], i+j), length(M), length(M))
ちょっと引っかかったのが、Maxima様のMatrixの行数、列数をどうしたら分かるのか、という点。length()関数で行数は分かるみたいだけれども。ここでは、「どうせ正方行列」なので、length()一つで定義してみました。
元の行列と同じ大きさの行列を作って、そこに転置しながら値を入れることができました。次に入れる値を先ほど作った cofactor()、余因子としてみます。こんな感じ。
adjugateMatrix(M) := genmatrix(lambda([i, j], cofactor(j, i, M)), length(M), length(M))
ちゃんと、余因子行列求まっているみたい。と思ったらMaxima様にちゃんと内蔵されていたことを発見。単に英語力の問題?
行列の行数と列数を数える
先ほど疑問に思った件、2行3列のサンプル行列Cを作って操作してみました。こんな感じ。
length()関数に行列を渡すと返るのは行数。列数はどうしたら求められるのか?col()関数とrow()関数で、指定の列と行を取り出せるようなので、先頭行または先頭列を取り出してみました。
col()関数で1列取り出してlength()見ると2.縦に1列とりだしているので、長さは行数に一致するのでOK.しかし、同様にrow()関数で1行取り出した結果をlength()にかけるとまさかの1。row()関数での1行抽出はできるのだけれど、1行x3列の行列だから1という結果が返ってきてしまう!
仕方がないなということで力業。とりだした1行を転置してその長さを見れば、以下のごとし。
列数もとまったけれど、何だかな~ きっともっと良く調べたらもっといい方法がありそうな気がするんですけれども。。。