虽然交通并不总是畅通无阻,但汽车无缝穿越交叉路口,在交通信号灯处转弯和停车看起来相当壮观。这种沉思让我思考交通流对人类文明的重要性。

在此之后,内心的书呆子特质让我忍不住思考一种模拟交通流的方法。我在一个涉及交通流量的本科项目上投入了几个星期的时间,深入到不同的模拟技术,最终选择了一个。

在本文中,我将解释为什么交通流模拟很重要,比较不同的方法来模拟交通流,并呈现仿真结果(以及源代码)。

1、为什么要模拟交通流?

模拟交通流的主要原因是在没有真实世界的情况下生成数据。你可以使用软件运行模型来预测交通流,而不需要在现实世界中安装传感器来测试新的管理思路如何影响现实世界。这有助于加速交通流系统的优化和数据收集。仿真是实际测试更便宜、更快捷的替代方案。

训练机器学习模型需要巨大的数据集,这些数据集的收集和处理成本可能很高。通过模拟交通流在程序上生成数据可以很容易地适应所需的数据类型。

2、建 模

要分析和优化交通系统,我们首先必须对交通系统进行数学建模。这种模型应根据输入参数(路网几何、每分钟车辆、车速等)真实地表示交通流量。

交通流系统模型通常分为三类,具体取决于它们在哪个级别上运行:

  • 微型模型:分别代表每辆车,并尝试复现驾驶员行为。
  • 宏观模型:从交通密度(每公里车辆)和交通流量(车辆每分钟)的角度描述车辆的整体移动。它们通常类似于流体的流动。
  • 中观模型:是结合微观和宏观模型特点的混合模型,将流量建模为车辆的"包"。
    在本文中,我将使用微观模型。

3、微观模型

在微观模型中使用驾驶员模型描述单个驾驶员/车辆的行为。因此,它必须是一个多代理系统,即每辆车都使用来自其环境的输入自行运行。

在微观模型中,每辆车都编号为i。第i辆车跟随第(i-1)辆车。对于第i辆车,我们将用xi表示其沿路的位置,用vi表示其速度,以及li表示其长度。每辆车都是如此。

我们将用si表示保险杠到保险杠的距离,用Δvᵢ 表示第i辆车和前面的第i-1辆车之间的速度差异。

4、智能驾驶员模型 (IDM)

2000年,Treiber, Hennecke 和 Helbing开发了智能驾驶员模型,它描述第i辆车的加速度是其变量和前面车辆的变量的函数。动态方程的定义为:

在我解释这个模型背后的直觉之前,我应该先解释下这些符号代表什么。

我们已经谈到了sᵢ, vᵢ, andΔvᵢ。其他参数包括:

  • s0i:是第i辆车和第i-1辆车之间的最小期望距离。
  • v0i :是第i辆车的最大期望速度.
  • δ:是加速度指数,它控制着加速度的"平滑度"。
  • Ti:是第i辆车的驾驶员的反应时间。
  • ai :是第i辆车的最大加速度。
  • bi :是第i辆车的舒适减速度.
  • s* : 是第i辆车和第i-1辆车之间的实际期望距离。

首先,我们将看看s*,这是一个距离,它由三部分组成。

  • s0i:如前所言,是所需的最小距离。

  • viTi:是反应时间的安全距离。这是车辆在驾驶员反应(刹车)前行驶的距离。由于速度是随着时间推移而保持的距离,距离是速度乘以时间。

  • (vᵢ Δvᵢ)/√(2aᵢ bᵢ):这个有点复杂,这是一个基于速度差的安全距离。它表示车辆在非紧急刹车时(减速度应小于bi),不撞到前面的车辆的前提下所需的距离。

5、智能驾驶员模型的工作原理

车辆假定沿着一条直道行驶,并假定遵守以下方程:

为了更好地了解这个等式,我们可以将其一分为二。我们有一个自由道路加速度和交互加速度。

自由道路加速度是自由道路上的加速,即没有车辆的空路。如果我们绘制加速度作为速度vi的函数,可以得到:

我们注意到,当车辆静止(vi=0)时,加速是最大的。当车速接近最高速度时,加速变为 0。这表明,自由道路加速度将加速车辆到最高速度。

