A cellular automaton is a discrete model studied in computer science, mathematics, physics, complexity science, theoretical biology and microstructure modeling.
- Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
- Any live cell with two or three live neighbours lives on to the next generation.
- Any live cell with more than three live neighbours dies, as if by overpopulation.
- Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
- 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
- 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
- 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
- 当前细胞为死亡状态时,当周围有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 国际许可协议 进行许可。转载请注明原作者与文章出处。