reaction-diffusion

チューリング波(反応拡散波)を理解したい

More than 1 year has passed since last update.

波紋と螺旋とフィボナッチ(著:近藤 滋 ) を読んで反応拡散波(チューリング波)のことを知り大変興味を持ちました。ただ、この本だけでは反応拡散波の仕組みをよく理解できなかったので、調べて、コードに書いてシュミレートしてみて、ようやく納得できました。

反応拡散波とは

honeycomb-moray-1877047_640.jpg

生き物は様々な模様をしているが、種を違えても似た模様をもつ生き物がいる、ということは、模様を発生させる共通した原理が働いているのではないか? ということで、この原理を説明するモデルが反応拡散波で、アラン・チューリングが論文で世に表したものである。

模様が生まれる構造

生物の細胞の中を2つの分子が行き来する状況を考える。一つの分子をU、もう一つをVとする。分子Uは細胞に働きかけ、Vの生成を促進する働きを持つ。分子Vは逆にUの成長を阻害する働きをもつとする。そして分子UとVは一定の速度で細胞間を広がって行くが、拡散する速度が異なっており、VはUより拡散速度が早い。このような構造下において、UとVの反応と拡散が進んで行くと、UとVの分布にパターンが現れ、それが模様となるというものである。
スクリーンショット 2017-09-22 16.01.30.png

これだけの説明で模様が生成されていく過程を想像するのは難しい思います。反応拡散波で模様が生成されて行く過程を見れるように、CodePenにP5jsで簡易なシュミレーターを作りました。

https://codepen.io/tamichan/pen/ZWppNL

また、反応拡散波の仕組みのより分かりやすい説明は下記リンク先を参照してください。
http://www.fbs.osaka-u.ac.jp/labs/skondo/ozaki/what%20is%20RD%201%20by%20ozaki.htm
上記のページでは、拡散についてあまり触れていないので、コードで表現する方法がわからない場合は下記リンクが助かりました。
http://nodamushi.hatenablog.com/entry/20121101/1351786511

反応と拡散をコードで表現するには

反応部分と拡散部分のコードは下記のようになります。

  // 反応
  void react() {
    u_reacted = (dt*a/(v))*(u*u) + (1-dt*b)*u + dt*d;
    u_reacted = max(0,min(u_reacted,10));
    v_reacted = (1-dt*c)*v + dt*c*u;
    v_reacted = max(0,min(v_reacted,10));
  }
  // 拡散
  void spread() {
    float du = spread_rate_u * u;
    float dv = spread_rate_v * v;
    for (Cell nei : neighbor) {
      nei.u_spreaded += du;
      nei.v_spreaded += dv;
    }
    u_spreaded -= neighbor.size() * du;
    v_spreaded -= neighbor.size() * dv;
  }
  // 反応と拡散を足し合わせる
  void sum() {
    u = u_reacted + u_spreaded;
    v = v_reacted + v_spreaded;
    u_spreaded = v_spreaded = 0;
    u_reacted = v_reacted = 0;
  }

上記の反応と拡散と合算をすべての細胞に適用します。細胞は縦横それぞれ100個並んでいるとします。

  for (int y=0; y<cells.length; y++) {
    for (int x=0; x<cells.length; x++) {
      Cell c = cells[x][y];
      c.react();
      c.spread();
    }
  }

  for (int y=0; y<cells.length; y++) {
    for (int x=0; x<cells.length; x++) {
      Cell c = cells[x][y];
      c.sum();
  }

上記のイテレーションを何度も繰り返して行くとパターンが形成されます。

どうして等間隔のようなパターンができるのか?

反応拡散波の説明や構造について、数式やプログラムコードでわかったとしても、実際にパターンが形成される過程が実感を持って納得できませんでした。数学的に証明されており、プログラムを動かすと模様ができるのですが、多数の細胞間の協調作用でパターンが形成されるため、風が吹いたら桶屋が儲かる的な、順序だった変化を確認しづらいです。

そこで、細胞の並びを1次元にして、局所的な変化を追ってみます。下記は最初から最後までの変化です。横一列に細胞が100個並んでおり、最初はUとVを完全に均一な状態に置いたあと、中央の細胞のひとつにUを少しだけ加えると、そこから反応が伝播して行きます。Uを赤、Vを青にしてそれぞれの量を描いています。
gif.gif

最初の状態、UとVの値が全ての細胞で均一の場合はパターンは形成されずに一定の均衡を保っています。
1506055815056.png

中央の細胞にUを少し加えるとUの増加が始まります。
1506055830192.png

Uはさらに増加し、Uの促進効果でVも増加していきます。
1506055840634.png

さらに反応拡散が進んで、パターン(次のUの盛り上がり)が起こる流れは以下のようになります。
スクリーンショット 2017-09-24 21.51.48.png

微細な変化なのでグラフからは読み取りにくいですが、ちょっと離れたところに次のUの優勢となるポイントが出来上がります。これを進めると下記のようになります。
1506055849329.png

ということで、パターンが起こる流れは、
1. Uの増加に伴いVも増加する
2. Vの方が拡散が早いため、Uの増加した周りでは逆にUが減少する
3. Uが減少した箇所ではVも減少を開始する
4. Vの減少はUよりも早く拡散するため、近傍ではUの方が優勢の箇所が出現する
5. Uが優勢となるとUは増加を開始する

というのが繰り返し起こっていると見て取れます。これでパターンが形成される仕組みがステップ・バイ・ステップで理解できたと思います。