如果我们绘制不同值的δ的 v-a 图,我们会注意到它控制驾驶员在接近最大速度时减速的速度。这反过来又控制了加速度/减速度的平滑度。


交互加速度与与前方车辆的交互有关。为了更好地了解它是如何工作的,让我们考虑以下情况:

  • 在自由路上(si >>s*):
    当前面的车辆很远时,即si远远大于车辆之间所需的安全距离s*,交互加速度几乎为0。这意味着车辆将受到自由道路加速的制约。

  • 在高接近速率((Δvᵢ):
    当速度差很大时,交互加速度试图通过分子中的(vᵢΔvᵢ)²项进行制动补偿,但过于困难。这是通过分母中4bᵢsᵢ²实现的(老实说,我不知道它如何精确限制减速到bᵢ)。

  • 在小距离差(si <<1和Δvᵢ≈0):
    加速度成为一个简单的排斥力。

6、交通道路网络模型

我们需要模拟道路网络。为此,我们将使用有向图 G =(V、E),其中:

  • V是一组顶点(或节点)。
  • E是代表道路的边的几何。

每辆车将沿着一条由多个路段(边)组成的路径形式。我们将在同一路段(边)上的车辆应用智能驾驶员模型。当车辆到达路的尽头时,我们会将其从该路段移开并附加到下一路段上。

在仿真中,我们不会保留一组节点(阵列),相反,每条道路都将由其开始和结束节点的值明确定义。

7、随机车辆发生器

为了将车辆添加到我们的模拟中,我们有两个选项:

  • 通过创建新的Vehicle类实例并将其添加到车辆列表中,手动将每辆车添加到模拟中。
  • 根据预先定义的概率,随机添加车辆。

对于第二个选项,我们必须定义一个随机车辆发生器。

随机车辆发生器由两个约束定义:

  • 车辆生成速率(τ): 平均每分钟应添加到仿真中的车辆数。
  • 车辆配置列表 (L):车辆配置和生成概率的元组列表。

L = [(p1,V1),(p2,V2),(p3,V3]),…
随机车辆发生器以概率pi生成车辆Vi。

8、交通信号灯

红绿灯位于路段端点上,其特点是包含以下两个区域:

  • 减速区:以减速距离和减速系数为特征,是车辆使用减速系数减速的区域。

  • 停车区:以停车距离为特征,是车辆停车的区域。这是通过此动态方程使用阻尼力实现的:

9、仿真

我们将采用面向对象的方法。每辆车和道路将被定义为一个类。

我们将反复使用以下的__init__函数。它通过一个函数set_default_config设置当前类的默认配置,并将一个字典中的属性设置为当前类实例的属性。这样,我们不必担心更新不同类别的__init__函数或将来的变化。

def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)

我们将为路段创建一个Road类:

from scipy.spatial import distanceclass Road:def __init__(self, start, end):self.start = startself.end = endself.init_porperties()def init_properties(self):self.length = distance.euclidean(self.start, self.end)self.angle_sin = (self.end[1]-self.start[1]) / self.lengthself.angle_cos = (self.end[0]-self.start[0]) / self.length

当在屏幕上绘制道路及其角度的正弦和余弦时,我们需要道路的长度length。

还有一个Simulation类,让我们添加了一些方法来将道路添加到仿真里。

from .road import Roadclass Simulation:def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)def set_default_config(self):self.t = 0.0            # Time keepingself.frame_count = 0    # Frame count keepingself.dt = 1/60          # Simulation time stepself.roads = []         # Array to store roadsdef create_road(self, start, end):road = Road(start, end)self.roads.append(road)return roaddef create_roads(self, road_list):for road in road_list:self.create_road(*road)

我们必须在屏幕上实时显示我们的仿真。为此,我们将使用pygame。我将创建一个Window类,以类Simulation作为参数。

我定义了多个绘图函数,有助于绘制基本形状。

该loop方法创建一个pygame窗口,并在每一帧调用draw方法和loop参数。当我们的仿真需要逐帧更新时,这将变得有用。

