プログラムな日常>ウェブプログラム作品集>
一次変換と行列、逆行列
(linear transformation, matrix and its inverse)
 
original outline

このウェブプログラムは二次元の線形変換を表わす。 それぞれのスクロールバーで制御される4つの数値は線形変換の行列要素と見て良い。その第1要素(上の行および左の列)はX軸すなわち横向き、第2要素(下および右)はy軸すなわち縦向きの位置に対応する。 本来の右手の平の画の各部分は、本来の場所ではなく、線形変換された位置にプロットされる。 最近使い始めていて、ここでも使っている svg の機能はこうしたプロットには向いている、はずである。

ところが、今回の絵は線画ではなく、ピクセル単位の描画をしている。 これはどういうことかと言うと、面上の一個々々の点の色を決めるのに、「その位置にまで変換される」原画上の点の色を持ってきているのである。 これは、変換の結果である点の位置をもとに、その本来の点を逆変換で求めて、その色要素を使うことを意味する。

まあ、その手続きは、逆行列を使ってできるようにしたのである。 このような低い次元の逆行列に限っては、「余因子(行列式)」と行列式の商から求めるという、数学の教科書にある方法を使って構わないと思う。 使い慣れないルーチンよりもその方が確実かも知れない。 ただし、このプログラムにおいては、それこそ数千次元でも解けるほどの本格的なルーチンを呼び出して使っているが。

使い方であるが、"original" のチェックボックスにチェックを入れると、変換前の画の外形を上書きして比較することができる。

図が小さかったり、痩せたものであるとき、外形の線が見づらくなる。 これは、変換結果のピクセルベースでサンプリングを行っているため、原画上でのサンプリングが荒くなってしまって、外形線をとり損ねるためである。 "outline" のチェックボックスにチェックすると、原画の線のみにつき、正変換した位置に上書きされるので、輪郭がはっきりする。

"initial" のボタンで、単位行列(変換しない)に戻る。

私が使っている中で逆行列のルーチンは最も歴史が古く、それこそ N-88ベーシックから Javascript まで、言語をまたいで書き換え、育てて来た。 アルゴリズムは ガウス=ジョルダン法 だが、ピボットゼロの問題がないように工夫している。 関数の値として通常は true が、非正則(行列式がゼロ)の場合は false が返される。

パフォーマンスだが、C#のルーチンで次の通り。Javascript でも大差ない。次元(行列の一辺)に対してほぼ3乗比例のようだ。

課題サイズと逆行列の計算時間
次元 elapsed time(msec)
128 0~17
256 78
512 875
1,024 5,983
2,048 53,433
4,096 457,588

逆行列のルーチン("matinv")を含む javascript のライブラリ("autil.js")は次の通り。