2019-12-19  2024-09-18    1334 字  3 分钟

A cellular automaton is a discrete model studied in computer science, mathematics, physics, complexity science, theoretical biology and microstructure modeling.

  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.

Golly

  1. 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
  2. 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
  3. 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
  4. 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)
Python Code 1
  1# Python code to implement Conway's Game Of Life
  2import argparse
  3import numpy as np
  4import matplotlib.pyplot as plt
  5import matplotlib.animation as animation
  6
  7# setting up the values for the grid
  8ON = 255
  9OFF = 0
 10vals = [ON, OFF]
 11
 12
 13def randomGrid(N):
 14    """returns a grid of NxN random values"""
 15    return np.random.choice(vals, N * N, p=[0.2, 0.8]).reshape(N, N)
 16
 17
 18def addGlider(i, j, grid):
 19    """adds a glider with top left cell at (i, j)"""
 20    glider = np.array([[0, 0, 255],
 21                       [255, 0, 255],
 22                       [0, 255, 255]])
 23    grid[i:i + 3, j:j + 3] = glider
 24
 25
 26def addGosperGliderGun(i, j, grid):
 27    """adds a Gosper Glider Gun with top left
 28       cell at (i, j)"""
 29    gun = np.zeros(11 * 38).reshape(11, 38)
 30
 31    gun[5][1] = gun[5][2] = 255
 32    gun[6][1] = gun[6][2] = 255
 33
 34    gun[3][13] = gun[3][14] = 255
 35    gun[4][12] = gun[4][16] = 255
 36    gun[5][11] = gun[5][17] = 255
 37    gun[6][11] = gun[6][15] = gun[6][17] = gun[6][18] = 255
 38    gun[7][11] = gun[7][17] = 255
 39    gun[8][12] = gun[8][16] = 255
 40    gun[9][13] = gun[9][14] = 255
 41
 42    gun[1][25] = 255
 43    gun[2][23] = gun[2][25] = 255
 44    gun[3][21] = gun[3][22] = 255
 45    gun[4][21] = gun[4][22] = 255
 46    gun[5][21] = gun[5][22] = 255
 47    gun[6][23] = gun[6][25] = 255
 48    gun[7][25] = 255
 49
 50    gun[3][35] = gun[3][36] = 255
 51    gun[4][35] = gun[4][36] = 255
 52
 53    grid[i:i + 11, j:j + 38] = gun
 54
 55
 56def update(frameNum, img, grid, N):
 57    # copy grid since we require 8 neighbors
 58    # for calculation and we go line by line
 59    newGrid = grid.copy()
 60    for i in range(N):
 61        for j in range(N):
 62
 63            # compute 8-neghbor sum
 64            # using toroidal boundary conditions - x and y wrap around
 65            # so that the simulaton takes place on a toroidal surface.
 66            total = int((grid[i, (j - 1) % N] + grid[i, (j + 1) % N] +
 67                         grid[(i - 1) % N, j] + grid[(i + 1) % N, j] +
 68                         grid[(i - 1) % N, (j - 1) % N] + grid[(i - 1) % N, (j + 1) % N] +
 69                         grid[(i + 1) % N, (j - 1) % N] + grid[(i + 1) % N, (j + 1) % N]) / 255)
 70
 71            # apply Conway's rules
 72            if grid[i, j] == ON:
 73                if (total < 2) or (total > 3):
 74                    newGrid[i, j] = OFF
 75            else:
 76                if total == 3:
 77                    newGrid[i, j] = ON
 78
 79                    # update data
 80    img.set_data(newGrid)
 81    grid[:] = newGrid[:]
 82    return img,
 83
 84
 85# main() function
 86def main():
 87    # Command line args are in sys.argv[1], sys.argv[2] ..
 88    # sys.argv[0] is the script name itself and can be ignored
 89    # parse arguments
 90    parser = argparse.ArgumentParser(description="Runs Conway's Game of Life simulation.")
 91
 92    # add arguments
 93    parser.add_argument('--grid-size', dest='N', required=False)
 94    parser.add_argument('--mov-file', dest='movfile', required=False)
 95    parser.add_argument('--interval', dest='interval', required=False)
 96    parser.add_argument('--glider', action='store_true', required=False)
 97    parser.add_argument('--gosper', action='store_true', required=False)
 98    args = parser.parse_args()
 99
