APL 高次元へのアナロジー
ぼくは、ふと、APL の高次元アレイというものを頭のなかに描いてみた。
簡単なところから、スカラ、ベクトル、マトリックスと進んで、もう一つ 3 次元アレイの名前がほしくなった。それでぼくはそれを「キューブ」と呼ぶことにした。イメージとしては、マトリックスの後ろ側に次のマトリックス、その次のマトリックスと続いており、それが 10面も続けばキューブのように見えるだろう。
つまりこれで、アレイ(Array)の特定次元までのネーム・シュガーが、スカラ(Scalar)、ベクトル(Vector)、マトリックス(Matrix)、キューブ(Cube)ということになったのだ。
ネームシュガーというのぼくもは聞いたことがないが(勝手に作ったね)、愛称的な意味だね。ぼくなんかも本名は「まじん」だけど、「まーくん」って呼ばれるからね。楽天優勝おめでとう!
さて、APL の高次元は理論物理学のそれとは違って、すべて 3 次元空間でイメージできるものだ。そして実用的なものなのだ。今回の定義によって APL とはキューブを演算するための言語だと言ってもよいかもしれないとぼくは思っている(おいおい)。なお、APL ではすべての次元の操作対象をアレイ(Array)と呼ぶことにしている。キューブは 3次元アレイだと言える。
ぼくは頭のなかで APL の高次元アレイをイメージしてみたが、12次元までは自然にイメージできることに気づいた。4 次元はキューブが横に並んだもの。言うならば、キューブを要素とするベクトルだ。
これは、キューブ・ベクトルが縦にも並んでマトリックスになっている。だから、キューブ・マトリックス。こんな感じで 12 次元までイメージしてみた。
こんな感じ。
6 次元アレイはキューブ・キューブと呼べばいいのだけど、この後、キューブ・キューブ・キューブとかキューブ・キューブ・キューブ・キューブなんかが出てくることになるのだ。それはそれで合理的なんだけど、上のようにあと2つだけ新しい呼び名を導入してみよう。
それがブロックとコンテナだ。大体、12 次元アレイのコンテナ・キューブまではイメージしやすいので、ここ以降が必要なら、コンテナ・キューブ・ベクトル、コンテナ・キューブ・マトリックス、コンテナ・キューブ・キューブ、..と永遠に続くだろう。しかし、もちろん、APL の処理系がどこまで対応できるかによる。
さて、APL という言語はこういう高次元のデータをひとつの演算子で一度にグオ~ン・グオ~ンと 処理してくれるわけだ。ぼくはこのグオ~ン・グオ~ンという音を実際に聞いたことが何度かあるのだ。(ウソ)
さてさて、まじめに考えてみよう。
コンテナ・ベクトルとか言えば、その次元数が直ぐにイメージできる。しかし、その並びのイメージは APL の操作と整合しているのだろうか。
どうなんだろうね。
アレイを繋ぐ演算子「,」をつかってその構造を調べてみることにしよう。
まずは、要素が 1 ばかりのマトリックス M1 と要素が 2 ばかりのマトリックス M2 を繋いでみる。
⎕←M1←2 2⍴1
1 1
1 1
⎕←M2←2 2⍴2
2 2
2 2
M1,M2
1 1 2 2
1 1 2 2
M1,[2]M2
1 1 2 2
1 1 2 2
M1,[1]M2
1 1
1 1
2 2
2 2
単に「,」を使うと最後の次元で繋ぐ。[2] を指定しても同じこと。見てのとおり横に繋がれる。[1] を指定すると縦に繋がれるのだ。
まぁ、マトリックスの場合は簡単だけど、これがキューブになるとどうなるのか。
やってみよう。(⍝ のあとはコメント)
⎕←C1←2 2 2⍴1
1 1
1 1
1 1
1 1
⎕←C2←2 2 2⍴2
2 2
2 2
2 2
2 2
C1,[3]C2 ⍝ 単に C1,C2 としたのと同じ
1 1 2 2
1 1 2 2
1 1 2 2
1 1 2 2
C1,[2]C2
1 1
1 1
2 2
2 2
1 1
1 1
2 2
2 2
C1,[1]C2
1 1
1 1
1 1
1 1
2 2
2 2
2 2
2 2
行喰うなぁ。:P
さて、これをどう見るか。
APL では [3] のように一番大きな数が一番小さな次元を示す。だから横方向に繋ぐ。次の [2] では縦方向に繋ぎ、最後の [1] でキューブを繋ぐ。またこのことは、 [3] では各ベクトルを繋ぎ、[2] では各マトリックスを繋ぎ、[1] では各キューブを繋いだと解釈できるのではないだろうか。この辺りは、ぼく自身まだ検討が十分ではなかったが正しいように思える。
この辺りの仕組みをもう一つの例を使って見てみたい。
CV←2 3 4 5⍴0
⍴CV
2 3 4 5
CV
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
CV の次元ベクトルは上で見たとおり「2 3 4 5」だ。これは、次元ベクトルの後ろから見ていって、5列、4行、3面、2体 のキューブ・ベクトルと言うことだ。つまり、上の例のキューブ・ベクトルは「2体 3面 4行 5列」の構造を持つと言える。このように捉えると APL のアレイの構造がよくわかると思う。
また、新しい用語を作って使用したが、面とはマトリックスで、体とはキューブのことだ。キューブにせよ、面、体にせよ、APL の理解を易しくするための工夫なのだ。
次に、2つのキューブ・ベクトルを繋いで詳しく調べてみたい。
⍝ 次元 [4] で繋ぐ
CV1←2 2 2 2⍴⍳16
CV2←2 2 2 2⍴⍳16
CV0←2 2 2 2⍴⍳16,2 2 2 2⍴⍳16 ⍝ 次元を指定した CV1,[4]CV2 と同じ
CV0
1 2 1 2
3 4 3 4
5 6 5 6
7 8 7 8
9 10 9 10
11 12 11 12
13 14 13 14
15 16 15 16
⍝ 上の結果は、それぞれのベクトル同士を繋いだ。
⍝ 次元 [3] で繋ぐ
CV1←2 2 2 2⍴⍳16
CV2←2 2 2 2⍴⍳16
CV0←2 2 2 2⍴⍳16,[3]2 2 2 2⍴⍳16
CV0
1 2
3 4
1 2
3 4
5 6
7 8
5 6
7 8
9 10
11 12
9 10
11 12
13 14
15 16
13 14
15 16
⍝ 上の結果は、それぞれのマトリックス同士を繋いだ。
⍝ 次元 [2] で繋ぐ
CV1←2 2 2 2⍴⍳16
CV2←2 2 2 2⍴⍳16
CV0←2 2 2 2⍴⍳16,[2]2 2 2 2⍴⍳16
CV0
1 2
3 4
5 6
7 8
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
9 10
11 12
13 14
15 16
⍝ 上の結果は、それぞれのキューブ同士を繋いだ。
⍝ 次元 [1] で繋ぐ
CV1←2 2 2 2⍴⍳16
CV2←2 2 2 2⍴⍳16
CV0←2 2 2 2⍴⍳16,[1]2 2 2 2⍴⍳16
CV0
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
⍝ 上の結果は、それぞれのキューブ・ベクトル同士を繋いだ。
これは CV1 全体の後ろに CV2 全体を続けた結果を表示しただけと言える。
今回のような高次元アレイの演算は、繋ぐ演算子「,」だけではなく APL の他の演算子にも応用の利く考え方だと思う。
最後に、これはただのお遊びとしか言えないかも知れないが、12次元アレイであるコンテナ・キューブを繋いでみた。
CTC1←2 2 2 2 2 2 2 2 2 2 2 2⍴⍳4096 ⍝ コンテナ・キューブ 1
CTC2←2 2 2 2 2 2 2 2 2 2 2 2⍴⍳4096 ⍝ コンテナ・キューブ 2
CTC0←CTC1,CTC2 ⍝ 2つのコンテナ・キューブ 1 と 2 を繋いだ
1 2 1 2
3 4 3 4
5 6 5 6
7 8 7 8
.....
..........
....................
..... APL は全部で 4048 行のデータを表示した(空行含む)
....................
..........
.....
4089 4090 4089 4090
4091 4092 4091 4092
4093 4094 4093 4094
4095 4096 4095 4096
これはなにをしたかということをもう一度言えば、12次元アレイと12次元アレイを繋ぐ演算をしたのだ。
ぼくは今回、高次元アレイの実際の操作と、ぼくの頭に描いた高次元アレイへのアナロジーとの関係性というか整合性を検証しようと思ったのだが、考えていたとおりの結果ではないかと思っている。
なお、今回の内容は、すべて NARS2000 で動作させたものである。