%comment $OpenXM: OpenXM/src/asir-contrib/packages/doc/noro_matrix/noro_matrix-ja.texi,v 1.4 2017/03/30 06:16:36 takayama Exp $ %comment --- おまじない --- \input ../../../../asir-doc/texinfo

行列演算パッケージ noro_matrix.rr
************************

このマニュアルでは, asir-contrib パッケージに収録されている, 行列演算パッケージ noro_matrix.rr について解説する. このパッケージを使うには, まず noro_matrix.rr をロードする.

     [1831] load("noro_matrix.rr");
     [2014]

このパッケージの函数を呼び出すには, 全て linalg. を先頭につける.

     [2014] linalg.random_mat(3,5);
     [ 0 -1 -1 ]
     [ -1 3 0 ]
     [ -2 -2 4 ]

このマニュアルでは, 関連する組込み函数についても解説する.

行列に関する函数
========

matrix,vector,linalg.unit_mat
-----------------------------

matrix(M,N[,LISTOFLIST]) :: M行N列の行列を生成する.
vector(SIZE[,LIST]) :: サイズが SIZE のベクトルを生成する.
linalg.unit_mat(SIZE) :: サイズが SIZE の単位行列を生成する.

return
     行列

size
m
n
     正整数

listoflist
     リストのリスト

list
     リスト

  * matrix, vector は組込み, linalg.unit_mat は noro_matrix.rr で定義されている.

  * matrix, vector は, LISTOFLIST, LIST がない場合には零行列, 零ベクトルを生成する.

  * LISTOFLIST は [[1,2,3],[3,4,5]] のようにリストからなるリストである. これが引数として与えられた場合, 要素であるリストを使って行列の各行が順に初期化される.

  * LIST は [1,2,3] のようなリストである. これが引数として与えられた場合, このリストの要素によりベクトルの各成分が初期化される.

     [1559] matrix(2,3);
     [ 0 0 0 ]
     [ 0 0 0 ]
     [1560] vector(3);
     [ 0 0 0 ]
     [1561] linalg.unit_mat(3);
     [ 1 0 0 ]
     [ 0 1 0 ]
     [ 0 0 1 ]
     [1559] matrix(2,3,[[1,2,3],[4,5,6]]);
     [ 1 2 3 ]
     [ 4 5 6 ]

linalg.random_mat, linalg.random_rmat, linalg.random_vect
---------------------------------------------------------

linalg.random_mat(SIZE,BOUND) :: 正方整数行列をランダム生成する.
linalg.random_rmat(M,N,BOUND) :: M 行 N 列の整数行列をランダム生成する.
linalg.random_vect(SIZE,BOUND) :: 整数ベクトルをランダム生成する.

return
     整数

number
     整数

  * linalg.random_mat(SIZE,BOUND) は, サイズ SIZE, 要素がBOUND未満の正方整数行列をランダム生成する.

  * linalg.random_rmat(M,N,BOUND) は M 行 N 列の, 要素がBOUND未満の整数行列をランダム生成する.

  * linalg.random_vect(SIZE,BOUND) は長さ SIZEの, 要素がBOUND未満の整数ベクトルをランダム生成する.

     [1579] linalg.random_mat(3,4);
     [ 2 1 -2 ]
     [ 0 -2 1 ]
     [ 3 1 -2 ]
     [1580] linalg.random_rmat(3,5,2);
     [ 0 -1 0 0 0 ]
     [ 0 -1 0 1 0 ]
     [ -1 0 0 -1 1 ]
     [1581] linalg.random_vect(3,6);
     [ -3 2 3 ]

invmat
------

invmat(MAT)
     :: MAT の逆行列を計算する.

return
     リスト

mat
     正方行列

  * 正方行列 MAT の逆行列を計算する.

  * 結果は [INVMAT,DENOM] なるリストである. ここで, INVMAT は行列, DENOM は分母を表す式であり, INVMAT/DENOM が逆行列を表す.

  * MATが整数行列, あるいは多項式行列の場合, INVMAT はそれぞれ整数行列, あるいは多項式となる. この仕様は, 無駄な分数, 有理式計算を省くために定められているが, 使いにくい場合もある.

     [1575] A=linalg.random_mat(4,5);
     [ 2 4 3 3 ]
     [ 3 0 0 0 ]
     [ 0 2 3 -2 ]
     [ 2 0 -4 3 ]
     [1576] L=invmat(A);
     [[ 0 38 0 0 ]
     [ -3 -28 63 45 ]
     [ 18 16 -36 -42 ]
     [ 24 -4 -48 -18 ],114]
     [1577] AI=L[0]/L[1]$ AI*A;
     [1578] [ 1 0 0 0 ]
     [ 0 1 0 0 ]
     [ 0 0 1 0 ]
     [ 0 0 0 1 ]

det,nd_det
----------

det(MAT[,MOD])
nd_det(MAT[,MOD])
     :: MAT の行列式を求める.

return
     式

mat
     行列

