Python 元胞自動機模擬——生命游戲


簡介
元胞自動機(cellular automata) 是離散而抽象的計算系統。元胞自動機在時間和空間上是離散的,最小單位是簡單元胞(單元格)。每個元胞會產生有限數量的狀態集,后續元胞由其鄰域元胞的狀態確定。這里所說的領域元胞,是指當前元胞的前一個元胞(記作元胞A)以及元胞A左右兩個元胞。也就是說,鄰域元胞總共包含三個元胞。給定初始層的狀態,基於一定規則,我們可以不斷更新下一層元胞的狀態。通俗的講,元胞自動機就是基於一定規則的“繁衍機器”。

最簡單的例子
這里,我們選取的元胞狀態只有兩種,分別為 0 和 1。每一層由 64 個元胞組成,若元胞狀態為 1,那么控制台將打印星號(*);如果元胞狀態為 0,那么控制台將打印連字符(-)。也就是說,每一行由 64 個混合星號與連字符的圖案組成。
那么,我們如何確定每一行的狀態呢?

首先,我們要對第一行進行初始化操作。我們設置第 31 個元胞的狀態為 1、其余 63 個元胞的狀態為 0.
狀態更新規則:若當前元胞的前一個元胞的狀態為 1,或者前一個元胞的左右兩邊的元胞的狀態有且只有一個值為 1, 那么該元胞的狀態就為 1。反之,元胞的狀態設為 0。對於第一列和最后一列,我們只需分別考慮右元胞和左元胞即可。對於中間部分的元胞來說,若其領域元胞的狀態為[0,1,0]、[0,0,1]、[1,0,0]、[1,1,0]等狀態時,當前元胞的狀態就為 1。
代碼

 

"""
元胞自動機 Python 實現
"""
import numpy as np
import matplotlib.pyplot as plt
 
 
class GameOfLife(object):
 
  def __init__(self, cells_shape):
    """
    Parameters
    ----------
    cells_shape : 一個元組,表示畫布的大小。
 
    Examples
    --------
    建立一個高20,寬30的畫布
    game = GameOfLife((20, 30))
     
    """
 
    # 矩陣的四周不參與運算
    self.cells = np.zeros(cells_shape)
 
    real_width = cells_shape[0] - 2
    real_height = cells_shape[1] - 2
     
    self.cells[1:-1, 1:-1] = np.random.randint(2, size=(real_width, real_height))
    self.timer = 0
    self.mask = np.ones(9)
    self.mask[4] = 0
   
  def update_state(self):
    """更新一次狀態"""
    buf = np.zeros(self.cells.shape)
    cells = self.cells
    for i in range(1, cells.shape[0] - 1):
      for j in range(1, cells.shape[0] - 1):
        # 計算該細胞周圍的存活細胞數
        neighbor = cells[i-1:i+2, j-1:j+2].reshape((-1, ))
        neighbor_num = np.convolve(self.mask, neighbor, 'valid')[0]
        if neighbor_num == 3:
          buf[i, j] = 1
        elif neighbor_num == 2:
          buf[i, j] = cells[i, j]
        else:
          buf[i, j] = 0
    self.cells = buf
    self.timer += 1
   
  def plot_state(self):
    """畫出當前的狀態"""
    plt.title('Iter :{}'.format(self.timer))
    plt.imshow(self.cells)
    plt.show()
 
  def update_and_plot(self, n_iter):
    """更新狀態並畫圖
    Parameters
    ----------
    n_iter : 更新的輪數
    """
    plt.ion()
    for _ in range(n_iter):
      plt.title('Iter :{}'.format(self.timer))
      plt.imshow(self.cells)
      self.update_state()
      plt.pause(0.2)
    plt.ioff()
           
 
if __name__ == '__main__':
  game = GameOfLife(cells_shape=(60, 60))
  game.update_and_plot(200)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM