元胞自动机

元胞自动机

元胞自动机定义

元胞自动机(Cellular Automata,CA)是一种用来仿真局部规则和局部联系的方法。典型的元胞自动机是定义在网格上的,每一个点上的网格代表一个元胞与一种有限的状态。变化规则适用于每一个元胞并且同时进行。元胞自动机也是一类模型的总称,或者说是一个方法框架。其特点是时间、空间、状态都离散,每个变量只取有限多个状态,且其状态改变的规则在时间和空间上都是局部的。

元胞自动机分类

元胞自动机的动力学行为归纳为四大类(Wolfram. S.,1986):

  • 平稳型:自任何初始状态开始,经过一定时间运行后,元胞空间趋于一个空间平稳的构形,这里空间平稳即指每一个元胞处于固定状态。不随时间变化而变化。
  • 周期型:经过一定时间运行后,元胞空间趋于一系列简单的固定结构(Stable Patterns)或周期结构(Perlodical Patterns)。由于这些结构可看作是一种滤波器(Filter),故可应用到图像处理的研究中。
  • 混沌型:自任何初始状态开始,经过一定时间运行
    后,元胞自动机表现出混沌的非周期行为,所生成的结构的统计特征不再变止,通常表现为分形分维特征。
  • 复杂型:出现复杂的局部结构,或者说是局部的混沌,其中有些会不断地传播。

另一角度,元胞自动机可视为动力系统,因而可将初始点、轨道、不动点、周期轨和终极轨等一系列概念用到元胞自动机的研究中

元胞自动机的应用

元胞自动机以计算机建模和仿真的方法,研究类似于生物细胞(cell)的,由大量并行单元个体组成的复杂系统的宏观行为与规律。L-系统、格子气模型、格子气-Boltzmann方法、交通流模型等都是元胞自动机的具体化,有着重要的理论意义和实际应用价值。

1. 生命游戏
生命游戏(Game of Life),或者叫它的全称John Conway’s Game of Life。是英国数学家约翰·康威在1970年代所发明的一种元胞自动机👉生命游戏

规则
在二维平面上的方格细胞里,每个细胞有两种状态:死或活,而下一回合的状态完全受它周围8个细胞的状态而定。按照以下三条规则进行演化:

  1. 活细胞周围的细胞数小于2个或多于3个则死亡;

  2. 活细胞周围有2或3个细胞可以继续存活;

  3. 死细胞周围恰好有3个细胞则会复活。

2. 交通领域

元胞自动机常常被用来模拟道路上的车辆或移动的行人。

  • 经典的NaSch模型,车辆在一维道路上行驶
    在这里插入图片描述
  • 考虑行人流的换道,将CA模型推广到二维
    在这里插入图片描述
  • 基于行人特性的对向行人流,元胞们会自己排队从而避免对向冲突
    在这里插入图片描述

元胞自动机的基本要素

  • 空间:元胞在空间中分布的空间格点,可以是一维、二维或多维。
  • 状态集:可以是两种状态,用“生”、“死”,“0”、“1”,“黑”、“白”来表示;也可以是多种状态,如不同的颜色。
  • 邻居:存在与某一元胞周围,能影响该元胞在下一时刻的状态。
  • 演化规则:根据元胞及其邻居元胞的状态,决定下一时刻该元胞状态的动力学函数,也可以是状态转移方程。

元胞自动机的规则设定
周围有三个邻居的时候就能存活,周围有两个邻居的时候,生命状态不变,其他的时候元胞就死亡呢?
(规则原因)
这是因为生命的存活其实是需要非常严苛的条件的,当周围其他生命过多时,环境舒适度就会下降,元胞自然就会感觉到不适,所以存活率就会降低,而当周围生其他生命数量过少时也不适宜生命的存活,只有当周围其他生命的数量维持在一个区间时,生命才能够生存下

NaSch模型

NaSch模型是对184号模型的推广,1992年Nagle和Schreckenberg提出了著名的NaSch模型,在这一模型中,时间、空间以及速度都被离散化,道路被划分为离散的格子(即元胞),每个元胞都是空的,或者被一辆车占据,每辆车的速度可以取1,2,…,Vmax ,Vmax 为最大速度。在时间步增加的过程中,模型按照如下规则进行演化。

  • 加速规则:Vn —> min(Vn+1, Vmax),直观上的解释是若能加速则速度加一,反应了司机倾向于以尽可能大的速度行驶的特点
    在这里插入图片描述
  • 减速规则:Vn —> min(Vn, Dn),以确保车辆不会与前车发生碰撞。
    在这里插入图片描述
  • 随机变化:以随机概率p令Vn —> max(Vn-1,0),该规则用来体现驾驶人的行为差异,这样既可以反映随机加速行为,又可以反映减速过程中的过度反应行为。这一规则也是堵塞自发产生的至关重要因素。
    在这里插入图片描述
  • 位置更新:Xn —> Xn+Vn,车辆按照更新后的速度继续向前移动。

NaSch模型Python的实现

  1. 老规矩,先调包,并创建一个图像
    在这里插入图片描述
import matplotlib as mpl
import matplotlib.pyplot as plt
import random
//创建图像
fig = plt.figure(figsize=(10,1))
  1. 设置模型的参数,相当于一个遥控器,哪里不对点哪里~
 #模型参数设置
numofcell = 20     # 道路长度
numofcar = 12      # 空间中的车辆数
max_time = 100     # 设置最大时间步
max_speed = 5      # 允许的车辆最大速度
p_slowdown = 0.3   # 随机慢化概率
pause_time = 0.1   # 刷新时间(每一帧持续的时间)
cell_size = 15     # 元胞的大小
  1. 定义一个函数来构建一维空间,空间的长度就是道路长度,相当于用一系列和X轴或Y轴平行的直线,绘制一排小网格,每个小网格的中心,相当于(i,0),其中,i=1,2,…,numofcell
#函数:构建一维空间
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([])
  1. 定义一个函数来获取和前车的距离,从而避免两车相撞。在这里采用了周期性边界,即从道路末端驶出的小车会重新回到起点,相当于一个环路。
# 函数:获取和前车的距离
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
  1. 在道路空间中随机生成numofcar个初始元胞,并赋予随机的初始速度(不大于已经设置好的最大速度)。道路被车辆占有的状态储存在列表link中,若元胞中没有车辆,则link对应的位置为“None”;若元胞中有车,link对应的位置储存车辆的速度。(可以开开脑洞,大胆地尝试不同初始状态噢)
 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

  1. 在0~max_time的时间步内,进行NaSch模型的演化。
# 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
  1. 绘制当前时间步车辆位置的图像,注意这里有缩进,说明上一段NaSch模型演化代码中的for循环还没有结束呦~
  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))
  1. 让图片动起来(同样注意缩进),plt.pause()函数让当前的图像维持pause_time长的时间,随后plt.cla()函数将整个图像擦除。下一个时间步,继续绘制图像,保留一段时间,并擦除,再绘制图像……就能源源不断地产生动画啦!
 plt.pause(pause_time)
    plt.cla()

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司六米希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值