元胞自动机(Cellular Automata,CA)是一种用来仿真局部规则和局部联系的方法。典型的元胞自动机是定义在网格上的,每一个点上的网格代表一个元胞与一种有限的状态。变化规则适用于每一个元胞并且同时进行。元胞自动机也是一类模型的总称,或者说是一个方法框架。其特点是时间、空间、状态都离散,每个变量只取有限多个状态,且其状态改变的规则在时间和空间上都是局部的。
元胞自动机的动力学行为归纳为四大类(Wolfram. S.,1986):
另一角度,元胞自动机可视为动力系统,因而可将初始点、轨道、不动点、周期轨和终极轨等一系列概念用到元胞自动机的研究中
元胞自动机以计算机建模和仿真的方法,研究类似于生物细胞(cell)的,由大量并行单元个体组成的复杂系统的宏观行为与规律。L-系统、格子气模型、格子气-Boltzmann方法、交通流模型等都是元胞自动机的具体化,有着重要的理论意义和实际应用价值。
1. 生命游戏
生命游戏(Game of Life),或者叫它的全称John Conway’s Game of Life。是英国数学家约翰·康威在1970年代所发明的一种元胞自动机生命游戏
规则
在二维平面上的方格细胞里,每个细胞有两种状态:死或活,而下一回合的状态完全受它周围8个细胞的状态而定。按照以下三条规则进行演化:
活细胞周围的细胞数小于2个或多于3个则死亡;
活细胞周围有2或3个细胞可以继续存活;
死细胞周围恰好有3个细胞则会复活。
2. 交通领域
元胞自动机常常被用来模拟道路上的车辆或移动的行人。
元胞自动机的规则设定
周围有三个邻居的时候就能存活,周围有两个邻居的时候,生命状态不变,其他的时候元胞就死亡呢?
(规则原因)
这是因为生命的存活其实是需要非常严苛的条件的,当周围其他生命过多时,环境舒适度就会下降,元胞自然就会感觉到不适,所以存活率就会降低,而当周围生其他生命数量过少时也不适宜生命的存活,只有当周围其他生命的数量维持在一个区间时,生命才能够生存下
NaSch模型是对184号模型的推广,1992年Nagle和Schreckenberg提出了著名的NaSch模型,在这一模型中,时间、空间以及速度都被离散化,道路被划分为离散的格子(即元胞),每个元胞都是空的,或者被一辆车占据,每辆车的速度可以取1,2,…,Vmax ,Vmax 为最大速度。在时间步增加的过程中,模型按照如下规则进行演化。
import matplotlib as mpl
import matplotlib.pyplot as plt
import random
//创建图像
fig = plt.figure(figsize=(10,1))
#模型参数设置
numofcell = 20 # 道路长度
numofcar = 12 # 空间中的车辆数
max_time = 100 # 设置最大时间步
max_speed = 5 # 允许的车辆最大速度
p_slowdown = 0.3 # 随机慢化概率
pause_time = 0.1 # 刷新时间(每一帧持续的时间)
cell_size = 15 # 元胞的大小
#函数:构建一维空间
def Plot_Space():
for i in range(1, numofcell): plt.plot([i-0.5, i-0.5], [-0.5, 0.5], '-k', linewidth = 0.5)
plt.axis([-0.5, numofcell-0.5, -0.5, 0.5])
plt.xticks([]);plt.yticks([])
# 函数:获取和前车的距离
def get_empty_front(link, numofcell, indexofcell):
link2 = link * 2 # 周期性边界
num = 0; i = 1
while (link2[indexofcell + i]) == None:
num += 1; i += 1
return num
3. 随机生成初始元胞
Plot_Space()
link = [None] * numofcell
num = 0
while num != numofcar:
sj = random.randint(0, numofcell - 1)
if link[sj] == None:
link[sj] = random.randint(0, 5)
num += 1
# NaSch模型
for t in range(0, max_time):
for cell in range(0, numofcell):
if link[cell] != None:
# 加速
link[cell] = min(link[cell] + 1, max_speed)
# 减速
link[cell] = min(link[cell], get_empty_front(link, numofcell, cell))
# 随机慢化
if random.random() <= p_slowdown:
link[cell] = max(link[cell] - 1, 0)
# 位置更新
nlink = [None] * numofcell
for cell in range(0, numofcell):
if link[cell] != None:
new_index = cell + link[cell]
if new_index >= numofcell:
new_index -= numofcell
nlink[new_index] = link[cell]
link = nlink
x1 = []
for i in range(0,len(link)):
if link[i] != None:
x1.append(i)
Plot_Space()
plt.plot(x1, [0] * numofcar, 'sk', markersize=cell_size)
plt.xlabel('timestep:' + str(t))
plt.pause(pause_time)
plt.cla()