最近跟深城交的一位大佬(也是我刚入职我司时的导师)交流,天马行空的探讨了一些城市交通仿真系统的设计问题,使我对离散事件仿真系统的了解更深刻,且偶有奇思妙想,特此记录。
1. 城市交通仿真一般分为微观、中观、宏观几类。微观仿真会具体到每一辆车,包括车辆的启停、加速减速等各种事件的模拟;中观和宏观会把多辆车,或者整个街道的车流量作为仿真的基本对象,但此类仿真不在我们讨论范围内,故不做详述。
深圳市的交通仿真系统,其设计目的是模拟不同初始条件下,城市路况的拥堵或改善情况。比如在某条路设置施工障碍,或者改变某些交通信号灯的变化时间,或者拓宽某些道路时,车辆行驶会不会拥堵等。
有两种实现方法,一种是先设置好初始输入条件(如信号灯切换时间,车辆信息等)和仿真步长(比如1秒钟),再通过一个具有全局视角的复杂算法,计算出在此初始条件下,每辆车每一秒所在的位置。以此来验证初始条件的设置是否合理,是否会导致道路拥堵。而该算法的运行,是一个连续事件,也就是算法启动之后一定要把所有车辆的下一秒位置计算完毕才会终止,除了中断程序重新输入条件、重新启动算法的方式外,没有其他方法可以改变算法的运行状态。
另一种方式则是利用离散事件仿真的原理,让每一辆车的每一个动作(比如加速减速等)都变成一个独立的事件,每一辆车根据其他事件变化(比如红绿灯的突然变化)自主判断下一秒要发生什么事件(比如加速、减速、刹车灯),车辆实体把这些事件全部上报事件队列管理。如此,便可以去掉前一种方式中的全局视角的算法,把一个连续的计算过程,打散成无数个离散的事件,而仿真系统只需要不断从事件队列里读取并处理事件。此方式的最大特点是,在仿真执行过程中,可以随时往队列里人为加入各种突发事件,进而实时改变仿真结果,即实现了人和仿真系统的实时交互。
2. 另一个收获是对离散事件仿真系统的分布式计算有了初步的想法。离散事件的仿真更向一条流水线,事件之间相互影响,因此会存在复杂的前后关系,此时,并行计算便很难应用。但是在城市交通的仿真领域,是否可以将整个城市拆分成不同方向的道路,每条道路拆分成不同的车道,每个车道当成一个事件队列处理。设计单独的对象管理不同的队列,每次步进,暂停所有队列的事件处理,处理不同队列中相互影响的事件,做好信息分享,再触发所有事件队列继续,如此循环往复,实现分布式的离散事件处理。
3. 仿真方法介绍—事件调度法。
事件调度法的基本原理是将事件例程(即事件队列中的一条记录)作为仿真的基本模型单元,按照事件发生的先后顺序不断执行相应的事件例程。每一事先可预知其发生时间的确定事件都带有一个事件例程,用以处理事件发生后对实体状态所产生的影响,并安排后续事件,事件调度法中所说的事件是指确定事件。
采用事件调度法建立的仿真模型称为面向事件的仿真模型。该仿真方法由一个总控程序来控制整个仿真系统的运行。其总控程序完成如下工作:
(1)时间扫描:确定下—事件发生时间并将仿真时钟推进到该时刻;
(2)事件辨识:正确地辨识当前要发生的事件;
(3)事件执行:正确地执行当前发生的事件。
面向事件仿真模型的主控程序使用事件表(EventList)来完成上述任务。在仿真运行中,事件的记录不断被列入或移出事件表。
使用事件表后,面向事件仿真模型总控程序的算法结构如下:
(1)时间扫描
- 扫描事件表,确定下一事件发生时间;
- 推进仿真时钟至下一事件发生时间;
- 从事件表中产生当前事件表CEL,CEL中包含了所有当前发生事件的事件记录;
(2)事件执行
- 依次安排CEL中的各个事件的发生,调用相应的事件例程。某一事件一旦发生,将其从事件表中移出。