R Simmer多轨迹场景下自定义优先级的问题求助
Simmer多轨迹自定义优先级问题的解决方案
问题1:仿真运行时长显著增加的优化方案
你推测的“每次释放资源都重新评估所有到达者优先级”是核心原因,尤其是到达者数量或仿真时长提升时,全局遍历的开销会被放大。可以通过以下方式优化:
替代思路:到达者主动触发+资源专属信号
不要用全局的recompute_priority信号,改为让到达者在满足等待时长条件时主动更新自身优先级,并触发对应资源的专属信号,而非每次释放资源都全局扫描。同时,取消已被服务的到达者的优先级更新事件,避免无效计算。
示例代码:
library(simmer) traj_0 <- trajectory() %>% # 记录进入等待的时间 set_attribute("wait_start", function() now(env)) %>% # 生成延迟18秒的优先级提升事件,记录事件ID用于后续取消 set_attribute("priority_event", function() { env %>% send_at(now(env) + 18, function() { # 仅当仍在resource_a队列中时执行 if (!is.na(get_seized(env, "resource_a"))) { set_priority(env, get_priority(env) + 10) send_signal(env, "recompute_priority_a") } }) }) %>% # 抢占资源 seize("resource_a") %>% # 一旦被服务,立刻取消之前的优先级提升事件 cancel(function() get_attribute(env, "priority_event")) %>% timeout(5) %>% release("resource_a") %>% # 50%概率进入分支 branch(function() sample(1:2, 1), continue = FALSE, trajectory("traj_1") %>% timeout(10), trajectory("traj_2") %>% timeout(15)) # 环境初始化:为resource_a绑定专属信号 env <- simmer() %>% add_resource("resource_a", capacity = 1, queue_size = Inf, signal = "recompute_priority_a") %>% add_generator("arrival", traj_0, function() rexp(1, 0.1)) %>% run(until = 1000)
这种方式只有当到达者确实等待满18秒且仍在队列中时,才会触发优先级更新和资源队列的优先级重算,避免了全局遍历的无效开销,大幅降低仿真时长。
问题2:信号作用范围错误的解决方法
核心是为不同资源/轨迹逻辑绑定专属信号,而非使用全局信号,同时确保到达者离开对应队列后,取消相关的事件触发,避免信号影响无关到达者。
实现分轨迹的自定义优先级
以traj_1和traj_2分别处理不同资源为例,为每个资源设置专属信号,各自实现独立的优先级逻辑:
示例代码:
traj_0 <- trajectory() %>% set_attribute("wait_start", function() now(env)) %>% set_attribute("priority_event_a", function() { env %>% send_at(now(env) + 18, function() { if (!is.na(get_seized(env, "resource_a"))) { set_priority(env, get_priority(env) + 10) send_signal(env, "recompute_priority_a") } }) }) %>% seize("resource_a") %>% cancel(function() get_attribute(env, "priority_event_a")) %>% timeout(5) %>% release("resource_a") %>% branch(function() sample(1:2, 1), continue = FALSE, # traj_1的自定义优先级:等待满10秒提升优先级 trajectory("traj_1") %>% set_attribute("wait_start_b", function() now(env)) %>% set_attribute("priority_event_b", function() { env %>% send_at(now(env) + 10, function() { if (!is.na(get_seized(env, "resource_b"))) { set_priority(env, get_priority(env) + 8) send_signal(env, "recompute_priority_b") } }) }) %>% seize("resource_b") %>% cancel(function() get_attribute(env, "priority_event_b")) %>% timeout(10) %>% release("resource_b"), # traj_2的自定义优先级:等待满12秒提升优先级 trajectory("traj_2") %>% set_attribute("wait_start_c", function() now(env)) %>% set_attribute("priority_event_c", function() { env %>% send_at(now(env) + 12, function() { if (!is.na(get_seized(env, "resource_c"))) { set_priority(env, get_priority(env) + 12) send_signal(env, "recompute_priority_c") } }) }) %>% seize("resource_c") %>% cancel(function() get_attribute(env, "priority_event_c")) %>% timeout(15) %>% release("resource_c")) # 环境初始化:每个资源绑定专属信号 env <- simmer() %>% add_resource("resource_a", capacity = 1, queue_size = Inf, signal = "recompute_priority_a") %>% add_resource("resource_b", capacity = 1, queue_size = Inf, signal = "recompute_priority_b") %>% add_resource("resource_c", capacity = 1, queue_size = Inf, signal = "recompute_priority_c") %>% add_generator("arrival", traj_0, function() rexp(1, 0.1)) %>% run(until = 1000)
关键逻辑说明
- 每个资源对应唯一的信号(如
recompute_priority_a对应resource_a),触发时仅重算该资源的队列优先级,不会影响其他轨迹的到达者; - 到达者进入分支后,处理的是其他资源的队列,之前traj_0的信号事件已被取消,不会干扰后续流程;
- 各轨迹可独立定义自己的优先级规则,互不影响。
内容的提问来源于stack exchange,提问作者HLP
相关产品推荐
相关产品推荐

