ソフトの砂場(Bugsシミュレータ)

最終更新日:1998年11月28日

今回は,簡単な遺伝子を持つ虫が,進化する様子を見るシミュレータを作ってみます.遺伝子の初期値のせいで最初はでたらめに動き回る虫が,次第に生存に適したものに進化していく様子が観察できます.いつものように,起動してパラメータをセットした後は,ひたすらボーっとながめるプログラムです.

Bugsシミュレータの画面

仕様

このシミュレータ内には,虫とバクテリアだけが存在します.虫はバクテリアを食べ,バクテリアは自然発生します.虫はそれぞれエネルギーを持ち,1単位時間でエネルギーを1消費して,1ステップ移動します.虫が持つエネルギーが0になると,その虫は死亡します.また虫は一定の単位時間生存すると,2匹に分裂可能になります.ただし分裂するためには,一定のエネルギーを持っている必要があります.虫が分裂すると,それまで存在していた虫は消滅し,新たに2匹の虫が誕生したと考えます.虫は,死亡も分裂もしなければ,ずっと生き続けることができます.移動先にバクテリアがいれば,虫はそのバクテリアを食べて一定のエネルギーを得ることができます.ただし,虫が保有できる最大エネルギーは決まっており,バクテリアを食べ続けてもそれを越えるエネルギーを持つことはできません.移動や分裂の結果,同じ位置に複数の虫が存在することができます.複数の虫が同じ位置に移動した場合,移動先にバクテリアがいれば,最初に移動した虫がバクテリアを全て食べ,二番目以降の虫はバクテリアを食べません.

虫が移動するとき,その移動方向は遺伝子を元にした確率に基づいて決まります.遺伝子として,前・右前・右後・左前・左後・後の6つがあり,その値が大きい方に方向転換しやすくなります.それぞれの虫には,その時々に進んでいる向きがあり,その向きと方向転換する先を組み合わせた方向に進みます.

虫が分裂すると,親は消滅し,親と同じ位置で2匹の子になります.子は親のエネルギーの半分と遺伝子を受け継ぎますが,6つある遺伝子のうちランダムに選ばれた1つだけは,値がランダムな値だけ増減します. 1匹の子のある遺伝子の値がある値だけ増加したら,もう1匹の子の同じ遺伝子の値は同じ値だけ減少します.

バクテリアは,初期状態でランダムな位置に存在し,さらに適当なタイミングでランダムな位置に発生します.同じ位置に複数のバクテリアが存在することができます.バクテリアは移動せず,また分裂することも死ぬこともありません.

虫の状態を色で表すことにします.分裂可能なエネルギーを持つ場合は黄色,分裂可能な年齢の場合は赤色,エネルギーが残り少ない場合は水色,それ以外は白色で表します.バクテリアには状態がないので,紫色だけです.

パラメータ

上の仕様に書かなかったパラメータを,以下のようにします.ただし,これらの値は変更可能なように実装することにします.

虫の初期数
10
虫の初期エネルギー
1000
虫の最大エネルギー
1500
虫が分裂可能になる時間
100単位時間
虫がバクテリアを1匹食べたときに得られるエネルギー
50
虫の遺伝子の初期値のばらつき
2(実際には 1 〜 この値)
分裂時の遺伝子の変化の最大値
2(実際には 1 〜 この値)
バクテリアの初期数
2000
バクテリアが増える時間間隔
10
バクテリアが増える数
10

また,変更できないパラメータは以下の通りです.

虫の大きさ
3*3ドット
虫の最大数
1000
バクテリアの大きさ
1*1ドット
画面の大きさ
512*512ドット

実装

では,これをプログラムで実現してみました.今までの簡単なプログラムと違って,画面のちらつきを抑える必要があり,ローカルなメモリに描画していき,描画が完了した時点で画面にコピーするようにしました.

プログラムのダウンロード

虫の移動先の確率は,次のように計算します.6つの遺伝子の値をそれぞれ g0, g1, ..., g5とすると,遺伝子g0の方向に方向転換する確率は,次のようにして求めます.

