为什么我的 Simpy 资源不保持队列?

Why isn't my Simpy resource keeping a queue?

我已经工作了大约一个星期来学习 SimPy 以进行我必须 运行 的离散模拟。我已经尽力了,但我只是没有足够的经验来快速弄清楚。我快死了。请帮忙。

有问题的系统是这样的:

订单到达 -> resource_1(有 2 个)执行 take_order -> 订单分解为项目 -> resource_2(有 10 个)执行 process_item

我的代码 运行s 并执行了模拟,但我在使资源队列正常运行时遇到了很多麻烦。就像,当我 运行 它时,队列不会建立在任何一个资源上,我找不到原因。我尝试 resource.get_queue 并得到空列表。绝对应该有队列,因为订单到达的速度比处理速度快。

我觉得跟请求资源的逻辑有关系,但是想不通。以下是我构建代码的方式:

import simpy
import random 
import numpy as np 



total_items = []


total_a = []
total_b = []
total_c = []

order_Q = [] 
item_Q = []
skipped_visits = []

order_time_dict = {}
order_time_dict2 = {}
total_order_time_dict = {}
var = []

class System:
    def __init__(self,env,num_resource_1,num_resource_2):
        self.env = env
        self.resource_1 = simpy.Resource(env,num_resource_1)
        self.resource_2 = simpy.Resource(env,num_resource_2)

    def take_order(self, order): 
        self.time_to_order = random.triangular(30/60,60/60,120/60)
        arrive = self.env.now
        yield self.env.timeout(self.time_to_order)

    def process_item(self,item): 
        total_process_time = 0
        current = env.now
        order_num = item[1][0]

        for i in range(1,item[1][1]): 
            if 'a' in item[0]: 
                total_process_time +=  random.triangular(.05,7/60,1/6) #bagging time only
                #here edit order time w x
            if 'b' in item[0]: 
                total_process_time += random.triangular(.05,.3333,.75)

            if 'c' in item[0]: 
                total_process_time +=  random.triangular(.05,7/60,1/6)

            #the following is handling time: getting to station, waiting on car to arrive at window after finished, handing to cust
            total_process_time += random.triangular(.05, 10/60, 15/60)

            item_finish_time = current + total_process_time
            if order_num in order_time_dict2.keys(): 
                start = order_time_dict2[order_num][0]
                if order_time_dict2[order_num][1] < item_finish_time:
                    order_time_dict2[order_num] = (start, item_finish_time) 
            else: 
                order_time_dict2[order_num] = (current, item_finish_time)

        yield self.env.timeout(total_process_time)


class Order: 
    def __init__(self, order_dict,order_num): 
        self.order_dict = order_dict
        self.order_num = order_num
        self.order_stripped =  {}
        for x,y in list(self.order_dict.items()): 
            if x != 'total':
                if y != 0: 
                    self.order_stripped[x] = (order_num,y) #this gives dictionary format {item: (order number, number items) } but only including items in order
        
        self.order_list = list(self.order_stripped.items()) 

def generate_order(num_orders): 
    print('running generate_order')

    a_demand = .1914 ** 3
    a_stdev = 43.684104

    b_demand = .1153
    b_stdev =  28.507782

    c_demand = .0664
    c_stdev = 15.5562624349

    num_a = abs(round(np.random.normal(a_demand)))
    num_b = abs(round(np.random.normal(b_demand)))
    num_c = abs(round(np.random.normal(c_demand)))
    total = num_orders 
    
    total_a.append(num_a)
    total_b.append(num_b)
    total_c.append(num_c)
    total_num_items = num_a + num_b + num_c
    total_items.append(total_num_items)
    

    order_dict = {'num_a':num_a, 'num_b':num_b,'num_c':num_c, 'total': total}
     
    return order_dict

def order_process(order_instance,system): 
    enter_system_at = system.env.now
    print("order " + str(order_instance.order_num) + " arrives at " + str(enter_system_at))
    if len(system.resource_1.get_queue) > 1: 
        print("WORKING HERE ******************")
    if len(system.resource_1.get_queue) <= 25: 
        with system.resource_1.request() as req: 
            order_Q.append(order_instance)
            yield req
            yield env.process(system.take_order(order_instance))
            order_Q.pop()
        enter_workstation_at = system.env.now
        print("order num " + str(order_instance.order_num) + " enters workstation at " + str(enter_workstation_at))


        for item in order_instance.order_list: 
            item_Q.append(item)
            with system.resource_2.request() as req: 
                yield req
                yield env.process(system.process_item(item))
            if len(system.resource_2.get_queue) >1: 
                var.append(1)

            item_Q.pop()
        leave_workstation_at = system.env.now
        print("Order num " + str(order_instance.order_num) + " leaves at " + str(leave_workstation_at))

        order_time_dict[order_instance.order_num] = leave_workstation_at-enter_workstation_at
        total_order_time_dict[order_instance.order_num]=leave_workstation_at-enter_system_at
    else: 
        skipped_visits.append(1)


def setup(env):
    system = System(env,2,15)
    order_num = 0
    while True: 
        next_order = random.expovariate(3.5) #where 20 is order arrival mean (lambda)
        yield env.timeout(next_order)
        order_num+=1
        env.process(order_process(Order(generate_order(order_num),order_num),system))

env = simpy.Environment()
env.process(setup(env))
env.run(until=15*60)
print("1: \n", order_time_dict)

我想你看错队列了。

用于获取排队的资源请求的 api 只是属性队列,因此请尝试使用 len(系统。resource_1.queue)

get_queue 和 put_queue 来自基础 class 并用于派生新资源 classes.

但是等等,它们不是任何有理智的人会假设的,我也觉得这很混乱,但文档说 请求资源被建模为“将进程的令牌放入资源”,这意味着当您调用 request() 时,进程被放入 put_queue,而不是 get_queue。对于资源,释放总是立即成功,所以它的队列(即 get_queue)总是空的

我认为 queue 只是 put_queue 的别名,但 queue 不那么令人困惑