mod
     素数

  * det および nd_det は行列 MAT の行列式を求める.

  * 引数 MOD がある時, GF(MOD) 上での行列式を求める.

  * 分数なしのガウス消去法によっているため, 多変数多項式を成分とする行列に対しては小行列式展開による方法のほうが効率がよい場合もある.

  * nd_det は有理数または有限体上の多項式行列の行列式計算専用である. アルゴリズムはやはり分数なしのガウス消去法だが, データ構造および乗除算の工夫により, 一般に det より高速に計算できる.

     [91] A=matrix(5,5)$
     [92] V=[x,y,z,u,v];
     [x,y,z,u,v]
     [93] for(I=0;I<5;I++)for(J=0,B=A[I],W=V[I];J<5;J++)B[J]=W^J;
     [94] A;
     [ 1 x x^2 x^3 x^4 ]
     [ 1 y y^2 y^3 y^4 ]
     [ 1 z z^2 z^3 z^4 ]
     [ 1 u u^2 u^3 u^4 ]
     [ 1 v v^2 v^3 v^4 ]
     [95] fctr(det(A));
     [[1,1],[u-v,1],[-z+v,1],[-z+u,1],[-y+u,1],[y-v,1],[-y+z,1],[-x+u,1],
     [-x+z,1],[-x+v,1],[-x+y,1]]

generic_gauss_elim
------------------

generic_gauss_elim(MAT)
     :: 整数行列を簡約する.

return
     リスト

mat
     整数行列

  * 整数行列 MAT の簡約階段形 (reduced row echelon form; rref) を計算し, それを構成するデータをリストとして返す.

  * 出力は [B,D,J,K] の形のリストである. 入力 MAT が M 行 N 列とし, そのランクが R とすれば, B は R 行 N-R 列の行列である. D は整数, J は長さ R, K は長さ N-R の整数ベクトルである.

  * 出力データは MAT の rref をエンコードしている. rref の第 J[L] 列は L 行目のみが D, それ以外は 0 の列ベクトル, rref の 第 K[L] 列は B の第 L 列を, 上から詰めたものとなる.

  * このような形式で出力する理由は, 入力行列のランクが大きい場合に, rref は 0 が多い疎な行列となり, メモリを多く消費することと, この形の方が, プログラム上でデータを利用しやすいことによる.

     [1600] A=linalg.random_rmat(3,5,2);
     [ 0 -1 -1 0 -1 ]
     [ 1 0 1 -1 0 ]
     [ 1 1 0 0 0 ]
     [1601] L=generic_gauss_elim(A);
     [[ -1 -1 ]
     [ 1 1 ]
     [ -1 1 ],2,[ 0 1 2 ],[ 3 4 ]]

例えば, rref を計算する函数は次のように書ける.

     def my_rref(A)
     {
         S = size(A); M = S[0]; N = S[1];
         L = generic_gauss_elim(A);
         B = L[0]; D = L[1]; J = L[2]; K = L[3];
         R = length(J); NR = N-R;
         A1 = matrix(M,N);
         for ( I = 0; I < R; I++ ) {
             A1[I][J[I]] = D;
             for ( L = 0; L < NR; L++ ) A1[I][K[L]] = B[I][L];
         }
         return A1;
     }

参照
     matrix vector linalg.unit_mat

linalg.compute_kernel, linalg.compute_image
-------------------------------------------

linalg.compute_kernel(MAT[|rhs=VECT])
     :: 有理数行列の核の基底を計算する.
linalg.compute_image(MAT)
     :: 有理数行列の像の基底を計算する.

return
     リスト

mat
     有理数行列

vect
     有理数ベクトル

  * M 行 N 列の行列を, 列ベクトルに左から掛けることにより N 次元ベクトル空間から M 次元ベクトル空間への線形写像とみなす.

  * linalg.compute_kernel は有理数行列 MAT の核の基底を計算する.

  * linalg.compute_kernel の出力は [[V1,POS1],...,[VL,POSL]] の形のリストである. ここで, VI は基底ベクトル, POSI は, VI の主成分位置, すなわち最小のインデックスを持つ成分の位置を表す. POSI は全て異なることが保証される.

  * オプション VECT が指定された場合, 結果は [SOL,[[V1,POS1],...,[VL,POSL]]] なるリストとなる. ここで SOL は MAT SOL = VECT を満たすベクトル (特殊解), のこりは核の基底である.

  * 解が存在しないような VECT を指定するとエラーを起こす.

  * linalg.compute_image は有理数行列 MAT の像の基底を計算する.

  * linalg.compute_image の出力は, [V1,POS1,HIST1],...,[VL,POSL,HISTL] の形のリストである. ここで, VI は基底ベクトル, POSI は, VI の主成分位置, すなわち最小のインデックスを持つ成分の位置を表す. POSI は全て異なることが保証される. HISTI は, VI が, MAT の列からどのように作られるかを示すデータである. 分散多項式で表現されており, 指数が行インデックス, 係数が, 一次結合の係数を表す. このデータにより作られるベクトルは, 定数倍を除いて VI に等しい.

     [1643] A=linalg.random_rmat(3,5,3);
     [ 2 1 0 1 -1 ]
     [ 2 -2 1 0 1 ]
     [ 2 1 -1 -1 -1 ]
     [1644] linalg.compute_kernel(A);
     [[[ 1 0 -8 4 6 ],0],[[ 0 1 2 -1 0 ],1]]
     [1645] linalg.compute_kernel(A|rhs=vector(3,[1,2,3]));
     [[ 0 0 8 -5 -6 ],[[[ 1 0 -8 4 6 ],0],[[ 0 1 2 -1 0 ],1]]]
     [1646] linalg.compute_image(A);
     [[[ 1 1 1 ],0,(1)*<<0>>],[[ 0 -3 0 ],1,(1)*<<1>>+(-1)*<<0>>],
     [[ 0 0 3 ],2,(-3)*<<2>>+(-1)*<<1>>+(1)*<<0>>]]

