行列とテンソルの操作
このチュートリアルでは,行列,ベクトル,テンソルの構築と操作のためのWolfram言語関数を復習する.まずWolfram言語に特有の関数に焦点を当て,次に行列を使った多くの例を示す.すべての関数は一般的なものであり,どれもベクトル,テンソルにも使える.
行列の構築
{{1.5, 1.6}, {1.7, 1.8}}Wolfram言語では,この他にもさまざまな方法で行列が作成できる.
| Table[f,{i,m},{j,n}] | m×n 行列の作成(f は i,j 番目の要素を表す i と j についての関数) |
| Array[f,{m,n}] | i,j 番目の項目が f[i,j]である m×n 行列を作成する |
| DiagonalMatrix[list] | 対角要素が list である対角行列を作成する |
| IdentityMatrix[n] | n×n の単位行列を作成する |
| ConstantArray[val,{m,n}]] | 各要素が val である m×n 行列を作成する |
| RandomReal[{0,val},{m,n}]] | 要素が乱数である m×n 行列を作成する |
| Normal[SparseArray[{{i1,j1}->v1,{i2,j2}->v2,…},{m,n}]] | |
| 位置{ik,jk}に非零の値 νk を持つ m×n 行列を作成する | |
mat = Table[Subscript[m, i, j], {i, 3}, {j, 3}]MatrixForm[%]Array[m, {3, 3}]IdentityMatrix[5]N[IdentityMatrix[5]]DiagonalMatrix[ {1, 2, 3, 4}]非零の値が2つ埋め込まれた34行列を作成する.SparseArray式については後のセクションで述べる.
DiagonalMatrix[{1, 2, 3, 4}, 1]//MatrixFormConstantArray[2, {5, 5}]RandomReal[{0, 5}, {2, 4}]RandomInteger[{-5, 5}, {3, 4}]Normal[SparseArray[{{2, 3} -> a, {3, 2} -> b}, {3, 4}]]| SparseArray[{},{n,n}] | 零行列 |
| SparseArray[{i_,i_}->1,{n,n}] | n×n の単位行列 |
| SparseArray[{i_,j_}/;i>=j->1,{n,n}] | |
| 下三角行列 | |
SparseArrayによる特別な行列の作成
SparseArray[{i\_, j\_}/;i>=j -> f[i, j], {3, 3}] // MatrixFormファイルから行列を読み込む関数については「行列のインポートとエキスポート」で述べる.
特別な行列
Wolfram言語には,多くの特別な行列の定義が含まれている.
| HilbertMatrix[n] | 要素が1/(i+j-1)で与えられる n×n のヒルベルト(Hilbert)行列の作成 |
| HilbertMatrix[{m,n}] | m×n のヒルベルト行列を作成する |
| HankelMatrix[n] | 最初の列が1, 2, …, n であり,主反対角要素の下がゼロである n×n のハンケル(Hankel)行列を作成する |
| HankelMatrix[list] | 最初の列が list で,主反対角要素の下がゼロであるハンケル行列を作成する |
| HankelMatrix[col,row] | 最初の列がリスト col,最後の列がリスト row で与えられるハンケル行列を作成する |
HilbertMatrix[{2, 4}]//MatrixFormHankelMatrix[{w, x, y, z}]//MatrixFormHankelMatrix[{w, x, y, z}, {z, m, n}]//MatrixForm構造操作
以下の操作はすべて行列の構造に関連している.このセクションで示す方法の多くは,行列だけではなく,他のWolfram言語式にも適用できる.
行列の一部の抽出
行列の要素,行,列の抽出は,Wolfram言語関数Partを使えば極めて容易である.一般にPartは[[ ]]という表記で入力する.
| m[[i,j]] | i,j 番目の要素 |
| m[[i]] | i 番目の行 |
| m[[i;;i]] | i 番目から j 番目までの行 |
| m[[All,i]] | i 番目の列 |
| m[[All,i;;j]] | i 番目から j 番目間での列 |
| m[[{i1,…,ir},{j1,…,js}]] | 行指標が ik,列指標が jk である要素を持つ r×s の部分行列 |
| Tr[m,List] | m の対角要素のリスト |
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormmat[[1, 2]]mat[[3]]mat[[All, 3]]mat[[-1, -1]]mat[[2 ;; 4]]mat[[All, 2 ;; 4]]mat[[All, 1 ;; -1 ;; 2]]Tr[mat]Tr[mat, List]これらの行列の一部を抽出する関数は,他のどのWolfram言語式にも適用できる.
複数の部分の抽出
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormmat[[2, {1, 3}]]mat[[{2, 4}]]mat[[{2, 4}, {1, 3}]]行列の要素の設定
行列の要素,行,列は,割当て式の左辺にWolfram言語関数Partを指定すると簡単に変更できる.
| m={{a11,a12,…},{a21,a22,…},…} | m に行列を割り当てる |
| m[[i,j]]=v | {i,j} の要素を v に再設定する |
| m[[i]]=v | i 行目の要素すべてを v に再設定する |
| m[[i]]={v1,v2,…} | i 行目の要素を{v1,v2,…}に再設定する |
| m[[All,j]]=v | j 列目の要素すべてを v に再設定する |
| m[[All,j]]={v1,v2,…} | j 列目の要素を{v1,v2,…}に再設定する |
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixForm行列の一部に変更を加えるには,割当て式の左辺にPartを使えばよい.
mat[[3, 3]] = x;
mat//MatrixFormmat[[2]] = {1, 2, 3, 4, 5};
mat//MatrixFormmat[[All, 2]] = {-1, -2, -3, -4, -5};
mat//MatrixFormmat[[-1, -1]] = x;
mat//MatrixFormmat[[All, 1 ;; -1 ;; 2]] = z;
mat//MatrixForm複数の部分の設定
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormmat[[2, {1, 3}]] = x;
mat//MatrixFormmat[[2, {1, 3}]] = {x, y};
mat//MatrixFormmat[[{2, 4}]] = {1, 2, 3, 4, 5};
mat//MatrixFormmat[[{2, 4}]] = {{1, 2, 3, 4, 5}, {-1, -2, -3, -4, -5}};
mat//MatrixFormmat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat[[{2, 4}, {1, 3}]] = x;
mat//MatrixFormmat[[{2, 4}, {1, 3}]] = {{a, b}, {c, d}};
mat//MatrixForm部分行列の抽出
| m[[i0;;i1,j0;;j1]] | i0 行目から i1行目,j0 列目から j1列目までの部分行列を抽出する |
| m[[i0;;i1]] | i0 行目から i1行目までの部分行列を抽出する |
| m[[All,j0;;j1]] | j0 列目から j1列目までの部分行列を抽出する |
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormmat[[2 ;; 3, 1 ;; 2]]//MatrixFormmat[[1 ;; 3]]//MatrixFormmat[[All, 2 ;; 4]]//MatrixFormmat[[All, 2 ;; -2]]//MatrixForm行と列の削除
行や列の削除にはDropを使用する.
| Drop[m,{i0,i1}] | i0 行目から i1行目までを削除する |
| Drop[m,{},{j0,j1}] | j0 列目から j1列目までを削除する |
| Drop[m,{i0,i1},{j0,j1}] | i0 行目から i1行目まで,j0 列目から j1列目までを削除する |
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormDrop[mat, {2, 4}]//MatrixFormDrop[mat, {}, {2, 4}]//MatrixFormDrop[mat, {2, 3}, {1, 3}]//MatrixForm行と列の挿入
行の挿入にはInsertを使う.
| Insert[m,r,i] | 行列 m の位置 i に列 r を挿入する |
mat = Table[Subscript[m, i, j], {i, 5}, {j, 5}];
mat//MatrixFormInsert[mat, {x, x, x, x, x}, 3]//MatrixFormTranspose[Insert[Transpose[mat], {x, x, x, x, x}, 5]]//MatrixForm行列の拡張
mat = {{1, 2}, {3, 4}};PadLeft[mat, {4, 4}]//MatrixFormPadRight[mat, {4, 4}]//MatrixFormmat = {{1, 2, 3}, {4, 5, 6}};
PadRight[mat, {4, 9}, mat]%//MatrixForm転置
mat = {{1, 2, 3}, {4, 5, 6}};
mat//MatrixFormTranspose[mat]%//MatrixFormmat = {{1., -I}, {I, 10.}};
matCT = ConjugateTranspose[mat]mat === matCTHermitianMatrixQ[mat]要素の回転
m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
m//MatrixFormRotateLeft[m, 1]//MatrixFormRotateLeft[m, {0, 1}]//MatrixFormRotateRight[m, {0, 1}]//MatrixForm行列のテスト
Wolfram言語には行列をテストし,サイズ情報を得るための関数が数多く存在する.
| MatrixQ[expr] | expr が行列ならばTrueを返し,行列でなければFalseを返す |
| Dimensions[expr] | ベクトルまたは行列の大きさのリスト |
| mi==mj | 2つの行列の要素を比較して,行列が等しいかどうかを調べる |
MatrixQ[{{1, 2, 3}, {4, 5, 5}}]MatrixQ[ 5]MatrixQ[ {{1, 2, 3}, {4, 5}}]MatrixQ[{{2, 2, 3}, {4, 5, 6}}, IntegerQ]MatrixQ[{{2, 2, 3}, {4, 5, 6}}, IntegerQ[#] && # > 1 &]Dimensions[{{1, 2, 3}, {4, 5, 6}}]mat1 = {{1, 2}, {4, 5}};
mat1 == mat1mat1 == N[mat1]EqualはどのようなWolfram言語式についても使用できる.行列の属性を使って総括的に2つの行列が等しいかどうか比較する場合は,行列のノルムを比較する方がよいことがある.これについては後のセクションで述べる.
その他の構造操作
このセクションでは,行列を扱う上で役に立つその他の構造操作について述べる.
| Flatten[m] | ネストしたリスト m をフラットにする |
| Flatten[m,n] | ネストしたリスト m をレベル n までフラットにする |
| Partition[m,n] | m を長さ n のサブリストに分割する |
| Join[m1,m2] | m1と m2を連結する |
| Append[m,r] | 行 r を m の最後に挿入する |
| Prepend[m,r] | 行 r を m の最初に挿入する |
mat = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};vec = Flatten[mat]Partition[vec, 4]Join[ mat, mat]Join[ mat, mat, 2]Append[mat, {x, x, x}]この操作はInsertを使っても行える.「行と列の挿入」を参照のこと.
要素の操作
mat = Table[Random[], {i, 3}, {j, 3}];
mat//MatrixFormmat + 52 matmat^2mat ^ 2 / matSin[mat]mat + matmat + {{1, 2}, {2, 3}}mat + {x, y, z}mat1 = {{1, 2}, {3, 4}};
mat2 = {{2, 2}, {3, 3}};
mat1 mat2リストへの縫込み
SetAttributes[fun, Listable];
fun[x_] := x ^ 2 / 3mat = {{1., 4.}, {4., 5.}};fun[ mat]fun[{{1, 2}, {x, 4}}]マップ
mat = {{1., 4.}, {4., 5.}};Map[f, mat, {-1}]Map[# ^ 2 / 3 &, mat, {-1}]ベクトルとテンソル
Wolfram言語では行列の他に,ベクトルとテンソルもサポートされている.これらはすべてリストから作成する.「Wolfram言語における線形代数入門」でも述べたが,Wolfram言語ではテンソルとは一般化された行列を表す.行列を作成する操作はすべて,ベクトルとテンソルに対しても使えるように一般化できる.Wolfram言語のベクトルは1レベルのリストである.
vec = {1, 2, 3}| Table[f,{i,n}] | f を i=1,2,… ,n について評価して長さ n のベクトルを作成する |
| Array[a,n] | {a[1],a[2],…}という形の長さ n のベクトルを作成する |
| Range[n] | リスト{1,2,3,… ,n}を作成する |
| Range[n1,n2] | リスト{n1,n1+1…,n2}を作成する |
| Range[n1,n2,dn] | リスト{n1,n1+dn …,n2}を作成する |
Range[10]Range[1., 4, 0.1]vec = Table[Random[], {5}]vec = Sqrt[Range[5] / 2.]vec + 4vec[[2]]vec[[4]] = x;
vecWolfram言語には行ベクトル・列ベクトルという概念はないということに注意されたい.Wolfram言語におけるベクトルとは,要素をあらわす指標が1つのものをいう.
tensor = Table[1 / (i j k), {i, 2}, {j, 3}, {k, 4}]tensor[[1, 2, 1]]ベクトルとテンソルのテスト
Wolfram言語には,ベクトルやテンソルのテストと,サイズ情報の抽出のためのさまざまな関数がある.
| VectorQ[expr] | expr がベクトル形式である場合はTrueを,それ以外はFalseを返す |
| MatrixQ[expr] | expr が行列形式である場合はTrueを,それ以外はFalseを返す |
| ArrayQ[t,n] | t が階数 n のテンソルであるかどうかをテストする |
| Dimensions[expr] | ベクトルまたは行列の次元のリストを返す |
| ArrayDepth[t] | テンソルの階数を求める |
| ti==tj | 2つのテンソルの要素が等しいかどうかを比較する |
MatrixQ[{{1, 2, 3}, {4, 5, 5}}]VectorQ[{1, 2, 3}]ArrayQ[ {{{1, 2}, {3, 4}}, {{4, 5}, {6, 7}}}]ArrayQ[ {{{1, 2}, {3, 4}}, {{4, 5}, {6, 7}}}, 3]ArrayQ[ {{{x, 2}, {3, 4}}, {{4, 5}, {6, 7}}}, 3, NumberQ]Dimensions[{{{1, 2}, {3, 4}}, {{4, 5}, {6, 7}}}]ArrayDepth[ {{1, 2, 3}, {4, 5, 6}}]ten = {{{1, 2}, {3, 4}}, {{4, 5}, {6, 7}}};
ten == tenten == N[ten]ten == {1, 2, 3}行列の可視化
このセクションでは行列のフォーマットとプロットのための関数について述べる.
| MatrixForm[mat] | 行列の要素を二次元配列形式で表示する |
| MatrixPlot[mat] | mat の構造的パターンを示す |
行列のフォーマット
mat = {{a, b}, {c, d}};
MatrixForm[mat]MatrixForm[ Array[ m, {3, 2, 2}]]行列のプロット
mat = RandomInteger[{0, 1}, {10, 10}];
mat//MatrixFormMatrixPlot[mat]MatrixPlotには,プロットの外観を調整するための数多くのグラフィックスオプションがあり,その多くがWolfram言語DensityGraphicsオブジェクトの一般的なオプションである.行列の最大表示サイズを指定する特殊オプションMaxPlotPointsもある.このサイズより大きい行列はダウンサンプリングされる.
オプション名
|
デフォルト値
| |
| MaxPlotPoints | 200 | 表示する行列の最大サイズ |
| AspectRatio | 1 | 最終的な図形のスケール |
| ColorRules | Automatic | 各要素の色 |
| ColorFunction | Automatic | 各要素の色 |
| Mesh | False | 罫線描画の有無 |
| MeshStyle | GrayLevel[1] | 罫線スタイル |
MatrixPlotのオプション
n = 10000;
nz = 2000;
sp = SparseArray[
RandomInteger[{1, n}, {nz, 2}] -> Table[1, {nz}], {n, n}];
sp = sp + Transpose[sp]MatrixPlot[sp, MaxPlotPoints -> 100]MatrixPlot[RandomInteger[{0, 1}, {50, 50}], Mesh -> True, MeshStyle -> White]MatrixPlot[RandomInteger[{0, 1}, {50, 50}], ColorRules -> {0 -> White, 0. -> White, _ -> Black}]MatrixPlot[RandomInteger[{0, 1}, {50, 50}], ColorFunction -> (RGBColor[#, 0, 0]&)]行列のインポートとエキスポート
このセクションでは行列のインポートとエキスポートに使う関数について述べる.
Wolfram言語にはインポート・エキスポートのためのさまざまなツールがある.後で同僚がWolfram言語で作業を続けられるようにデータをファイルに保存したいときは,ファイルに含まれるWolfram言語式が処理できる関数を使った方がよい.これについては「式の入出力」で述べる.
$ImportFormatsFilePrint["LinearAlgebraExamples/Data/simplematrix.dat"]Import["LinearAlgebraExamples/Data/simplematrix.dat", "Table"]Export["fileout.dat", {{1, 2}, {3, 4}}, "Table"]FilePrint["fileout.dat"]Export["filecsvout.dat", {{1, 2}, {3, 4}}, "CSV"]FilePrint["filecsvout.dat"]この他の行列形式もある.例えばHarwell-Boeingは疎行列に使われ,Matrix Marketは密・疎行列ともに使われる.これについては,「疎行列のインポートとエキスポート」で述べる.また,MAT行列形式とFITS天文データ形式も有用なインポート・エキスポート形式である.
行列の掛け算
mat = {{1, 2}, {3, 4}};mat.matmat.{4, 5}mat1 = {{1, 2, 3}, {4, 5, 6}};
mat2 = {{4, 1}, {5, 6}, {3, 1}};mat1.mat2mat2.mat1mat1.{1, 2}vec = {1, 2, 3};
vec.vecmat1.vecvec.mat2行列の掛け算の定義は,2つの行列
,
の積
は以下のような
になるというものである.
2つの任意の階数のテンソル
,
の積
が次のようになるように,定義を一般化する.
そのため,Dotを階数
のテンソルと階数
のテンソルに適用すると,結果は階数
のテンソルとなる.以下に例を示す.
tensor1 = { {{1, 2, 3, 4}, {4, 5, 6, 7}, {4, 5, 6, 7}}, {{1, 2, 3, 9}, {1, 2, 6, 5}, {1, 2, 6, 5}}};
tensor1//MatrixFormtensor2 = { {{1}, {4}}, {{7}, {1}}, {{8}, {3}}, {{9}, {1}}};
tensor2//MatrixFormtensor1.tensor2//MatrixFormDimensions[%]外積
vec1 = {a, b, c};
vec2 = {x, y, z};
Outer[Times, vec1, vec2]//MatrixFormOuter[f, {a, b, c}, {ap, bp}]//MatrixForm外積の可視化
pts = Table[{Sin[t], Cos[t]}, {t, 0, 2Pi, Pi / 8.}];Show[Graphics[Outer[Line[ {##}]&, pts, pts, 1]], AspectRatio -> Automatic]一般化された内積
行列の掛け算は線形代数計算の基本的な操作である.そのため,Wolfram言語には最適化された専用の関数Dotがある.また,これを一般化したものがInnerである.Innerを使うと,積を形成するのに使用する演算が2種類の中から指定できる.
vec1 = {a, b, c};
vec2 = {x, y, z};vec1.vec2Inner[Times, vec1, vec2, Plus]Inner[Power, vec1, vec2, Plus]行列の置換
行列演算の多くは,行列を特定の方法で並べることで行われる.例えば,演算技術の中には対角に要素を置くように行列の並べ替えを試みるものや,特定の要素を密ブロックのグループにまとめようとするものがある.Wolfram言語関数Partは行列の行や列の置換に非常に適した関数である.
| m[[perm]] | 行列の行に置換を適用する |
| m[[All,perm]] | 行列の列に置換を適用する |
| m[[perm,perm]] | 行列の行と列に置換を適用する |
| m[[perm]]=m | 行列の行に逆置換を適用する |
| m[[All,perm]]=m | 行列の列に逆置換を適用する |
mat = Table[Random[Integer, {0, 3}], {4}, {4}];
mat//MatrixForm行が2-ノルムの大きさの増加列となるように行列を並べ替える(ノルムについては「行列の計算:ノルム」で述べる).
Map[ Norm, mat]perm = Ordering[%, All, Less]pmat = mat[[perm]];
pmat//MatrixFormpmat[[perm]] = pmat;
pmat//MatrixFormpmat == mat置換行列
mat = RandomInteger[{0, 3}, {4, 4}];
mat//MatrixFormperm = Ordering[Map[Norm, mat], All, Less]sp = SparseArray[{i_, i_} -> 1, {4, 4}]permMat = sp[[perm]]pmat = permMat.mat;
pmat//MatrixFormTranspose[permMat].pmat//MatrixForm一般に,置換にはWolfram言語関数Partを使用した方が速い.しかし置換行列の方が便利なこともあるだろう.
関連するテクニカルノート
-
▪
- Wolfram言語における線形代数 ▪
- 行列とテンソルの操作 ▪
- 疎行列(スパース行列)を使う ▪
- 行列の計算 ▪
- 行列の型