葉脈と潮流

純粋さを磨き、迷わない。

FireflySimulatorについての説明と考察

 こんにちは。寒いですか?京都は寒いです。風は通さないけれど温度はガンガン通す壁というのは壁としての機能を保っていると言えるのでしょうか。ギリギリなラインだと思います。

 

 今日は蛍の同調現象についてのお話です。皆さん蛍は見たことありますか。僕は2年前に見た気がするのですがどんな感じだったか忘れてしまいました。どうやら蛍はランダムに光るのではなく同調するのだそうです。その同調現象は昔から有名な一方で、どういった方法で互いに同調しているかはまだ分かっていないそうです。これを聞いて興味をもったので蛍がどんなアルゴリズムで動けば同調するのかを調べてみることにしました。僕はモデル化が好きなのでとりあえずモデル化をしてどんなアルゴリズムならちゃんと同期するのか必要条件だけでも調べてみることにしました。

 また、大学にてプログラミングの授業があり、7月にそこで課題としてプログラムを作るよう言われました。そこで作ったのが次のプログラムです。

f:id:indigomou5e:20161217155953j:plain

 静止画では分かりにくいですが、10×10のマスに蛍が詰まっていて、"o"の文字は発光している蛍を表しています。見た目はお粗末ですが、それぞれの蛍は1秒に30回隣の蛍を参照して自分の光りかたを調整し、ちゃんと同調もします。

 これで終わるのはちょっと残念なので、秋ごろから時間を見つけてはこのプログラムを作り直すというのを少しずつやりました。つい最近完成したのが次のプログラムです。

 一気に見栄えが良くなりましたね。やはり人間は象徴などではなくそれを想起させるものでないとリアリティを感じ得ないのですね。

 こちらでは蛍を文字でなく画像で表し、また蛍が移動するようにプログラムを追加しました。蛍は一定距離内の別の蛍の光を感知するようになっています。他にも下段に色んな設定が増えました。同調するまで早送りしたり、背景や蛍の光の色も変えられるようになっています。

 ソースコードこちら(github)、またプログラムはこちらからダウンロードも可能です。以下の説明はダウンロードしてみたほうが分かりやすいと思われます。java動作環境が必要なので、ない人はjreで検索してダウンロードしてください。

 

 さて、このプログラムは単に蛍を描画するだけでなく、蛍の同調アルゴリズムを変更することでそれが同調するかを調べることが出来ます。今回は8つのアルゴリズムを実装しました。ここから先はその仕様を説明し、シミュレートの結果をもとに考察してみようと思います。

 

 ここから先は次の二点を前提にします。

  1. 蛍の同調はリーダー的存在が他を指揮して起こるのではなく、互いに合わせようとして起こるということ
  2. その際他の蛍を参照するときには他の蛍が光っているかどうかでしか判別できないこと

 このあたりはまだ明らかになっていないので、自分でそれらしい前提をつけました。もしかしたら超常的な力で同調しているのかもしれませんが、そのときはお手上げです。

 

 まず、アルゴリズムの一覧はこのようになっています。(コメントから引用)

/* algorithmの詳細
* 0: アルゴリズムなし。全く周りを参照しない。
* 1: 自分が光っておらず、周りが光っていれば早める。
* 2: 自分が光っておらず、周りが光っていれば遅らせる。
* 3: 自分が光っておらず、周りが光っていたらそれに合わせる。
* 具体的には、光り終わってすぐなら遅らせ、もうすぐ光るなら早める。
* 4: 1と2の混合。半分は1、半分は2のアルゴリズムで動く。
* 5: 3と0が5:1の割合で混合している。
* 6: 3の派生。半分が周りの変化に敏感でもう半分が鈍感。
* 7: 3の派生。全員非常に敏感。手っ取り早く同期させたいとき用。
* ただし過度に同期してしまう。
*/

 これからひとつずつ見ていくことにしましょう。

 

 まず、algorithm 0は周りに関係なくマイペースに光ります。当たり前ですがこのアルゴリズムのみでは同調は起こりません。周りに合わせて早めたり遅らせたりが必要になってきます。とりあえず、一番簡単なアルゴリズムを作ってみましょう。

> 1: 自分が光っておらず、周りが光っていれば早める。
> 2: 自分が光っておらず、周りが光っていれば遅らせる。

 周りが光っていて、それに合わせるように早めたり遅れたりすれば少しずつ同期するかもしれません。とりあえずこの二つを作成して動かしてみました。

 しかし結果は同調せずでした。全員が完全に同調した状態から始めたときでさえ、十分な時間の後にはバラバラになってしまいました。理由は以下の2つが考えられます。

1.お互いに早めあうのでいつまで経っても同調に至らない。

 例えばAとBの2匹の蛍を考えます。Aは光ってるBを見て自分の光るタイミングを早めようとします。しかし、その後Aが光ったときにBもまたタイミングを早めるので1サイクルの中で相対的なタイミングが全く変わらないのです。