import pygame
from pygame import gfxdraw
import numpy as npclass Window:def __init__(self, sim, config={}):# Simulation to drawself.sim = sim# Set default configurationsself.set_default_config()# Update configurationsfor attr, val in config.items():setattr(self, attr, val)def set_default_config(self):"""Set default configuration"""self.width = 1400self.height = 1000self.bg_color = (250, 250, 250)self.fps = 60self.zoom = 5self.offset = (0, 0)self.mouse_last = (0, 0)self.mouse_down = Falsedef loop(self, loop=None):"""Shows a window visualizing the simulation and runs the loop function."""# Create a pygame windowself.screen = pygame.display.set_mode((self.width, self.height))pygame.display.flip()# Fixed fpsclock = pygame.time.Clock()# To draw textpygame.font.init()self.text_font = pygame.font.SysFont('Lucida Console', 16)# Draw looprunning = Truewhile not self.sim.stop_condition(self.sim) and running:# Update simulationif loop: loop(self.sim)# Draw simulationself.draw()# Update windowpygame.display.update()clock.tick(self.fps)# Handle all eventsfor event in pygame.event.get():# Handle mouse drag and wheel events...def convert(self, x, y=None):"""Converts simulation coordinates to screen coordinates"""...def inverse_convert(self, x, y=None):"""Converts screen coordinates to simulation coordinates"""...def background(self, r, g, b):"""Fills screen with one color."""...def line(self, start_pos, end_pos, color):"""Draws a line."""...def rect(self, pos, size, color):"""Draws a rectangle."""...def box(self, pos, size, color):"""Draws a rectangle."""...def circle(self, pos, radius, color, filled=True):"""Draws a circle"""...def polygon(self, vertices, color, filled=True):"""Draws a polygon"""def rotated_box(self, pos, size, angle=None, cos=None, sin=None, centered=True, color=(0, 0, 255), filled=True):"""Draws a filled rectangle centered at *pos* with size *size* rotated anti-clockwise by *angle*."""def rotated_rect(self, pos, size, angle=None, cos=None, sin=None, centered=True, color=(0, 0, 255)):"""Draws a rectangle centered at *pos* with size *size* rotated anti-clockwise by *angle*."""def draw_axes(self, color=(100, 100, 100)):"""Draw x and y axis"""def draw_grid(self, unit=50, color=(150,150,150)):"""Draws a grid"""def draw_roads(self):"""Draws every road"""def draw_status(self):"""Draws status text"""def draw(self):# Fill backgroundself.background(*self.bg_color)# Major and minor grid and axesself.draw_grid(10, (220,220,220))self.draw_grid(100, (200,200,200))self.draw_axes()# Draw roadsself.draw_roads()# Draw status infoself.draw_status()

我将trafficSimulator文件夹中的每一个文件使用__init__.py组合在一起。

from .road import *
from .simulation import *
from .window import *

每当定义新类时,应在此文件中导入该类。

将trafficSimulator文件夹放置在我们的项目文件夹中将以便使用仿真模块。

from trafficSimulator import *# Create simulation
sim = Simulation()# Add one road
sim.create_road((300, 98), (0, 98))# Add multiple roads
sim.create_roads([((300, 98), (0, 98)),((0, 102), (300, 102)),((180, 60), (0, 60)),((220, 55), (180, 60)),((300, 30), (220, 55)),((180, 60), (160, 98)),((158, 130), (300, 130)),((0, 178), (300, 178)),((300, 182), (0, 182)),((160, 102), (155, 180))])# Start simulation
win = Window(sim)
win.loop()

10、车辆

现在,我们必须增加车辆。

我们将使用Taylor级数来近似求解本文建模部分所讨论的动态方程。

一个微分方程f的泰勒级数展开是:

使用▲x替换a,使用x+▲x替换x, 我们得到:

使用位置x替换f:

作为一个近似,对位置我们将在2阶截止,因为加速度是最高阶导数。我们得到方程(2):

对于速度,我们将用v代替x:

我们将在1阶 停止,因为速度是1阶导数。方程(2):

在每个迭代(或帧)中,使用 IDM 公式计算加速度后,我们将使用以下两个方程更新位置和速度:

在代码中看起来像这样:

self.a = ...      # IDM formula
self.v += self.a*dt
self.x += self.v*dt + self.a*dt*dt/2

由于这只是一个近似值,速度有时可能会变为负值(但模型不允许这样)。当速度为负时,会产生不稳定性,位置和速度会分化为负无穷大。

为了克服这个问题,每当我们预测负速度时,我们就会将其设定为零,并从那里找出方法:

