中身が2行だけ書かれた,以下のMATLABプログラムについて解説していきます.
function W = SLD(H,M)
W = nchoosek(1:H+M-1,M-1) - repmat(0:M-2,nchoosek(H+M-1,M-1),1) - 1;
W = ([W,zeros(size(W,1),1)+H]-[zeros(size(W,1),1),W])/H;
end
前編,中編で準備が整いました.後編では,いよいよプログラムの解説に入ります.
\(H=4\),\(M=3\)を例にプログラムを解説します.処理を1個ずつ進めながら,プログラムの変化を見ていきます.1行目,2行目で分けて考えます.
処理開始前.初期状態.
W = nchoosek(1:H+M-1,M-1) - repmat(0:M-2,nchoosek(H+M-1,M-1),1) - 1;
最初に,プログラムを以下のように変形します.
A = nchoosek(1:H+M-1,M-1);
B = repmat(0:M-2,nchoosek(H+M-1,M-1),1);
W = A - B - 1;
次に,括弧の中でカンマで区切られた要素の四則演算をします.
A = nchoosek(1:6,2);
B = repmat(0:1,nchoosek(6,2),1);
W = A - B - 1;
次に,括弧の中でカンマで区切られた要素について,コロン演算子(:)を適用し行ベクトルを作成します.
A = nchoosek([1 2 3 4 5 6],2);
B = repmat([0 1],nchoosek(6,2),1);
W = A - B - 1;
次に,nchoosek
を利用して,行ベクトル[1 2 3 4 5 6]
から2
要素取り出す組み合わせを計算します.
A = [[1 2];[1 3];[1 4];[1 5];[1 6];[2 3];[2 4];[2 5];[2 6];[3 4];[3 5];[3 6];[4 5];[4 6];[5 6]];
B = repmat([0 1],nchoosek(6,2),1);
W = A - B - 1;
結果,\(A\)は15行2列の行列になります.散布図としてプロットすると以下が得られます.
次に,nchoosek
を利用して,6
個の対象から2
個選ぶ選び方の総数,二項係数を計算します.
A = [[1 2];[1 3];[1 4];[1 5];[1 6];[2 3];[2 4];[2 5];[2 6];[3 4];[3 5];[3 6];[4 5];[4 6];[5 6]];
B = repmat([0 1],15,1);
W = A - B - 1;
次に,repmat
を利用して,行ベクトル[0 1]
のコピーを作成します.\(B\)も15行2列の行列になります.
A = [[1 2];[1 3];[1 4];[1 5];[1 6];[2 3];[2 4];[2 5];[2 6];[3 4];[3 5];[3 6];[4 5];[4 6];[5 6]];
B = [[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1];[0 1]];
W = A - B - 1;
次に,同じ要素数の行列\(A\),\(B\)の各要素について,引き算をします.
W = [[1 1];[1 2];[1 3];[1 4];[1 5];[2 2];[2 3];[2 4];[2 5];[3 3];[3 4];[3 5];[4 4];[4 5];[5 5]] - 1;
そして,行列の各要素を-1します.
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
以上で,1行目の処理が全て終了し,15行2列の行列\(W\)が作成されます.散布図としてプロットすると以下が得られます.
処理開始前.初期状態.
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
W = ([W,zeros(size(W,1),1)+H]-[zeros(size(W,1),1),W])/H;
最初に,プログラムを以下のように変形します.
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
C = zeros(size(W,1),1);
D = C+H;
E = [W,D];
F = [C,W];
W = (E-F)/H;
次に,size
を利用して,行列\(W\)の行数を計算します.
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
C = zeros(15,1);
D = C+H;
E = [W,D];
F = [C,W];
W = (E-F)/H;
次に,\(C\)を計算します.(zeros
を利用して,すべての要素が0の列ベクトルを作成します.)
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
C = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]';
D = C+H;
E = [W,D];
F = [C,W];
W = (E-F)/H;
次に,\(D\)を計算します.(列ベクトル\(C\)の各要素を+\(H\)(=4)します.)
W = [[0 0];[0 1];[0 2];[0 3];[0 4];[1 1];[1 2];[1 3];[1 4];[2 2];[2 3];[2 4];[3 3];[3 4];[4 4]];
C = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]';
D = [4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]';
E = [W,D];
F = [C,W];
W = (E-F)/H;
次に,\(E\)と\(F\)を計算します.(同じ行数である\(W\)と\(D\),\(C\)と\(W\)を水平連結します.)
E = [[0 0 4];[0 1 4];[0 2 4];[0 3 4];[0 4 4];[1 1 4];[1 2 4];[1 3 4];[1 4 4];[2 2 4];[2 3 4];[2 4 4];[3 3 4];[3 4 4];[4 4 4]];
F = [[0 0 0];[0 0 1];[0 0 2];[0 0 3];[0 0 4];[0 1 1];[0 1 2];[0 1 3];[0 1 4];[0 2 2];[0 2 3];[0 2 4];[0 3 3];[0 3 4];[0 4 4]];
W = (F-G)/H;
最後に,行列を引き算し,各要素を\(H\)で割って正規化します.
これで,単位超平面に均一分布する点群SLDが得られます.
$$
W\quad=\quad\left(
\begin{matrix}
[0\ 0\ 4]\cr
[0\ 1\ 4]\cr
[0\ 2\ 4]\cr
[0\ 3\ 4]\cr
[0\ 4\ 4]\cr
[1\ 1\ 4]\cr
[1\ 2\ 4]\cr
[1\ 3\ 4]\cr
[1\ 4\ 4]\cr
[2\ 2\ 4]\cr
[2\ 3\ 4]\cr
[2\ 4\ 4]\cr
[3\ 3\ 4]\cr
[3\ 4\ 4]\cr
[4\ 4\ 4]\cr
\end{matrix}\;-\;\;
\begin{matrix}
[0\ 0\ 0]\cr
[0\ 0\ 1]\cr
[0\ 0\ 2]\cr
[0\ 0\ 3]\cr
[0\ 0\ 4]\cr
[0\ 1\ 1]\cr
[0\ 1\ 2]\cr
[0\ 1\ 3]\cr
[0\ 1\ 4]\cr
[0\ 2\ 2]\cr
[0\ 2\ 3]\cr
[0\ 2\ 4]\cr
[0\ 3\ 3]\cr
[0\ 3\ 4]\cr
[0\ 4\ 4]\cr
\end{matrix}
\right)\;/\;4\quad=\quad
\left(
\begin{matrix}
[0\ 0\ 4]\cr
[0\ 1\ 3]\cr
[0\ 2\ 2]\cr
[0\ 3\ 1]\cr
[0\ 4\ 0]\cr
[1\ 0\ 3]\cr
[1\ 1\ 2]\cr
[1\ 2\ 1]\cr
[1\ 3\ 0]\cr
[2\ 0\ 2]\cr
[2\ 1\ 1]\cr
[2\ 2\ 0]\cr
[3\ 0\ 1]\cr
[3\ 1\ 0]\cr
[4\ 0\ 0]\cr
\end{matrix}
\right)\;/\;4\quad=\quad
\begin{matrix}
[\quad\ 0\quad\ \ \ 0\quad\ \ \ 1]\cr
[\quad\ 0\ \ 0.25\ \ 0.75]\cr
[\quad\ 0\quad0.5\quad0.5]\cr
[\quad\ 0\ \ 0.75\ \ 0.25]\cr
[\quad\ 0\quad\ \ \ 1\quad\ \ \ 0]\cr
[0.25\quad\ \ \ 0\ \ 0.75]\cr
[0.25\ \ 0.25\quad0.5]\cr
[0.25\quad0.5\ \ 0.25]\cr
[0.25\ \ 0.75\quad\ \ \ 0]\cr
[\ \ 0.5\quad\ \ \ 0\quad0.5]\cr
[\ \ 0.5\ \ 0.25\ \ 0.25]\cr
[\ \ 0.5\quad0.5\quad\ \ \ 0]\cr
[0.75\quad\ \ \ 0\ \ 0.25]\cr
[0.75\ \ 0.25\quad\ \ \ 0]\cr
[\quad\ 1\quad\ \ \ 0\quad\ \ \ 0]\cr
\end{matrix}
$$
以上で,プログラムは終了です.
解説するのはたった2行なのに,3つに分割する必要があるほど内容が膨らんで自分でも驚きました.基礎の基礎から解説したため,MATLABに全く触れたことがない人でも理解できる記事が書けたと思います.普段なら関数の入出力を説明して,前編の内容で解説を終えることが多いです.しかし,技術者ブログということで,関数の中の処理も頑張って解説しました.
MATLABは,非常に短く簡潔にプログラムが書ける利点があります.それが,今回解説した2行のプログラムに良く表れていると思います.また,MATLABは,日本語で書かれた公式のドキュメント,教材が充実しており,学習も非常にしやすいです.更に,公式が提供するファイル共有サイト,GitHubに多数のコードが公開されています.ぜひ一度,MATLABを触ってみてください.
最後に,この内容を更に詳しく知りたいという方は,元のプログラムを眺めてみることをお勧めします.論文も2本,Referenceとして紹介されています.
以上です.