2^g0 / (2^g0 + 2^g1 + ... + 2^g5)

これを実現するには,0〜(2^g0 + 2^g1 + ... + 2^g5)の範囲の乱数を発生させ,それが0〜2^g0の間ならg0の方向,2^g0〜2^g0+2^g1の間なら g1の方向,2^g0+2^g1〜2^g0+2^g1+2^g2の間ならg2の方向のようにします.

進む向きが決まれば,現在の虫の向きと合わせて,移動先の位置を計算します.虫の向きを表す定数として,画面に対して上を0,右上を1,右下を2,下を3,左下を4,左上を5とします.また方向転換を表す定数として,前を0,右前を1,右後を2,後ろを3,左後を4,左前を5とします.虫の現在の向きをd,方向転換の方向をgとすると,移動後の方向は次のように求められます.

移動後の方向 = (d + g) mod 6

移動後の方向が求まれば,次の表を用いて移動距離が得られます.このプログラムでは,y座標は画面の下向きに大きくなるので,参考文献[1]とは y座標の符号が反転しています.

移動後の方向 1 2 3 4 5 6
x方向の移動 0 2 2 0 -2 -2
y方向の移動 -2 -1 1 2 1 -1

雑感

実はこれと同じプログラムを,7, 8年ほど前に作成したことがあります.その時はX68000というパソコンを使っていたのですが,今回作り直してみて,特に工夫をしたわけでもないのに実行速度が向上しており,パソコン(PentiumPro 200MHz)の性能が大幅に向上したことを強く感じました.

デフォルトのパラメータで実行すると,ゆっくりと虫の人口(虫口?)が増えていき,あるところから爆発的に人口が増えます.しかしそうなると,餌となるバクテリアの供給が足りず,急激に人口が減少します.バクテリアは虫の増減によらず一定の間隔で一定の数が発生して死ぬことがないので,虫の数が減れば食べられずに残るバクテリアが増えていき,虫が必要とするバクテリアの数をある程度上回れば,虫の数が再び増加に転じます.この試練を生き残った虫は,最初の頃のランダムな動きとは違い,バクテリアを見つけるのに適した動きになっていることがわかります.

この世界は,ボーっと見ている分には楽しい世界なのですが,私がこの世界の虫だったらあっというまに死んでしまうだろうなー,と思う厳しい世界でもあります.


改造

このプログラムはDelphiで作っています.その乱数発生ルーチンのヘルプを見ていると,正規分布の乱数を発生するルーチンがあることを発見しました.バクテリアが発生する位置を,これを使って決めるとどうなるか試してみました.こうすれば,文献[1]の「エデンの園」(バクテリアが豊富に存在する地域)のようなものを特別な処理を行わなくても実現できるかもしれない,という気もします.

画面中央を中心にバクテリアが分布するようにしました.正規分布の標準偏差の値を二種類用意して,バクテリアの分布のしかたに差をつけてみました.これらは,メニューの[設定]から選択できます.この設定は,バクテリアの初期配置だけでなく,その後に発生するものについても有効です.つまり,画面中心に集中的にバクテリアが発生するように設定すれば,設定を変更するまでシミュレーション実行中ずっと有効です.

試してみると,確かに虫の動き方が違って,前に進む確率が低いように思います.そのうち気が向けば統計的に処理してみるかもしれないと考えて,虫の情報をログに出力できるようにしました.メニューの[ファイル]から,ログを出力するかどうか選択できます.ログを処理するプログラムは,また,そのうち.


さらに改造

 バクテリアを発生させるパラメータとして、横方向と縦方向を独立にして、発生する中心として画面中央か画面端を選択できるようにしました。また、バクテリアと虫の色を変更できるようにしました。虫の色の初期値を変更し、未成熟状態は水色、成熟状態は白、エネルギーが残り少ないときは赤、未成熟状態だが分裂できるエネルギーがあるときは黄色にしました。

参考文献

  1. Dewdney, A.K., 別冊日経サイエンス113 コンピューターレクリエーションIV, pp.46-50, 日経サイエンス社, 1995

ホーム