在代码中,此实现如下:

if self.v + self.a*dt < 0:self.x -= 1/2*self.v*self.v/self.aself.v = 0
else:self.v += self.a*dtself.x += self.v*dt + self.a*dt*dt/2

要计算 IDM 加速度,我们将引导车辆表示为lead,并当lead不是None时,计算一个交互项(用alpha表示)。

alpha = 0
if lead:delta_x = lead.x - self.x - lead.ldelta_v = self.v - lead.valpha = (self.s0 + max(0, self.T*self.v + delta_v*self.v/self.sqrt_ab)) / delta_x
self.a = self.a_max * (1-(self.v/self.v_max)**4 - alpha**2)

如果车辆停止(例如在红绿灯处),我们将使用阻尼方程:

if self.stopped: self.a = -self.b_max*self.v/self.v_max

然后,我们将所有内容整合在Vehicle类的update方法中:

import numpy as npclass Vehicle:def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)# Calculate propertiesself.init_properties()def set_default_config(self):    self.l = 4self.s0 = 4self.T = 1self.v_max = 16.6self.a_max = 1.44self.b_max = 4.61self.path = []self.current_road_index = 0self.x = 0self.v = self.v_maxself.a = 0self.stopped = Falsedef init_properties(self):self.sqrt_ab = 2*np.sqrt(self.a_max*self.b_max)self._v_max = self.v_maxdef update(self, lead, dt):# Update position and velocityif self.v + self.a*dt < 0:self.x -= 1/2*self.v*self.v/self.aself.v = 0else:self.v += self.a*dtself.x += self.v*dt + self.a*dt*dt/2# Update accelerationalpha = 0if lead:delta_x = lead.x - self.x - lead.ldelta_v = self.v - lead.valpha = (self.s0 + max(0, self.T*self.v + delta_v*self.v/self.sqrt_ab)) / delta_xself.a = self.a_max * (1-(self.v/self.v_max)**4 - alpha**2)if self.stopped: self.a = -self.b_max*self.v/self.v_maxdef stop(self):self.stopped = Truedef unstop(self):self.stopped = Falsedef slow(self, v):self.v_max = vdef unslow(self):self.v_max = self._v_max

在Road类中,我们将添加一个deque(双端队列)来跟踪车辆。队列是存储车辆的较好的数据结构,因为队列中的第一辆车是路上最远的车辆,它是第一个可以从队列中删除的车辆。要从deque 中删除第一个车辆,我们可以使用self.vehicles.popleft() 。

我们将在Road类中添加一个update方法:

def update(self, dt):n = len(self.vehicles)if n > 0:# Update first vehicleself.vehicles[0].update(None, dt)# Update other vehiclesfor i in range(1, n):lead = self.vehicles[i-1]self.vehicles[i].update(lead, dt
在Simulation类中添加一个update方法:def update(self):# Update every roadfor road in self.roads:road.update(self.dt)# Check roads for out of bounds vehiclefor road in self.roads:# If road has no vehicles, continueif len(road.vehicles) == 0: continue# If notvehicle = road.vehicles[0]# If first vehicle is out of road boundsif vehicle.x >= road.length:# If vehicle has a next roadif vehicle.current_road_index + 1 < len(vehicle.path):# Update current road to next roadvehicle.current_road_index += 1# Create a copy and reset some vehicle propertiesnew_vehicle = deepcopy(vehicle)new_vehicle.x = 0# Add it to the next roadnext_road_index = vehicle.path[vehicle.current_road_index]self.roads[next_road_index].vehicles.append(new_vehicle)# In all cases, remove it from its roadroad.vehicles.popleft()

回到Window类,添加了一个run方法来实时更新仿真:

def run(self, steps_per_update=1):"""Runs the simulation by updating in every loop."""def loop(sim):sim.run(steps_per_update)self.loop(loop)

现在我们将手动添加车辆:

sim.roads[4].vehicles.append(Vehicle({"path": [4, 3, 2]})
)sim.roads[0].vehicles.append(Vehicle())
sim.roads[1].vehicles.append(Vehicle())
sim.roads[6].vehicles.append(Vehicle())
sim.roads[7].vehicles.append(Vehicle())

车辆生成器代码如下:

