カオスゲーム

 昨日の非線形振動論でカオスゲームの話題が出ていたので、昔作ったプログラムを引っ張りだしてきました。


 カオスゲームとは

正三角形の各頂点をA,B,Cとし、点P(i)が最初、頂点Aにあるものとする。サイコロを振って、1,2のときはA、3,4のときはB、5,6のときはCとP(i)の中点をP(i+1)とする。P(i)に点をうっていくとどのような図形が描かれるか。

というもの。実際のカオスゲームは正三角形じゃなく、任意の多角形、任意の内分比でできます。


 さて、描かれる図形はどうなるでしょうか。


 実は次のような図形が描かれます。

 きれいですね。これはシェルピンスキーのギャスケットと呼ばれる図形です。


 他の正N角形, 内分比q:1-qでどうなるかもやってみました。


N=5, q=0.38


N=6, q=0.33


 N=6の図形が個人的にお気に入りで、中央の黒い部分を図形として注目すると、コッホ雪片と呼ばれる図形になっています。コッホ雪片は、

線分を3等分し、分割した2点を頂点とする正三角形の作図を無限に繰り返すことによって得られる図形である。(wikipedia)


 これからわかるように、n+1回目の図形の周の長さはn回目の図形の周の長さの4/3倍です。つまり、n回目の図形の周の長さは最初、一辺が1の正三角形だったとして、3*(4/3)^{n-1}になります。これをn→∞に飛ばすので、当然、周の長さも∞になります。しかしながら、見て分かる通り、コッホ雪片は有限の面積を囲みます。無限の周に囲まれた、有限の面積。不思議な図形です。


 プログラムのソースコードも載せておきます。Processingを使って書いています。winの場合、ダウンロードしてzipを展開して、起動した画面にコピペしてスタートボタン押すだけなので簡単です。

int N = 3; //正N角形
float q = 0.5; //内分比

//これより下はいじらなくておk

int r = 200;

PVector[] v; //頂点
PVector p; //ジャンプする点

void setup(){
  //基本設定
  background(0);
  size(500,500);

  //頂点登録
  v = new PVector[N];
  for(int i=0; i<N; i++){
    v[i] = new PVector(width/2+r*sin(i*TWO_PI/N), height/2-r*cos(i*TWO_PI/N));
  }

  //Pの初期値は頂点上  
  p = v[0];
}

void draw(){
  //点を打つ
  stroke(255);
  point(p.x, p.y);

  //ジャンプする先を決める
  PVector vs = v[(int)random(0,N)];
  
  //内分点の計算
  PVector vp = PVector.mult(p,q);
  PVector vg = PVector.mult(vs,1-q);
  p = PVector.add(vp,vg);
}


 Nに正何角形か、qに内分比q:1-qはいくらかということを代入して、あとはじーっと眺めるだけで、だんだんと図形が作られて行きます。お試しあれ。