5.確率的L-system
次の2つの写真をみてください。
どちらも、きれいに枝分かれしているように見えます。しかし、左側に比べると、右側の方は枝の長さや比率にばらつきがあります。
「5.樹を描く」で描いたのは、左側のように規則的に成長した図でした。(それでも実際には少しばらつきがあります)
このように、ある規則にしたがっているために、先の方まで予測できるものは「決定論的(deterministic)」といいます。これに対して、ばらつきがありながら、それでも数学的に記述できる場合、「確率的(stochastic)」といいます。つまり、「ばらつき」を確率としてとらえるのです。
リンデンマイヤーの「The Algorithmic Beauty of Plants」には、「Stocastic L-system」として次のような例が載っています。
3つのジェネレータを用意し、それぞれ確率3分の1で置き換えを行なうのです。
確率3分の1で F→F[+F]F[−F]F
確率3分の1で F→F[+F]F
確率3分の1で F→F[−F]F
すると次のように、実行するたびに生成される図が違ってきます。(少しずらして3回実行した結果)
この節では、成長過程においていくつかのパターンを確率的に選択しながら成長していくシステムを作ります。
まず、「確率3分の1」をどのように発生させるかですが、このようなときは「乱数」を用います。CindyScriptでは、乱数を発生する関数がいくつか用意されています。ここでは randomint() という関数を用いるのがよいでしょう。
--------------------------------------------
p=randomint(3)
--------------------------------------------
とすると、0,1,2の3つの数がランダムに発生してpの値となります。3つの数字のどれかなので、それぞれの数になる確率が3分の1になるのです。この「乱数発生」についてのスクリプトの作り方は、「乱数の発生」というページに少し詳しく書きました。
さて、3つのジェネレータを用意しましょう。それにはリストを用います。
generatorlist=[[["F","F[+F]F[-F]F"]],[["F","F[+F]F"]],[["F","F[-F]F"]]];
少しややこしいですが、括弧の数に注意してください。1つのジェネレータはリストで変換規則を記述したものです。
F→F[+F]F[−F]F
という変換規則は [["F","F[+F]F[-F]F"]] です。ジェネレータの変換規則は複数個をリストにして記述できますので、1つだけなら、1つだけの要素からなるリストということで、括弧は2つになるのです。これらのジェネレータを3つリストにしたのが上の generatorlist です。
さて、この中から、乱数でどれかを選びます。randomint(3) で0,1,2の乱数ができるので、これに1を足してpとします。
p=randomint(3)+1
一般化するには、length() 関数を用いて、リストの個数を数えます。
len=length(generatorlist);
p=randomint(len)+1
リストのp番目を取り出すには、アンダーバーを使います。
s=replace(s,generatorlist_p);
とすれば、generatorlist の中からp番目の要素(変換規則)をとり出して、文字列sをその変換規則で置き換えます。
この作業をする関数を次のように定義して、Initializationスロットに追加します。
-----------------------------------------------------------------------------------------------------------------------
// initiator と generatorlist から乱数でコマンド列を作成する
makecomprob(n):=(
workstr=initiator;
len=length(generatorlist);
repeat(n,
p=randomint(len)+1;
workstr=replace(workstr,generatorlist_p);
);
);
-----------------------------------------------------------------------------------------------------------------------
こうしてできたコマンド列sを、tree( ) 関数で表示します。
「5.樹を描く」で作ったスクリプトの Draw スロットの内容を書き換えて実行してみましょう。
一つ描いたあと少し移動するには、直接亀を少しだけ動かします。たとえば、
・最初に上を向く
・木を1本描く
・横に向きを戻して、少し進む
という動作をまとめて何回か繰り返します。次の図では6回繰り返しています。
ここまでは、リンデンマイヤーの本にしたがって、3つのジェネレータを3分の1の確率で選ぶことをやってみました。
この他に、次のようなことが考えられるでしょう。
・ジェネレータを増やす。選ばれる確率を変える。
・角度もいくつか用意して確率で選ぶ。
・枝の長さをいくつか用意して確率で選ぶ。
< 戻る >