4. 离散事件仿真原理与排队系统仿真框架
排队系统的本质是“状态在随机时刻发生跳变”的过程:顾客到达、开始服务、服务结束、顾客离开,这些动作并非连续发生,而是在离散的时间点上改变系统状态。离散事件仿真(Discrete Event Simulation, DES)正是围绕这一特征构建的:它不按固定步长推进时间,而是让仿真时钟从一个事件时刻直接跳到下一个事件时刻,从而跳过大量“无事发生”的空闲区间。理解事件调度、仿真时钟、状态变量与统计计数器这四个核心机制,是设计通用排队仿真引擎的前提。
四个核心机制及其相互关系
仿真时钟是引擎的“当前时间”变量,记为 t_now。它只在处理事件时被更新,更新方式是直接赋值为下一个待处理事件的发生时刻,而不是 t_now += Δt。这一“时间跳跃”特性决定了 DES 的计算效率:仿真 8 小时(28800 秒)的银行网点,若平均每 30 秒发生一个事件,只需处理约千级事件,而非按秒推进的 28800 次循环。
事件调度依赖事件表(Future Event List, FEL)。事件表按发生时刻升序排列,引擎每次取出表头事件执行,执行过程中可能产生新事件并插入表中。事件通常用三元组表示:(发生时刻, 事件类型, 关联实体)。例如 (t=125.4, "到达", 顾客#7)。为保证同一时刻多个事件的处理顺序确定,可引入优先级字段,如“离开”优先于“到达”,避免资源释放与占用在同一时刻产生歧义。
状态变量描述系统在某一时刻的完整快照,排队系统中最典型的是:服务员状态(空闲/忙碌)、队列长度、队列中顾客的到达时刻列表、当前正在服务的顾客剩余服务时间等。状态变量必须足以支撑“下一事件如何改变系统”的判断,例如服务员空闲且队列非空时,应立即触发“开始服务”事件。
统计计数器在事件处理过程中累积指标:累计排队人数的时间积分、累计等待时间、服务人数、最大队列长度等。关键在于“时间加权”统计——队列长度在两次事件之间保持不变,因此面积累加应写成 area += queue_len * (t_now - t_last),再在仿真结束时除以总时长得到平均队列长度。若只在事件点采样求算术平均,会系统性偏离真实时间平均值。
通用引擎的模块划分
把上述机制组织成可复用的引擎,通常划分为五个模块:事件表管理(插入、取最小、判空)、时钟推进(取表头并赋值)、事件分派器(按事件类型调用对应处理函数)、状态容器(保存服务员、队列等实体)、统计收集器(在事件前后记录时间戳并累积)。事件处理函数是唯一允许修改状态的地方,这种“单点修改”约束能显著降低调试难度。
一个最小可用的主循环伪代码如下,其中 t_last 用于时间加权统计:
初始化:t_now = 0, t_last = 0
插入首个“到达”事件到 FEL
while FEL 非空 and t_now < T_end:
evt = FEL.pop_min()
t_now = evt.time
统计器.累积(t_now - t_last) # 用旧状态填充时间区间
t_last = t_now
dispatch(evt) # 到达 / 开始服务 / 离开
统计器.收尾(T_end - t_last)
注意 累积 必须发生在状态更新之前,否则会把“事件之后”的状态错误地算进“事件之前”的时间区间。这是初学者最常见的统计偏差来源。
教学示例:单服务员队列的事件推演
设某窗口到达间隔服从均值 10 秒的指数分布,服务时间服从均值 8 秒的指数分布,仿真时长 100 秒。假设随机数生成得到前几个到达时刻为 6.2、17.5、25.1、40.3,服务时间为 5.4、9.1、7.6。推演过程如下:
| 时刻 | 事件 | 状态变化 | 统计动作 |
|---|---|---|---|
| 6.2 | 到达#1 | 服务员空闲→立即开始服务 | 队列面积 += 0×6.2 |
| 11.6 | 离开#1 | 服务员转空闲,队列为空 | 服务人数=1,空闲面积 += 5.4 |
| 17.5 | 到达#2 | 立即开始服务 | 空闲面积 += 5.9 |
| 25.1 | 到达#3 | 服务员忙碌,入队,队长=1 | 队列面积 += 0×7.6 |
| 26.6 | 离开#2 | 出队#3开始服务,队长=0 | 队列面积 += 1×1.5,等待=1.5 |
由表可见,队列面积只在“队长非零”的区间增长,等待时间在“出队开始服务”时结算。仿真结束后,平均等待时间 = 等待时间总和 ÷ 服务人数,平均队长 = 队列面积 ÷ 100。这些数值属于示例推演,用于说明机制,不代表任何真实系统的性能结论。
最后需要强调可复现性:所有随机抽样都应来自可设定种子的随机数流,且到达流与服务流使用独立子流,避免修改服务时间分布时扰动到达序列。引擎输出应至少包含平均等待时间、平均队长、服务员利用率与服务人数,并记录仿真时长与种子,便于结果复核与对比实验。