linalg.minipoly_mat
-------------------

linalg.minipoly_mat(MAT)
     :: 有理数行列 MAT の最小多項式を計算する.

return
     一変数多項式

mat
     有理数行列

  * 有理数行列 MAT の最小多項式を計算し, 変数 X の一変数多項式として返す.

     [1682] A=linalg.random_mat(3,3);
     [ -2 2 -2 ]
     [ 0 1 -1 ]
     [ 1 -2 -1 ]
     [1683] linalg.minipoly_mat(A);
     x^3+2*x^2-x-6
     [1684] A^3+2*A^2-A-6*linalg.unit_mat(3);
     [ 0 0 0 ]
     [ 0 0 0 ]
     [ 0 0 0 ]

linalg.jordan_canonical_form,linalg.sample_mat
----------------------------------------------

linalg.jordan_canonical_form(MAT)
     :: 有理数正方行列のジョルダン標準形を計算する.
linalg.sample_mat(LIST)
     :: 指定されたジョルダン標準形を持つ有理数正方行列を生成する.

return
     リスト

mat
     有理数正方行列

list
     ジョルダンブロックのリスト

  * linalg.jordan_canonical_form(MAT) は有理数正方行列 MAT のジョルダン標準形を計算する.

  * 出力は [P,[[E1,S1,N1],...,[EL,SL,NL]],DEFIDEAL] という形のリストである. ここで, P は変換行列, すなわち P^(-1)AP がジョルダン標準形となる正則行列, [EI,SI,NI] は, 固有値 EI, サイズ SI のジョルダンブロックが NI 個並ぶことを意味する.

  * 一般に, 出力は A0, ..., AM の形のパラメタを含む. これらは実際には, ある有理数体上既約な多項式の根である. これらを定義する方程式として, DEFIDEAL が与えられる. DEFLIDEAL はリストのリストであり, 各要素であるリストは, 一組の共役な根全体を定義するイデアルを表す. 実際には, 対応する一変数多項式の根を, 根と係数の関係により表したものである.

  * linalg.sample_mat(LIST) は指定されたジョルダン標準形を持つような行列を生成する. LIST は [[E1,S1],...,[EL,SL]] の形のリストで, [EI,S1] は固有値 EI, サイズ SI のジョルダンブロックを表す. 同じサイズのジョルダンブロックはいくつあってもよい.

     [ 1 -2 0 ]
     [ -1 2 1 ]
     [ 0 -2 1 ]
     [1807] L=linalg.jordan_canonical_form(A);
     [[ 2 -2 0 ]
     [ -1 0 1 ]
     [ 2 -2 -1 ],[[2,1,1],[1,2,1]],[]]
     [1808] P=L[0]$T=invmat(P)$PI=T[0]/T[1]$
     [1809] [1810] [1811] PI*A*P;
     [ 2 0 0 ]
     [ 0 1 1 ]
     [ 0 0 1 ]
     [1810] A=linalg.sample_mat([[1,2],[1,1],[2,3],[2,1],[2,1]]);
     [ 2 0 2 113 14 678 0 0 ]
     [ -1 1 -2 -120 -14 -720 0 0 ]
     [ -7 0 -13 -840 -105 -5040 0 0 ]
     [ 54 54 0 380 0 2268 -54 0 ]
     [ 1 0 2 112 16 672 0 0 ]
     [ -9 -9 0 -63 0 -376 9 0 ]
     [ 1 1 0 7 0 42 1 0 ]
     [ 1 1 0 7 0 42 0 2 ]
     [1811] L=linalg.jordan_canonical_form(A);
     [[ 0 -6 42 0 0 0 2 2 ]
     [ 0 6 0 0 0 0 0 -2 ]
     [ 42 -294 0 0 0 0 -1 -1 ]
     [ 0 0 0 6 0 108 0 0 ]
     [ -6 42 48 0 0 0 0 0 ]
     [ 0 0 -1 -1 0 -18 0 0 ]
     [ 0 0 0 0 0 2 0 0 ]
     [ 0 0 0 0 1 0 -2 0 ],[[2,3,1],[2,1,2],[1,2,1],[1,1,1]],[]]

参照
     linalg.minipoly_mat