2.同調していたとしても、少しのズレで同調が崩れる

 今度はAとBとCの三匹を考えます。この三匹は完全に同調しています。それぞれの蛍は1周期の時間が微妙に異なるので、Aが他の2匹と比べ少しタイミングを早めてしまいました。そうするとAが光っておらずB,Cが光る瞬間というのが存在します。この時間、Aには2つの光が見えているので2単位時間分サイクルを早めようとします。一方、B,Cが光っておらずAが光る時間もありますが、その時見える光はAの一つなのでB,Cは1単位時間分サイクルを早めます。こうなると相対的にAは1単位時間分さらにサイクルを早めてしまうことになります。この繰り返しで少しずつ同調が崩れていきます。どこかで聞いた言葉を使えばこの同調は「不安定なつりあい」と言えるでしょう。

 

 さて、単に早めたり遅らせたりでは同調しないことが分かりました。でも、早める個体と遅らせる個体が一緒にいれば同調するかもしれません。そこで書いたのがalgorithm 4です。

> 4: 1と2の混合。半分は1、半分は2のアルゴリズムで動く。

 結果から言うと、これも同調にはいたりませんでした。先ほど書いた理由1は部分的には回避していますが、2は結局回避できてないことも理由の一つだと思われます。これは早める蛍と遅らせる蛍を1:1で混合していますが、おそらくどの比率で混ぜても変わらないと思われます。

 

 また、この結果から蛍は自分が今1周期のどこにいるかを知っていて、それに応じて周りの光を見たときの調整の仕方を変えていることが導けるでしょう。そこでとりあえず作ったのがalgorithm 3です。

> 3: 自分が光っておらず、周りが光っていたらそれに合わせる。
>  具体的には、光り終わってすぐなら遅らせ、もうすぐ光るなら早める。

 詰まるところ普通に合わせようとします。自分が周りと比べて少し先行してるから遅らせようという感じです。これだと少なくとも「不安定なつりあい」は脱していることが分かりますね。このアルゴリズムならバラバラな状態から同調することができるのでしょうか。

 これはぜひ皆さんにプログラムをダウンロードして試して欲しいのですが、きちんと同期します。時間は少しかかります。これは同調度合いの定数をいい塩梅に調整したからです。少しずつ同調するのを楽しんで欲しいですが、せっかちな方は早送りするかalgorithm 7を使ってください。1分ほどで同調します。

 同調する理由ですが、周りの蛍に合わせる度合いの強さが光っている蛍の多さに比例することにあると思われます。

 例えば、蛍Aと、すでに同調している蛍のグループX,Yを考えます。AとXとYはそれぞれ同調しておらず、それぞれのグループの構成数はXが5、Yが3とします。

 このとき、Xが光る際にはAの周期をXの周期に5単位時間近づけます。一方でYはAの周期をYの周期に3単位時間近づけます。この繰り返しにより、Aは最も構成数が大きいグループ(X)に少しずつ近づいていきます。つまり、同調している蛍の数が多いグループほど、新たに他の蛍を同調させやすくなるのです。また、XとY同士も少しずつ近づいていくので、雪だるま式にグループの数は増えていくことになるでしょう。万有引力に似ているような気もします。

 

 これでalgorithm 3が同調することは分かりました。他にアルゴリズムも特に思いつかないので、次はノイズについて考えてみることにします。

> 5: 3と0が5:1の割合で混合している。
> 6: 3の派生。半分が周りの変化に敏感でもう半分が鈍感。

 5と6はそういった意図で書いたものです。5は周りを参照しない蛍が一部居てもちゃんとそれ以外の蛍は同調するのか、6は半数が鈍感(algorithm 3の1/5程度しか反応しない)でもちゃんと同期が行われるのかを試したものです。

 まず5ですが、この割合だと時間はかかりますがちゃんと同調します。空気を読めない蛍が居てもある程度なら何とかなるんですね。3と0の割合を変える、例えば1:1だとそもそも同調を確認することが難しいです。半分がバラバラな中でalgorithm 3で動いている蛍は同調しているかどうかなんて分かりにくいものです。一応計算上は同調する、ような気がします(計算してない)。

 また、6もちゃんと同調します。しかも3や7と違い、全員が同調せずにノイズのようにいくつかの蛍が同調から外れて光るのですごくそれっぽいです。こういうのがリアルだとすると、蛍の中にも周りをよく参照する蛍とマイペースに光る蛍が存在しているんじゃないでしょうか。

 5や6のようなアルゴリズムを作って満足したあたりで開発は終了しました。一匹ずつに0,1,2,3,7のアルゴリズムをそれぞれ別個に設定できる機能もつけようと思いましたが、煩雑ですし4,5,6さえあれば何とかなる気がしたのでやめました。

 まとめに入ってみましょう。まず、蛍は自分が1周期のどのタイミングにいるかを知っていて、さらに蛍によって周りに合わせる度合いが異なることが分かりました。分かってみれば簡単なことですが、こういうことを知れるからモデル化はやめられません。今後も色んなモデル化をしていきたいと思いました。ブログの締め書くの苦手なのでこれで勘弁してください。さようなら。