from .vehicle import Vehicle
from numpy.random import randintclass VehicleGenerator:def __init__(self, sim, config={}):...def set_default_config(self):self.vehicle_rate = 20self.vehicles = [(1, {})]def init_properties(self):self.upcoming_vehicle = self.generate_vehicle()def generate_vehicle(self):"""Returns a random vehicle from self.vehicles with random proportions"""...def update(self):"""Add vehicles"""...

VehicleGenerator包含(odds, vehicle) 元组的列表。

元组第一个元素是在同一元组中生成车辆的权重(不是概率)。我使用权重, 因为它们更容易工作, 因为我们可以只使用整数。

例如,如果我们有3辆车权重分别为132,这相当于生成概率分别为1/6 , 3/6 ,2/66 。

为了实现这一点,我们使用以下算法

  • 生成1到权重和之间的数字r。
  • 当r是非负数:循环所有可能的车辆,并在每次迭代时减去其权重。
  • 返回最后使用的车辆。

如果我们有权重:W1,W2,W3。 此算法将在1和W 3之间的数字分配到第一辆车,将W₁ 到 W₁+W₂ 之间的数字分配给第二辆车,将W₁+W₂+W₃到结束的数字分配给第三辆车。

def generate_vehicle(self):"""Returns a random vehicle from self.vehicles with random proportions"""total = sum(pair[0] for pair in self.vehicles)r = randint(1, total+1)for (weight, config) in self.vehicles:r -= weightif r <= 0:return Vehicle(config)

每次生成器添加车辆时,last_added_time属性都会更新到当前时间。当当前时间和last_added_time之差值大于车辆生成周期时,添加车辆。

添加车辆的周期是60/vehicle_rate,因为vehicle_rate 的单位是车辆/每分钟,60表示1分钟或60秒。

我们还必须检查道路是否还有空间来添加即将行驶的车辆。我们通过检查道路上最后一辆车之间的距离和即将行驶的车辆的长度和安全距离的总和来做到这一点。

def update(self):"""Add vehicles"""if self.sim.t - self.last_added_time >= 60 / self.vehicle_rate:# If time elasped after last added vehicle is# greater than vehicle_period; generate a vehicleroad = self.sim.roads[self.upcoming_vehicle.path[0]]      if len(road.vehicles) == 0\or road.vehicles[-1].x > self.upcoming_vehicle.s0 + self.upcoming_vehicle.l:# If there is space for the generated vehicle; add itself.upcoming_vehicle.time_added = self.sim.troad.vehicles.append(self.upcoming_vehicle)# Reset last_added_time and upcoming_vehicleself.last_added_time = self.sim.tself.upcoming_vehicle = self.generate_vehicle()

最后,我们应该通过调用Simulation 的update方法来更新车辆生成。

sim.create_gen({'vehicle_rate': 60,'vehicles': [[1, {"path": [4, 3, 2]}],[1, {"path": [0]}],[1, {"path": [1]}],[1, {"path": [6]}],[1, {"path": [7]}]]
})

11、红绿灯

交通信号灯的默认属性是:

class TrafficSignal:def __init__(self, roads, config={}):# Initialize roadsself.roads = roads# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)# Calculate propertiesself.init_properties()def set_default_config(self):self.cycle = [(False, True), (True, False)]self.slow_distance = 40self.slow_factor = 10self.stop_distance = 15self.current_cycle_index = 0self.last_t = 0

self.cycle是self.roads 的一个数组,每个元组包含道路的状态(True绿色,False红色)。

在默认配置中,(False, True)表示第一组道路为红色,第二组道路为绿色。 (True, False) 则恰恰相反。

所以使用此方法之,是因为它易于扩展。我们创建红绿灯,包括超过 2 条道路、带有左右转弯单独信号的红绿灯,甚至用于多个交叉路口的同步交通信号灯。

交通信号灯的update函数应该是可定制的。其默认行为是对称的固定时间循环。

def init_properties(self):for i in range(len(self.roads)):for road in self.roads[i]:road.set_traffic_signal(self, i)@property
def current_cycle(self):return self.cycle[self.current_cycle_index]def update(self, sim):# Goes through all cycles every cycle_length and repeatscycle_length = 30k = (sim.t // cycle_length) % 2self.current_cycle_index = int(k)

我们需要在Road类添加以下方法:

