前言
想不到元胞自动机看的人更多,就写写吧。
听说有人想要看,今天就抽时间现场写了个NaSch的很简单的代码
各位大哥,代码是用lua写的,在MicroCity里运行的,不要问为啥报错了?你用前朝的剑来斩本朝的官,能好使么?
第六章 道路交通流中的元胞自动机模型
既然是交通系统中的元胞自动机模型,就需要对现实世界中的交通系统进行分析,了解它的组成和运行机理。而元胞自动机主要的应用领域还是在道路交通流中。包括:
- 单车道交通流
- 多车道交通流
- 双向交通流
- 自行车流
- 机非混合交通流
当然最简单最基础的就是单车道交通流了,也是其他场景的基础。
6.1 单车道元胞自动机模型
-
并行更新与顺序更新
-
step 1: 加速
-
step 2 : 减速
-
step 3 : 随机慢化
-
step 4 : 运动
其实这四步可以归纳成两部分,一是速度状态调整,二是位置状态调整。 -
边界条件
- 周期性边界条件
- 开口边界条件
- 初始状态
local Sim = AddModule('NaSch','Start')
ROADX = AddParameter(Sim, nil, 'value', 'The size of the Road at X', 20)
ROADY = AddParameter(Sim, nil, 'value', 'The size of the Road at Y', 1)
Vehicle = {}
Vehicle.__index = Vehicle
function Vehicle:new(max_speed, p, x, v)
local self = {Vmax = max_speed, p = p, x = x, v = v}
setmetatable(self, Vehicle)
return self
end
function Vehicle:setHead(veh)
self.head = veh
end
function Vehicle:getDis()
return self.head.x - self.x - 1
end
function Vehicle:accelerate()
self.v = math.min(self.v + 1, self.Vmax)
end
function Vehicle:brake()
self.v = math.min(self.v, self:getDis())
end
function Vehicle:random()
self.v = math.random() < self.p and math.max(self.v - 1, 0) or self.v
end
function Vehicle:move()
self.x = self.x + self.v
end
function updateRoad()
for i=0,ROADX do
SetValue(road, 0, i, 1)
end
for i=1,#vehicles do
SetValue(road, 1, vehicles[i].x, 1)
end
Update(road)
end
function OpenBoundary()
if vehicles[1].x > ROADX then
table.remove(vehicles, 1)
vehicles[1].head = boundary
end
end
function NaSch()
road = CreateGrid('Nature', 'int', ROADX, ROADY)
boundary = Vehicle:new(0, 0, ROADX + 2, 0)
vehicles = {
Vehicle:new(2, 0.25, 7, 0),
Vehicle:new(2, 0.25, 6, 1),
Vehicle:new(2, 0.25, 3, 1),
Vehicle:new(2, 0.25, 1, 2),
}
vehicles[1]:setHead(boundary)
for i=2,#vehicles do
vehicles[i]:setHead(vehicles[i-1])
end
local tick = 0
while GetReady() do
updateRoad()
for i=1,#vehicles do
vehicles[i]:accelerate()
end
for i=1,#vehicles do
vehicles[i]:brake()
end
for i=1,#vehicles do
vehicles[i]:random()
end
for i=1,#vehicles do
vehicles[i]:move()
end
OpenBoundary()
if tick % 5 == 0 then
table.insert(vehicles, Vehicle:new(2, 0.25, 0, 0))
vehicles[#vehicles].head = vehicles[#vehicles-1] or boundary
end
tick = tick + 1
Sleep(10000)
end
end