python仿真图_简单几步实现NaSch模型的Python仿真

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实现老规矩,先调包,并创建一个图像

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 # 元胞的大小定义一个函数来构建一维空间,空间的长度就是道路长度,相当于用一系列和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([])定义一个函数来获取和前车的距离,从而避免两车相撞。在这里采用了周期性边界,即从道路末端驶出的小车会重新回到起点,相当于一个环路。

# 函数:获取和前车的距离

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在道路空间中随机生成numofcar个初始元胞,并赋予随机的初始速度(不大于已经设置好的最大速度)。道路被车辆占有的状态储存在列表link中,若元胞中没有车辆,则link对应的位置为“None”;若元胞中有车,link对应的位置储存车辆的速度。(可以开开脑洞,大胆地尝试不同初始状态噢)

# 随机生成初始元胞

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在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绘制当前时间步车辆位置的图像,注意这里有缩进,说明上一段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))让图片动起来(**同样注意缩进**),plt.pause()函数让当前的图像维持pause_time长的时间,随后plt.cla()函数将整个图像擦除。下一个时间步,继续绘制图像,保留一段时间,并擦除,再绘制图像……就能源源不断地产生动画啦!

plt.pause(pause_time)

plt.cla()

终于写完代码啦,RUN一下!

仔细看,拥堵带也会跳鬼步舞,逐渐向后传播的。

操控我的“遥控器”,给它一个初始状态,就可以开启“阅兵模式”啦,你猜我是怎么做到的?

给我开“瞬移”挂,只要动的足够快,你就分不清我到底是往左跑还是往右跑

是不是很有趣呢?

以上内容首发于公众号【交通科研Lab】!

我们是一个有灵魂的团队,坚持探索,致力于分享交流学习经验。想学习更多交通编程知识的小伙伴可以移步关注噢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值