Fortgeschritten · Turing-Muster

Lektion 9: Gitter und Diffusion

Baue das Muster „Turing-Muster“ in Python und lerne dabei:

  • 2D-Arrays als Gitter aus Zellen
  • np.roll für Nachbarn, mit Rändern, die herumlaufen
  • der Laplace-Operator: eine Zelle gegen ihre Nachbarn
  • ein ganzes Gitter in einer Zeile aktualisieren
  • ein Array mit plt.imshow zeigen

Erst ansehen

Läuft nach einem Klick von 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

Kein Python auf diesem Computer? Das Notebook führt dasselbe Skript, die Übungen und die Lösungen in deinem Browser aus, in Google Colab. Das Notebook ist auf Englisch.

Zeile für Zeile

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

    Zwei Gitter von 128 × 128: überall das Futter A, noch kein B.

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

    Ein Tropfen B: ein Quadrat von 8 × 8 Zellen des Gitters, auf einmal durch Slicing gesetzt.

  3. def laplacian(Z):

    Wie sehr sich eine Zelle von ihren Nachbarn unterscheidet: positiv, wo die Nachbarn mehr haben, sodass die Diffusion sie auffüllt.

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

    np.roll verschiebt das ganze Gitter um eine Zelle nach oben, unten, links oder rechts; die Ränder laufen herum, also hat die Schale keinen Rand.

  5. reaction = A * B * B

    Die Reaktion, ein A und zwei B ergeben drei B, für jede Zelle auf einmal.

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

    Die Gray-Scott-Regel für A: Es breitet sich aus, wird verbraucht und wird mit der Rate f wieder in Richtung 1 aufgefüllt.

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

    Das Gitter von B als Bild, ein Pixel pro Zelle.

Probier es selbst

  1. Probier f, k = 0.034, 0.063.

    Hinweis

    Eine Zeile weit oben.

    Lösung

    Flecken: runde Stellen aus B, gleichmäßig verteilt, statt der gewundenen Linien der Koralle.

  2. Lass B so schnell wie A diffundieren: DB = 1.0. Was passiert?

    Hinweis

    DA, DB = 1.0, 1.0.

    Lösung

    Gar kein Muster: Die Tropfen verblassen zu nichts. Ohne dass sich A schneller ausbreitet als B, hält nichts die Flecken auseinander. Das ist Turings Kernpunkt.

  3. Nimm einen Tropfen in der Mitte statt sechs.

    Hinweis

    Ersetze die Schleife durch B[60:68, 60:68] = 1.0.

    Lösung

    Die Koralle wächst von dem einen Tropfen nach außen, mit einer vierzähligen Symmetrie, die den quadratischen Tropfen nachbildet: Ein Keim ergibt ein geordnetes Muster, sechs zufällige Tropfen ein natürlich aussehendes.

Quiz

1. Was macht np.roll(Z, 1, 0)?
2. Was misst der Laplace-Operator einer Zelle?
3. Warum gibt es keine Schleife über die Zellen?
4. Was hat Turing 1952 gezeigt?
5. Was ändert sich von der Koralle zu den Flecken?

Lernkarten

Lies die Vorderseite, sag dir die Rückseite vor, dann öffne die Karte.

  • np.roll(Z, shift, axis)

    Verschiebt ein Array entlang einer Achse; was an einem Ende herausfällt, kommt am anderen wieder herein.

  • Laplace-Operator

    Die Nachbarn einer Zelle minus die Zelle selbst: wohin die Diffusion sie bewegen wird.

  • Gray-Scott

    A wird mit f zugeführt, B mit f + k entfernt, und A + 2B → 3B.

  • Turing-Instabilität

    Diffusion zerlegt eine gleichmäßige Mischung in ein Muster, wenn sich ein Stoff schneller ausbreitet.

  • plt.imshow(grid)

    Zeigt ein 2D-Array als Bild, ein Pixel pro Zelle.

Diese Lernkarten auf einer eigenen Seite →

Du hast alle neun gebaut. Wenn dir der Kurs geholfen hat, freut sich der Kanal, davon zu hören. Den Kanal unterstützen →