首頁 > 軟體

Python實現的matplotlib動畫演示之細胞自動機

2022-04-21 13:01:07

維基百科上有個有意思的話題叫細胞自動機:https://en.wikipedia.org/wiki/Cellular_automaton

在20世紀70年代,一種名為生命遊戲的二維細胞自動機變得廣為人知,特別是在早期的計算機界。由約翰 · 康威發明,馬丁 · 加德納在《科學美國人》的一篇文章中推廣,其規則如下:

  1. Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overpopulation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

總結就是:任何活細胞在有兩到三個活鄰居時能活到下一代,否則死亡。任何有三個活鄰居的死細胞會變成活細胞,表示繁殖。

在Conway’s Game of Life中,展示了幾種初始狀態:

下面我們用python來模擬,首先嚐試表示Beacon:

import numpy as np
import matplotlib.pyplot as plt
universe = np.zeros((6, 6), "byte")
# Beacon
universe[1:3, 1:3] = 1
universe[3:5, 3:5] = 1
print(universe)
im = plt.imshow(universe, cmap="binary")
[[0 0 0 0 0 0]
 [0 1 1 0 0 0]
 [0 1 1 0 0 0]
 [0 0 0 1 1 0]
 [0 0 0 1 1 0]
 [0 0 0 0 0 0]]

可以看到已經成功的列印出了Beacon的形狀,下面我們繼續編寫細胞自動機的演化規則:

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三個活鄰居的死細胞都變成了活細胞,繁殖一樣。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有兩到三個活鄰居的活細胞都能活到下一代,否則就會死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
universe = cellular_auto(universe)
print(universe)
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
[[0 0 0 0 0 0]
 [0 1 1 0 0 0]
 [0 1 0 0 0 0]
 [0 0 0 0 1 0]
 [0 0 0 1 1 0]
 [0 0 0 0 0 0]]

ArtistAnimation動畫

基於此我們可以製作matplotlib的動畫,下面直接將Blinker、Toad、Beacon都放上去:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三個活鄰居的死細胞都變成了活細胞,繁殖一樣。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有兩到三個活鄰居的活細胞都能活到下一代,否則就會死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
universe = np.zeros((12, 12), "byte")
# Blinker
universe[2, 1:4] = 1
# Beacon
universe[4:6, 5:7] = 1
universe[6:8, 7:9] = 1
# Toad
universe[8, 2:5] = 1
universe[9, 1:4] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(2):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=500, blit=True)

然後我們畫一下Pulsar:

# Pulsar
universe = np.zeros((17, 17), "byte")
universe[[2, 7, 9, 14], 4:7] = 1
universe[[2, 7, 9, 14], 10:13] = 1
universe[4:7, [2, 7, 9, 14]] = 1
universe[10:13, [2, 7, 9, 14]] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(3):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=500, blit=True)

FuncAnimation動畫

另一種建立matplotlib動畫的方法是使用FuncAnimation,完整程式碼:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML
# %matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(h):
        for x in range(w):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三個活鄰居的死細胞都變成了活細胞,繁殖一樣。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有兩到三個活鄰居的活細胞都能活到下一代,否則就會死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    return universe_new
def update(i=0):
    global universe
    im.set_data(universe)
    universe = cellular_auto(universe)
    return im,
# Pulsar
universe = np.zeros((17, 17), "byte")
universe[[2, 7, 9, 14], 4:7] = 1
universe[[2, 7, 9, 14], 10:13] = 1
universe[4:7, [2, 7, 9, 14]] = 1
universe[10:13, [2, 7, 9, 14]] = 1
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
plt.show()
anim = animation.FuncAnimation(
    fig, update, frames=3, interval=500, blit=True)
HTML(anim.to_jshtml())

這種動畫生成速度較慢,好處是可以匯出html檔案:

with open("out.html", "w") as f:
    f.write(anim.to_jshtml())

還可以儲存MP4視訊:

anim.save("out.mp4")

或gif動畫:

anim.save("out.gif")

注意:儲存MP4視訊或GIF動畫,需要事先將ffmpeg設定到環境變數中

ffmpeg下載地址:

連結: https://pan.baidu.com/s/1aioB_BwpKb6LxJs26HbbiQ?pwd=ciui 
提取碼: ciui

隨機生命遊戲

接下來,我們建立一個50*50的二維生命棋盤,並選取其中1500個位置作為初始活細胞點,我們看看最終生成的動畫如何。

完整程式碼如下:

from matplotlib import animation
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook

def cellular_auto(universe):
    universe_new = universe.copy()
    h, w = universe.shape
    for y in range(1, h-1):
        for x in range(1, w-1):
            neighbor_num = universe[x-1:x+2, y-1:y+2].sum()-universe[x, y]
            # 任何有三個活鄰居的死細胞都變成了活細胞,繁殖一樣。
            if universe[x, y] == 0 and neighbor_num == 3:
                universe_new[x, y] = 1
            # 任何有兩到三個活鄰居的活細胞都能活到下一代,否則就會死亡。
            if universe[x, y] == 1 and neighbor_num not in (2, 3):
                universe_new[x, y] = 0
    # 邊緣置零
    universe[[0, -1]] = 0
    universe[:, [0, -1]] = 0
    return universe_new
boardsize, pad = 50, 2
universe = np.zeros((boardsize+pad, boardsize+pad), "byte")
# 隨機選取1500個點作為初始活細胞
for i in range(1500):
    x, y = np.random.randint(1, boardsize+1, 2)
    universe[y, x] = 1
    
fig = plt.figure()
plt.axis("off")
im = plt.imshow(universe, cmap="binary")
frame = []
for _ in range(200):
    frame.append((plt.imshow(universe, cmap="binary"),))
    universe = cellular_auto(universe)
animation.ArtistAnimation(fig, frame, interval=50, blit=True)

到此這篇關於Python實現的matplotlib動畫演示之細胞自動機的文章就介紹到這了,更多相關python  matplotlib動畫內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com