def set_traffic_signal(self, signal, group):self.traffic_signal = signalself.traffic_signal_group = groupself.has_traffic_signal = True@property
def traffic_signal_state(self):if self.has_traffic_signal:i = self.traffic_signal_groupreturn self.traffic_signal.current_cycle[i]return True

而这个,在Road的update方法。

# Check for traffic signal
if self.traffic_signal_state:# If traffic signal is green or doesn't exist# Then let vehicles passself.vehicles[0].unstop()for vehicle in self.vehicles:vehicle.unslow()
else:# If traffic signal is redif self.vehicles[0].x >= self.length - self.traffic_signal.slow_distance:# Slow vehicles in slowing zoneself.vehicles[0].slow(self.traffic_signal.slow_speed)if self.vehicles[0].x >= self.length - self.traffic_signal.stop_distance and\self.vehicles[0].x <= self.length - self.traffic_signal.stop_distance / 2:# Stop vehicles in the stop zoneself.vehicles[0].stop()

在Simulation 的update 方法中检查交通灯状态:

for signal in self.traffic_signals:signal.update(self)

12、曲线

在现实世界中,道路有曲线。虽然从技术上讲,我们可以通过手写很多道路的坐标来接近曲线来创建此模拟中的曲线,但我们可以在程序上实现同样的事情。

我们将使用贝赛尔曲线来达到这个效果。

我创建了一个curve.py文件,其中包含有助于创建曲线并按其道路序号引用曲线的功能。

def curve_points(start, end, control, resolution=5):# If curve is a straight lineif (start[0] - end[0])*(start[1] - end[1]) == 0:return [start, end]# If not return a curvepath = []for i in range(resolution+1):t = i/resolutionx = (1-t)**2 * start[0] + 2*(1-t)*t * control[0] + t**2 *end[0]y = (1-t)**2 * start[1] + 2*(1-t)*t * control[1] + t**2 *end[1]path.append((x, y))return pathdef curve_road(start, end, turn_direction, resolution=15):points = curve_points(start, end, turn_direction, resolution)return [(points[i-1], points[i]) for i in range(1, len(points))]

测试:

from trafficSimulator import *# Create simulation
sim = Simulation()# Add multiple roads
sim.create_roads([((0, 100), (140, 100)),((150, 110), (150, 200)),*curve_road((140, 100), (150, 110), (150, 100))
])sim.create_gen({'vehicle_rate': 20,'vehicles': [[1, {"path": [0, *range(2, 17), 1]}]]
})# Start simulation
win = Window(sim)
win.run(steps_per_update=5)

13、示例

这些示例的代码可在 Github 中找到。

公路匝道入口

双向交叉路口

环形交叉路口

钻石型分流交叉路口

14、局限性

虽然我们可以修改Simulation类来存储有关我们以后可以使用的模拟数据,但如果数据收集过程更加简化,则更好。

这种模拟仍然缺乏很多。曲线的实现是糟糕和低效的,并导致车辆和交通信号之间的相互作用的问题。

虽然有些人可能认为智能驱动模型有点过头了,但重要的是要有一个模型,可以复制现实世界的现象,如交通波(又名幽灵交通蛇)和司机的反应时间的影响。因此,我选择使用智能驱动模型。但对于精度和极端现实主义不重要的仿真,就像在视频游戏中一样,IDM可以被一个更简单的基于逻辑的模型所取代。

完全依赖基于仿真的数据会增加过度拟合的风险。你的 ML 模型可以优化用于仅存在于仿真中的处理,并且在现实世界中不存在。

15、结论

仿真是数据科学和机器学习的重要组成部分。有时,从现实世界中收集数据是不可能的,或者成本很高。生成数据有助于以更好的价格构建巨大的数据集。仿真还有助于填补真实数据中的空白。在某些情况下,现实世界数据集缺少对开发模型至关重要的边缘案例。

这个仿真是我参与的本科学校项目的一部分。目的是优化城市交叉路口的交通信号。我制作了此仿真来测试和验证我的优化方法。

我从来没有想过发表这篇文章,直到我看到特斯拉的AI展示日,其中他们谈到他们如何使用仿真来生成数据的边缘样本。


原文链接:Python交通流仿真 - BimAnt

