Lekcja 9: Siatki i dyfuzja
Zbuduj w Pythonie wzór „Wzory Turinga” i po drodze naucz się:
- tablice dwuwymiarowe jako siatka komórek
- np.roll do sąsiadów, z brzegami, które się zawijają
- laplasjan: komórka wobec swoich sąsiadów
- zmiana całej siatki w jednej linijce
- pokazywanie tablicy przez plt.imshow
Najpierw obejrzyj
Film gra z YouTube po kliknięciu.
"""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
Nie masz Pythona na tym komputerze? Notatnik uruchamia ten sam skrypt, zadania i odpowiedzi w przeglądarce, w Google Colab. Notatnik jest po angielsku.
Linijka po linijce
A, B = np.ones((size, size)), np.zeros((size, size))Dwie siatki 128 × 128: pożywienie A wszędzie, jeszcze bez B.
B[y : y + 8, x : x + 8] = 1.0Kropla B: kwadrat 8 × 8 siatki, ustawiony naraz przez wycinek.
def laplacian(Z):O ile komórka różni się od sąsiadów: wartość dodatnia tam, gdzie sąsiedzi mają więcej, więc dyfuzja ją uzupełni.
sides = np.roll(Z, 1, 0) + np.roll(Z, -1, 0) + np.roll(Z, 1, 1) + np.roll(Z, -1, 1)np.roll przesuwa całą siatkę o jedną komórkę w górę, w dół, w lewo albo w prawo; brzegi się zawijają, więc szalka nie ma krawędzi.
reaction = A * B * BReakcja, jedno A i dwa B dają trzy B, dla każdej komórki naraz.
A += DA * laplacian(A) - reaction + f * (1 - A)Reguła Graya–Scotta dla A: rozprzestrzenia się, jest zjadane i dopływa z powrotem do 1 w tempie f.
plt.imshow(B, cmap="magma", vmin=0, vmax=0.5)Siatka B jako obrazek, jeden piksel na komórkę.
Twoja kolej
Spróbuj f, k = 0.034, 0.063.
Podpowiedź
Jedna linijka u góry.
Odpowiedź
Plamy: okrągłe skupiska B w równych odstępach zamiast krętych linii koralu.
Niech B rozprzestrzenia się tak szybko jak A: DB = 1.0. Co się dzieje?
Podpowiedź
DA, DB = 1.0, 1.0.
Odpowiedź
Żadnego wzoru: krople zanikają do zera. Jeśli A nie rozprzestrzenia się szybciej od B, nic nie utrzymuje plam w odstępach. To właśnie myśl Turinga.
Użyj jednej kropli na środku zamiast sześciu.
Podpowiedź
Zastąp pętlę przez B[60:68, 60:68] = 1.0.
Odpowiedź
Koral rośnie na zewnątrz z jednej kropli z czterokrotną symetrią, która powtarza kwadratową kroplę: jedno ziarno daje uporządkowany wzór, sześć losowych kropli naturalnie wyglądający.
Quiz
Fiszki
Przeczytaj przód, powiedz sobie, co jest z tyłu, potem otwórz kartę.
np.roll(Z, shift, axis)
Przesuwa tablicę wzdłuż osi; to, co spada z jednego końca, wraca na drugim.
Laplasjan
Sąsiedzi komórki minus sama komórka: tam ją przesunie dyfuzja.
Gray–Scott
A dopływa w tempie f, B jest usuwane w tempie f + k, a A + 2B → 3B.
Niestabilność Turinga
Dyfuzja rozbija jednolitą mieszaninę na wzór, gdy jedna substancja rozprzestrzenia się szybciej.
plt.imshow(grid)
Pokazuje tablicę dwuwymiarową jako obrazek, jeden piksel na komórkę.
Wszystkie dziewięć zbudowane. Jeśli kurs pomógł, kanał chętnie się o tym dowie. Wesprzyj kanał →