上級 · チューリングパターン

レッスン9:グリッドと拡散

Pythonで 「チューリングパターン」 を作りながら、次のことを学びます:

  • マスのグリッドとしての2次元配列
  • 端が折り返す、np.roll によるとなりのマス
  • ラプラシアン:マスと、そのとなりのマスとの差
  • グリッド全体を1行で更新する
  • plt.imshow で配列を表示する

まず見てみる

クリックするとYouTubeから再生されます。

turing-patterns.py
"""Turing patterns: the Gray-Scott reaction-diffusion rule on a 128 x 128 grid.
Run: python turing-patterns.py   (needs: pip install numpy matplotlib; takes a few seconds)
"""
import numpy as np
import matplotlib.pyplot as plt

plt.style.use("dark_background")

size, steps = 128, 6000
f, k = 0.0545, 0.062  # feed and kill rates: coral
DA, DB = 1.0, 0.5  # A spreads twice as fast as B

A, B = np.ones((size, size)), np.zeros((size, size))
rng = np.random.default_rng()
for y, x in rng.integers(10, size - 18, (6, 2)):
    B[y : y + 8, x : x + 8] = 1.0  # six drops of B


def laplacian(Z):
    """Each cell against its neighbours: 0.2 for the four sides, 0.05 for the corners (Karl Sims)"""
    sides = np.roll(Z, 1, 0) + np.roll(Z, -1, 0) + np.roll(Z, 1, 1) + np.roll(Z, -1, 1)
    corners = (np.roll(np.roll(Z, 1, 0), 1, 1) + np.roll(np.roll(Z, 1, 0), -1, 1)
               + np.roll(np.roll(Z, -1, 0), 1, 1) + np.roll(np.roll(Z, -1, 0), -1, 1))
    return 0.2 * sides + 0.05 * corners - Z


for _ in range(steps):
    reaction = A * B * B  # one A and two B make three B
    A += DA * laplacian(A) - reaction + f * (1 - A)
    B += DB * laplacian(B) + reaction - (f + k) * B

plt.figure(figsize=(6, 6))
plt.imshow(B, cmap="magma", vmin=0, vmax=0.5)
plt.axis("off")
plt.show()

# Try: f, k = 0.039, 0.058 (a cell net) or 0.034, 0.063 (spots) -> the same rule, another pattern

このコンピューターにPythonが入っていませんか?ノートブックなら、同じスクリプト、練習問題、答えを、ブラウザ上のGoogle Colabで実行できます。ノートブックは英語です。

1行ずつ

  1. A, B = np.ones((size, size)), np.zeros((size, size))

    128 × 128 のグリッドが2つ。エサのAはどこにでもあり、Bはまだありません。

  2. B[y : y + 8, x : x + 8] = 1.0

    Bのしずくです。グリッドの 8 × 8 の正方形を、スライスでいっぺんに設定します。

  3. def laplacian(Z):

    マスがとなりのマスとどれだけ違うか。となりのほうが多いところでは正になるので、拡散がそこを満たしていきます。

  4. sides = np.roll(Z, 1, 0) + np.roll(Z, -1, 0) + np.roll(Z, 1, 1) + np.roll(Z, -1, 1)

    np.roll はグリッド全体を、上、下、左、右に1マスずらします。端は折り返すので、シャーレにはふちがありません。

  5. reaction = A * B * B

    反応です。Aひとつと Bふたつで、Bが3つになります。すべてのマスでいっぺんに。

  6. A += DA * laplacian(A) - reaction + f * (1 - A)

    Aについてのグレイ–スコットのルールです。Aは広がり、食べられ、割合fで1に向かって補給されます。

  7. plt.imshow(B, cmap="magma", vmin=0, vmax=0.5)

    Bのグリッドを絵として表示します。1マスが1ピクセルです。

やってみよう

  1. f, k = 0.034, 0.063 を試してみましょう。

    ヒント

    上のほうにある1行です。

    答え

    斑点になります。サンゴのうねる線の代わりに、Bの丸い塊が等間隔に並びます。

  2. BをAと同じ速さで広がるようにしてみましょう:DB = 1.0。何が起こりますか?

    ヒント

    DA, DB = 1.0, 1.0。

    答え

    模様はまったくできません。しずくは消えて何も残りません。AがBより速く広がらなければ、塊どうしを引き離しておくものがないのです。これがチューリングの要点です。

  3. しずくを6滴ではなく、真ん中に1滴だけにしてみましょう。

    ヒント

    ループを B[60:68, 60:68] = 1.0 に置き換えます。

    答え

    サンゴは1滴のしずくから外へ向かって育ち、正方形のしずくを写した4回対称の形になります。種がひとつなら整った模様に、でたらめな6滴なら自然に見える模様になります。

クイズ

1. np.roll(Z, 1, 0) は何をしますか?
2. マスのラプラシアンは何を測りますか?
3. マスを回るループがないのはなぜですか?
4. チューリングは1952年に何を示しましたか?
5. サンゴから斑点へと、何が変わりますか?

フラッシュカード

表を読み、裏に何があるかを自分で言ってみてから、カードを開いてください。

  • np.roll(Z, shift, axis)

    配列を軸に沿ってずらします。一方の端から落ちたものは、反対の端に戻ってきます。

  • ラプラシアン

    マスのとなりから、そのマス自身を引いたもの。拡散がマスを動かす向き。

  • グレイ–スコット

    Aは割合fで補給され、Bは割合 f + k で取り除かれ、A + 2B → 3B。

  • チューリング不安定性

    一方の物質が速く広がるとき、拡散が均一な混合物を壊して模様にすること。

  • plt.imshow(grid)

    2次元配列を絵として表示します。1マスが1ピクセル。

このフラッシュカードを別のページで →

9つすべてを作り終えました。コースが役に立ったなら、ぜひチャンネルに聞かせてください。 チャンネルを応援 →