元胞自动机(Cellular Automata,简称CA,也有人译为细胞自动机、点格自动机、分子自动机或单元自动机)。是一时间和空间都离散的动力系统。散布在规则格网 (Lattice Grid)中的每一元胞(Cell)取有限的离散状态,遵循同样的作用规则,依据确定的 局部规则 作同步更新。大量元胞通过简单的相互作用而构成动态系统的演化。不同于一般的动力学模型,元胞自动机不是由严格定义的物理方程或函数确定,而是用一系列模型构造的规则构成。凡是满足这些规则的模型都可以算作是元胞自动机模型。因此,元胞自动机是一类模型的总称,或者说是一个方法框架。其特点是时间、空间、状态都离散,每个变量只取有限多个状态,且其状态改变的规则在时间和空间上都是局部的。 元 胞自动机是由空间上各项同性的一系列元胞所组成,是在有限元胞自动机基础上发 展起来的,用于模拟和分析几何空间内的各种现象。
1. S. Wolfram和初等元胞自动机
初等元胞自动机(Elementary Cellular Automata,ECA), 状态集S只有两个元素{s1,s2},即状态个数k=2,邻居半径r=l的一维元胞自动机
对于三个变量,每个变量有(0,1)两种状态值,所以共有2*2*2=8种 组合 ,8种组合分别对应0和1,所以共有2^8=256种 规则, 然后将这256种规则转换为十进制值R,表示第R号初等元胞自动机。 S. Wolfram对这256种模型一一进行了详细而深入的研究。研究表明,尽管初等元胞自动机是如此简单,但它们表现出各种各样的高度复杂的空间形态。经过一定时间,有些元胞自动机生成一种稳定状态,或静止,或产生周期性结构,而有些产生自组织、自相似的分形结构。
2. J. Conway和 "生命游戏"
生命游戏 (Came of Life)是J. H. Conway在20世纪60年代末设计的一种单人玩的计算机游戏(Garclner,M.,1970、1971)。他与现代的围棋游戏在某些特征上略有相似:围棋中有黑白两种棋子。生命游戏中的元胞有{ "生","死" }两个状态 {0,1};围棋的棋盘是规则划分的网格,黑白两子在空间的分布决定双方的死活,而生命游戏也是规则划分的网格(元胞似国际象棋分布在网格内。而不象围棋的棋子分布在格网交叉点上)。根据元胞的 局部空间构形 来决定生死。只不过规则更为简单。规则如下:
(1)元胞分布在规则划分的格网上
(2)元胞具有0,1两种状态
(3)元胞以相邻的8个元胞为邻居,即Moore邻居形式
(4)一个元胞的生死由其在该时刻本身的生死状态和周围的八个邻居的状态(和)决定:
当前时刻,如果一个元胞的状态为生(1),且邻居中有 两个或三个 的状态为生(1),则下一时刻该元胞继续为生(1),否则该元胞为死(0)
当前时刻,如果一个元胞的状态为死(0),且邻居中正好有 三个 的状态为生(1),则下一时刻该元胞为生(1),否则该元胞为死(0)
尽管它的规则看上去很简单。但生命游戏是具有产生动态图案和动态结构能力的元胞自动机模型。它能产生丰富的、有趣的图案。生命游戏的优化与初始元胞状态值的分布有关,给定任意的初始状态分布。经过若干步的运算,有的图案会很快消失。而有的图案则固定不动,有的周而复始重复两个或几个图案,有的婉蜒而行
遵循的规则:
1. 如果一个细胞周围有3个细胞为生(一个细胞周围共有8个细胞),则该细胞为生(即该细胞若原先为死,则转为生,若原先为生,则保持不变) 。
2. 如果一个细胞周围有2个细胞为生,则该细胞的生死状态保持不变;
3. 在其它情况下,该细胞为死(即该细胞若原先为生,则转为死,若原先为死,则保持不变) 设定图像中每个像素的初始状态后依据上述的游戏规则演绎生命的变化,由于初始状态和迭代次数不同,将会得到不同的图案
import numpy as np
import matplotlib.pyplot as plt
tmp=np.array([[0, 0, 0, 0, 0],
[0, 0, 1, 1, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
tmp=np.array([[1, 1, 1],
[1, 1, 1],
[1, 1, 0]])
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
#初始化随机整数矩阵
#相当于设置了原始的LUCC情况的栅格图
self.cells[1:-1,1:-1]=np.random.randint(2,size=(real_width,real_height))
#可以自己初始化背景矩阵
#self.cells=tmp
#运算步数
self.timer=0
#检测窗口的初始化 3*3 中间元胞初始值为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的显示模式 阻塞/交互
plt.ion()
for _ in range(n_iter):
plt.title('Iter :{}'.format(self.timer))
plt.imshow(self.cells)
self.update_state()
plt.pause(1)
plt.ioff()
if __name__=='__main__':
game=GameOfLife(cells_shape=(15,15))
game.update_and_plot(5)
参考资料: https://www.jianshu.com/p/701228dc496b
http://swarmagents.cn.13442.m8849.cn/complex/models/ca/ca1.htm