Python交通流仿真【含源码】相关推荐

  1. 【元胞自动机】保守策略元胞自动机三车道(不开放辅路,软件园影响)交通流模型matlab源码

    一.元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 · 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 · 何顿 ...

  2. 【元胞自动机】激进策略元胞自动机三车道(开放辅路,软件园影响)交通流模型matlab源码

    一.元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 · 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 · 何顿 ...

  3. 美女谁都爱看,跳舞的美女更是,python批量采集(含源码)

    前言 嗨喽,大家好呀~这里是魔王 ❤ 环境使用: Python 3.8 Pycharm 模块使用: requests >>> 数据请求 第三方模块 pip install reque ...

  4. 【元胞自动机】激进策略元胞自动机三车道(不开放辅路,软件园影响)交通流模型matlab源码

    一.元胞自动机简介 1 元胞自动机发展历程 最初的元胞自动机是由冯 · 诺依曼在 1950 年代为模拟生物 细胞的自我复制而提出的. 但是并未受到学术界重视. 1970 年, 剑桥大学的约翰 · 何顿 ...

  5. python视频网站项目_Python开发教育网站项目实例教学(105集视频课程含源码)

    Python开发教育网站项目实例教学(105集视频课程含源码)课程简介: Python开发教育网站项目实例教学(105集视频课程含源码)通过这105集Python实例视频课程的学习,学员可以掌握到使用 ...

  6. 用python画皇冠_【推荐】手把手教你如何用Python画一棵漂亮樱花树含源码

    最近给大家整理了一下,挑了一些我觉得不错的代码分享给大家手把手教你如何用Python画一棵漂亮樱花树含源码. 动态生成樱花 效果图(这个是动态的): import turtle as T import ...

  7. python代码弄成网站_原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想: 希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 最终调用 ...

  8. 原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想:     希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 ...

  9. Python毕业设计基于django的就业系统项目(含源码)

    目录 一.Python毕业设计基于django的就业系统项目(含源码) 二.基于django的就业系统项目文件说明 一.Python毕业设计基于django的就业系统项目(含源码) 源 码 免 费 下 ...

  10. python爬取豆瓣读书top250并保存xls(含源码)

    python爬取豆瓣读书top250并保存xls(含源码) 又是霍霍豆瓣的一天O(∩_∩)O哈哈~. 目标网站:http://book.douban.com/top250/ 全军出击!!! 首先,按下 ...

最新文章

  1. 测试逐飞的MM32F3277 MicroPython开发板的基本功能
  2. windows 下phpstudy 升级mysql版本5.7
  3. 安装确认书模板_Aion S车讲堂 | 关于充电桩安装的N个问题
  4. 某娱乐资源网同款网站源码
  5. [20150705]从AWR抽取有问题的sql语句.txt
  6. 创建指南针View的例子
  7. 一个简单的 SQLite 的示例
  8. EMC CTO:IT进化到“以数据为核心”的阶段
  9. K8s 使用helm 安装 EFK和ELK分布式日志分析系统系列(es版本:6.7.0;)
  10. 12道JS基础简答题
  11. Netbean 打开报 Cannot locate java installation in specified jdkhome: ***错误
  12. 手摸手教你搭个脚手架
  13. PHP 乐心 发送验证码 验证码识别
  14. win10安装super-url出现编码错误解决方法
  15. 认识java安全管理器SecurityManager
  16. skinsdog 狗网官网CSGO饰品皮肤开箱网站可直接取回
  17. 浏览器中实现3D全景浏览
  18. java派单策略_滴滴KDD2018:强化学习派单
  19. 酒店计算机管理系统维护合同,酒店计算机管理系统维护合同.pdf
  20. stm32f103c8t6c语言教程,STM32f103C8T6入门学习记录.doc

热门文章

  1. ecshop网店系统简评
  2. B2B、B2C、C2C、O2O分别是什么意思?
  3. C#--图表控件(Chart)
  4. android绑定两个ip,安卓手机模拟器如何多开切换IP防封号的最新方法介绍
  5. 甘特图控件VARCHART XGantt如何开始使用
  6. ns3网络设置模块 PointToPoint
  7. tracert工作原理
  8. Windows10(MSN)天气数据爬取
  9. 银川JW万豪酒店与银川万怡酒店双品牌酒店启幕
  10. 用Verilog HDL实现一位二进制全减器