100    # set grid size
101    N = 100
102    if args.N and int(args.N) > 8:
103        N = int(args.N)
104
105        # set animation update interval
106    updateInterval = 50
107    if args.interval:
108        updateInterval = int(args.interval)
109
110        # declare grid
111    grid = np.array([])
112
113    # check if "glider" demo flag is specified
114    if args.glider:
115        grid = np.zeros(N * N).reshape(N, N)
116        addGlider(1, 1, grid)
117    elif args.gosper:
118        grid = np.zeros(N * N).reshape(N, N)
119        addGosperGliderGun(10, 10, grid)
120    else:  # populate grid with random on/off -
121        # more off than on
122        grid = randomGrid(N)
123
124        # set up animation
125    fig, ax = plt.subplots()
126    img = ax.imshow(grid, interpolation='nearest')
127    ani = animation.FuncAnimation(fig, update, fargs=(img, grid, N,),
128                                  frames=10,
129                                  interval=updateInterval,
130                                  save_count=50)
131
132    # # of frames?
133    # set output file
134    if args.movfile:
135        ani.save(args.movfile, fps=30, extra_args=['-vcodec', 'libx264'])
136
137    plt.show()
138
139
140# call main
141if __name__ == '__main__':
142    main()
Python Code 2
 1"""
 2元胞自动机 Python 实现
 3"""
 4import numpy as np
 5import matplotlib.pyplot as plt
 6
 7
 8class GameOfLife(object):
 9
10    def __init__(self, cells_shape):
11        """
12        Parameters
13        ----------
14        cells_shape : 一个元组,表示画布的大小。
15
16        Examples
17        --------
18        建立一个高20,宽30的画布
19        game = GameOfLife((20, 30))
20
21        """
22
23        # 矩阵的四周不参与运算
24        self.cells = np.zeros(cells_shape)
25
26        real_width = cells_shape[0] - 2
27        real_height = cells_shape[1] - 2
28
29        self.cells[1:-1, 1:-1] = np.random.randint(2, size=(real_width, real_height))
30        self.timer = 0
31        self.mask = np.ones(9)
32        self.mask[4] = 0
33
34    def update_state(self):
35        """更新一次状态"""
36        buf = np.zeros(self.cells.shape)
37        cells = self.cells
38        for i in range(1, cells.shape[0] - 1):
39            for j in range(1, cells.shape[0] - 1):
40                # 计算该细胞周围的存活细胞数
41                neighbor = cells[i - 1:i + 2, j - 1:j + 2].reshape((-1,))
42                neighbor_num = np.convolve(self.mask, neighbor, 'valid')[0]
43                if neighbor_num == 3:
44                    buf[i, j] = 1
45                elif neighbor_num == 2:
46                    buf[i, j] = cells[i, j]
47                else:
48                    buf[i, j] = 0
49        self.cells = buf
50        self.timer += 1
51
52    def plot_state(self):
53        """画出当前的状态"""
54        plt.title('Iter :{}'.format(self.timer))
55        plt.imshow(self.cells)
56        plt.show()
57
58    def update_and_plot(self, n_iter):
59        """更新状态并画图
60        Parameters
61        ----------
62        n_iter : 更新的轮数
63        """
64        plt.ion()
65        for _ in range(n_iter):
66            plt.title('Iter :{}'.format(self.timer))
67            plt.imshow(self.cells)
68            self.update_state()
69            plt.pause(0.2)
70        plt.ioff()
71
72
73if __name__ == '__main__':
74    game = GameOfLife(cells_shape=(60, 60))
75    game.update_and_plot(200)

除另有声明外本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可转载请注明原作者与文章出处