SimPy订单履行模拟系统无报错但卡顿无结果求助
问题描述
我想用SimPy模拟一套订单履行系统,系统规则如下:
- 存在n个订单,每个订单包含mi个商品(i=1,2,…,n),所有订单的商品在模拟开始时已全部就绪,无需等待。
- 若干loading resources(分拣人员),逐个扫描并将商品送往包装环节;处理完成后,商品会被加入对应订单的cart(订单容器),cart数量与订单数一致且无容量限制。
- 当某个订单的cart中商品数量达到阈值(比如订单总商品数的10%)时,packaging resources(包装人员)开始逐个处理该订单的商品,可同时处理多个订单但每次仅处理一件商品。
我编写了代码,但运行时出现问题:每次随机选中一件商品(比如订单2的商品2),重复输出10条相同的分拣日志后系统卡顿,无后续结果输出。
我的代码
商品列表生成
from itertools import repeat import simpy import random import itertools num_order = 2 size_order = [10, 8] items = [] for i in range(num_order): ob = list(zip(repeat(i+1), (range(1,size_order[i]+1)))) items.append(ob) items = list(itertools.chain(*items))
逻辑:生成包含(订单号,商品号)元组的商品列表,示例中2个订单分别含10、8件商品。
商品生成函数
def gen_items(env,mean_load,mean_pack,items,load_op,pack_op,cart,size_order): # Choose a random item from the list of all items, #give it an id of it's tuple name, and remove that item from the list if items: item_id = random.choice(items) items.remove(item_id) while True: w = gen_activity(env,mean_load,mean_pack,item_id,load_op,pack_op,cart,size_order) env.process(w) yield env.timeout(0) #items are ready and don't take time to be available for the operator
逻辑:随机选取商品并启动处理流程,商品就绪无等待时间。
活动处理函数
def gen_activity(env,mean_load,mean_pack,item_id,load_op,pack_op,cart,size_order): time_enter_load_op_queue = env.now #time item is ready for loading with load_op.request() as req: yield req # we request an operator time_queue_load_op = env.now time_in_load_op_queue = time_queue_load_op - time_enter_load_op_queue print("item" +str(item_id[1])+ " of order" + str(item_id[0])+" entered load at" + str(time_enter_load_op_queue)+ " and spent"+ str(time_in_load_op_queue)) # print the time the item spent in the queue waiting for loading operator load_time = random.expovariate(1/mean_load) yield env.timeout(load_time) # once the item is processed, it then is loaded to the cart of that order in 45 time untis yield cart[item_id[0]-1].put(1) yield env.timeout(45) time_enter_pack_op_queue = env.now #now the item at the packaging location with pack_op.request() as req: if cart[item_id[0]-1].level >= 0.1*(size_order[item_id[0]-1]): yield req # request a packaging operator to start packaging only if there is 10% of the order in the cart time_queue_pack_op = env.now time_in_pack_op_queue = time_queue_pack_op - time_enter_pack_op_queue print("item" +str(item_id[1])+ " of order" + str(item_id[0])+" entered pack at" + str(time_enter_pack_op_queue)+ " and spent"+ str(time_in_pack_op_queue)) pack_time = random.expovariate(1/mean_pack) yield env.timeout(pack_time) # time to pack
逻辑:实现分拣、入cart、包装流程,包装环节需满足cart商品量达阈值才请求包装资源。
初始化与运行
env = simpy.Environment() load_op = simpy.Resource(env,capacity=10) pack_op = simpy.Resource(env,capacity=2) cart = [] for i in range(len(size_order)): c = simpy.Container(env,capacity=size_order[i],init=0) cart.append(c) mean_load,mean_pack = 3,2 env.process(gen_items(env,mean_load,std_load,mean_pack,std_pack,items,load_op,pack_op,chute,size_order)) env.run(until=1000)
问题排查与修正
核心问题分析
gen_items函数逻辑错误:仅在函数开头随机选一次商品并移除,后续while True循环一直复用同一个item_id,导致同一商品被反复处理;同时yield env.timeout(0)会让循环无限快速执行,瞬间创建大量重复进程引发卡顿。- 初始化参数错误:调用
gen_items时传入了未定义的std_load、std_pack、chute参数,与函数定义不匹配。 - 包装环节逻辑缺陷:未达阈值时直接跳过资源请求并执行包装计时,不符合“达到阈值才开始处理”的规则;且未等待cart满足条件就进入包装流程。
修正后的完整代码
from itertools import repeat import simpy import random import itertools num_order = 2 size_order = [10, 8] items = [] for i in range(num_order): ob = list(zip(repeat(i+1), range(1, size_order[i]+1))) items.append(ob) items = list(itertools.chain(*items)) def gen_items(env, mean_load, mean_pack, items, load_op, pack_op, cart, size_order): # 遍历所有商品,逐个启动处理流程,直到商品耗尽 while items: item_id = random.choice(items) items.remove(item_id) env.process(gen_activity(env, mean_load, mean_pack, item_id, load_op, pack_op, cart, size_order)) yield env.timeout(0) # 商品就绪无等待,快速启动下一个 def gen_activity(env, mean_load, mean_pack, item_id, load_op, pack_op, cart, size_order): order_idx = item_id[0] - 1 order_size = size_order[order_idx] threshold = 0.1 * order_size # 分拣环节 time_enter_load_op_queue = env.now with load_op.request() as req: yield req time_in_load_op_queue = env.now - time_enter_load_op_queue print(f"item {item_id[1]} of order {item_id[0]} entered load at {time_enter_load_op_queue:.2f}, spent {time_in_load_op_queue:.2f} in queue") load_time = random.expovariate(1/mean_load) yield env.timeout(load_time) # 商品加入cart,保留运输到包装区的45单位时间 yield cart[order_idx].put(1) yield env.timeout(45) # 包装环节:等待cart达到阈值后再请求资源 time_enter_pack_op_queue = env.now # 等待cart商品量满足阈值条件 yield env.event() until (cart[order_idx].level >= threshold) with pack_op.request() as req: yield req time_in_pack_op_queue = env.now - time_enter_pack_op_queue print(f"item {item_id[1]} of order {item_id[0]} entered pack at {time_enter_pack_op_queue:.2f}, spent {time_in_pack_op_queue:.2f} in queue") pack_time = random.expovariate(1/mean_pack) yield env.timeout(pack_time) # 初始化模拟 env = simpy.Environment() load_op = simpy.Resource(env, capacity=10) pack_op = simpy.Resource(env, capacity=2) cart = [] for i in range(len(size_order)): # 设置cart为无容量限制 c = simpy.Container(env, capacity=float('inf'), init=0) cart.append(c) mean_load, mean_pack = 3, 2 # 修正参数调用 env.process(gen_items(env, mean_load, mean_pack, items, load_op, pack_op, cart, size_order)) env.run(until=1000)
关键修正点说明
gen_items函数:将商品选择逻辑移入while items循环,确保每次处理新商品,商品耗尽后自动停止循环。- 参数修正:删除未定义的参数,替换为正确的
cart等参数;将cart的capacity设为float('inf')以实现无容量限制。 - 包装环节优化:添加等待cart达到阈值的逻辑,只有满足条件后才请求包装资源,符合系统规则。
内容的提问来源于stack exchange,提问作者Erin Walter
相关产品推荐
相关产品推荐

