如何使用simmer的branch功能实现机场旅客安检流程模拟
机场旅客安检流程仿真实现(基于R simmer包)
需求说明
- 普通旅客:到达服从泊松分布,每小时平均2965人;需通过3台验证机(VM),验证时间服从均匀分布
runif(1,1,3)(单位:秒);之后使用22台X光机(MC),准备时间服从三角分布rtri(1, min=5, max=15, mode=10),扫描时间服从三角分布rtri(1, min=5, max=30, mode=10)(单位均为秒)。 - VIP旅客:占普通旅客的20%,到达服从λ=0.125秒的泊松分布;使用4台专属X光机,X光流程时间与普通旅客一致。
问题解决:用branch实现旅客分流
以下是修正并完善后的仿真代码,核心通过simmer的branch函数实现普通/VIP旅客的分流逻辑,同时修正了原代码中的资源名错误与到达时间函数误用:
library(triangulr) library(simmer) rm(list = ls()) # 初始化仿真环境 env <- simmer("安检流程仿真") # 定义X光机通用流程(普通与VIP旅客共用此逻辑) xray_process <- trajectory("X光机流程") %>% timeout(function() rtri(1, min = 5, max = 15, mode = 10)) %>% # 准备时间 timeout(function() rtri(1, min = 5, max = 30, mode = 10)) %>% # 扫描时间 # 根据旅客属性释放对应X光机资源 release(function() ifelse(get_attribute(.env$self, "is_vip", default = FALSE), "VIP_MC", "MC")) # 定义完整旅客流程:验证机环节 + 分支分流 passenger_trajectory <- trajectory("旅客主流程") %>% # 所有旅客必须经过的验证机环节 seize("VM") %>% timeout(function() runif(1, 1, 3)) %>% release("VM") %>% # 分支判断:80%概率走普通通道,20%走VIP通道 branch( function() sample(c(1, 2), 1, prob = c(0.8, 0.2)), continue = FALSE, # 进入分支后不再返回主流程 # 分支1:普通旅客X光机流程 trajectory("普通旅客X光通道") %>% seize("MC") %>% join(xray_process), # 分支2:VIP旅客X光机流程 trajectory("VIP旅客X光通道") %>% set_attribute("is_vip", TRUE) %>% # 标记为VIP旅客 seize("VIP_MC") %>% join(xray_process) ) # 向仿真环境添加资源与生成器 env %>% add_resource("VM", 3) %>% # 验证机:3台 add_resource("MC", 22) %>% # 普通X光机:22台 add_resource("VIP_MC", 4) %>% # VIP专属X光机:4台 # 泊松到达的间隔时间服从指数分布,rate为每秒钟到达人数 add_generator("旅客", passenger_trajectory, function() rexp(1, rate = 2965/3600)) # 运行仿真3小时(10800秒) env %>% run(until = 10800)
关键细节说明
branch函数用法:通过sample函数按80/20的概率分配旅客到不同分支,continue = FALSE确保进入分支后不再执行主流程后续逻辑。- 通用流程复用:将X光机的准备与扫描逻辑提取为
xray_process轨迹,通过旅客属性is_vip判断释放对应资源,减少代码冗余。 - 到达时间修正:
simmer的add_generator需要的是间隔时间函数,泊松过程的时间间隔服从指数分布,因此用rexp替代原代码的rpois(rpois生成的是计数,不是间隔)。
内容的提问来源于stack exchange,提问作者Henrique Luís
相关产品推荐
相关产品推荐

