simmeR中自定义优先级与弃号行为共存的实现问题
Simmer中同时实现自定义优先级与弃号行为的问题解决
问题现象
在simmer中同时实现超时弃号(用renege_in)和自定义优先级重算(用renege_if触发)时,遇到了renege_abort的异常行为:
- 原代码中
renege_in放在renege_if之后:优先级重算完全不生效 - 调换顺序把
renege_in放前面:优先级恢复正常,但超时弃号逻辑失效
问题原因
simmer里的renege_in和renege_if默认会覆盖之前的renege规则,也就是说,第二个renege语句会把第一个的规则替换掉,导致只有一个逻辑能工作,另一个被静默覆盖了。
修复代码
lambda <- 2 mu <- 3 trajectory <- simmer::trajectory() %>% # 先设置到达时间作为优先级计算的基础 simmer::set_attribute('start_time', function() simmer::now(sim)) %>% # 超时弃号规则:保留后续添加的其他renege规则 simmer::renege_in( t = function() rpois(1,5), out = simmer::trajectory() %>% simmer::set_attribute('renege_time', function() simmer::now(sim)) %>% simmer::leave(1), keep = TRUE # 关键:保留后续的renege_if规则 ) %>% # 优先级重算规则:保留前面的renege_in规则 simmer::renege_if( signal = "recompute_priority", out = simmer::trajectory() %>% # 基于到达时间设置优先级(值越小优先级越高) simmer::set_prioritization(function() { prio <- simmer::get_attribute(sim,'start_time') c(prio, NA, NA) }) %>% simmer::rollback(1), # 回退到renege_if之前,重新等待信号 keep = TRUE # 关键:保留前面的renege_in规则 ) %>% # 抢占资源并终止所有renege规则 simmer::seize('v', amount = 1) %>% simmer::renege_abort() %>% # 服务过程 simmer::timeout(function() {rpois(1, mu)}) %>% # 发送信号触发队列中任务重算优先级 simmer::send("recompute_priority") %>% simmer::timeout(0) %>% # 记录当前优先级用于验证 simmer::set_attribute('priority', function(){simmer::get_prioritization(sim)[[1]]}) %>% simmer::release('v', amount = 1) sim <- simmer::simmer('sim') sims <- sim %>% simmer::add_resource("v", capacity = 1, queue_size=Inf, preemptive=F) %>% # 生成到达事件 simmer::add_generator("arrival", trajectory, function() {rpois(1, lambda)}, mon = 2) %>% simmer::run(until = 500)
关键修改说明
- 添加
keep=TRUE参数:在renege_in和renege_if中都设置keep=TRUE,让两个renege规则同时生效,不会互相覆盖。 - 补充
start_time属性设置:原代码中没有初始化start_time,导致优先级计算取不到值,现在在轨迹开头就设置该属性,作为优先级的计算依据。 - 修正
rollback步数:原代码中rollback(2)会回退到renege_in之前,导致重复设置弃号规则,改成rollback(1)只回退到renege_if之前,确保优先级重算后继续等待资源。 - 调整规则顺序:先设置
renege_in再设置renege_if,同时通过keep=TRUE保留两者,让超时弃号和优先级重算逻辑并行工作。
内容的提问来源于stack exchange,提问作者HLP
相关产品推荐
相关产品推荐

