You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Salabim的离散事件仿真(DES)动画交互:避免运行时修改的回溯影响

我明白你遇到的问题了——Salabim默认的Resource组件在修改可用量时会触发回溯式调度,也就是会重新检查所有历史等待的请求,这就导致你在10秒添加库存时,之前的Customer请求会被回溯处理,仿佛库存早就存在一样,这确实不符合实时调整的预期。

要解决这个问题,核心是让资源的修改只对当前仿真时间及之后的请求生效,不触动历史状态。最直接的方案是改用Salabim的Store组件替代Resource,因为Store是基于实体的库存管理,所有操作都是事件驱动的,不会回溯修改历史。

原因分析

原来的Resource是基于容量配额的,当你调用release(1)时,Salabim会自动回溯检查所有过去等待该资源的请求,看是否能在更早的时间点满足,这是它默认的资源调度逻辑,适合需要精确回溯调度的场景,但不适合你的实时交互调整需求。

而Store则是将库存作为实际的物品实体,添加物品的操作只会在当前仿真时间生效,之前的等待请求在当时没有物品,所以不会被回溯激活,只有当前及之后的请求会响应新添加的库存。

修改后的代码

import salabim as sim

window_length = 20
env = sim.Environment(trace=True, time_unit='seconds')

# 用Store替代Resource,模拟实体库存
stock = sim.Store("stock", capacity=5)
output = sim.Store("output", capacity=5)

class Customer(sim.Component):
    def process(self):
        while True:
            # 用get()获取库存物品,事件驱动,无回溯
            self.get(stock)
            self.hold(sim.Uniform(2, 5))
            # 将物品放入output Store
            self.put(output)

# 监控库存和输出的数量变化
sim.AnimateMonitor(
    stock.level,  # Store用level属性获取当前物品数量
    x=0, y=-50, width=140, height=100,
    horizontal_scale=1/window_length*140,
    vertical_scale=1/stock.capacity()*90,
    screen_coordinates=False
)
sim.AnimateMonitor(
    output.level,
    x=150, y=-50, width=140, height=100,
    horizontal_scale=1/window_length*140,
    vertical_scale=1/output.capacity()*90,
    screen_coordinates=False
)

Customer()

# 按钮动作修改为向Store放入/取出物品
sim.AnimateButton(x=-50, y=15, xy_anchor='se', width=100, text='Drop Stock', 
                  action=lambda: [stock.get() for _ in range(stock.level)] if stock.level > 0 else None)
sim.AnimateButton(x=-50, y=45, xy_anchor='se', width=100, text='Add Stock', 
                  action=lambda: stock.put(1) if stock.level < stock.capacity() else None)

env.animate(True)
env.animation_parameters(show_fps=True, show_time=True)
env.run(till=500)

关键修改点说明

  • 替换组件类型:用sim.Store替代sim.Resource,Store的level属性对应库存数量,put()/get()方法用于添加/取出物品,所有操作都是当前时间点的事件,无回溯。
  • 调整请求逻辑:Customer的process中用self.get(stock)替代self.request(stock),这是Store的标准获取方式,只会在有可用物品时触发,不会回溯历史请求。
  • 按钮动作适配:添加库存时调用stock.put(1),清空库存时循环调用stock.get()直到为空,确保操作只在当前时间生效。

测试效果

运行仿真后,前10秒库存为空,Customer会处于等待状态。当你在10秒时点击"Add Stock",库存会在10秒时增加1,Customer会立即获取该物品,等待2-5秒后放入output,不会出现回溯到10秒之前取货的情况,完全符合实时调整的预期。

如果你坚持要用Resource组件,也可以通过自定义请求逻辑,记录每个请求的发起时间,只允许当前时间之后的资源变化影响该请求,但这种方法复杂度较高,不如改用Store简洁直观。

内容的提问来源于stack exchange,提问作者AReubens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:09:08