【问题标题】:How to activate multiple Processes in SimPy如何在 SimPy 中激活多个进程
【发布时间】:2021-08-23 12:46:47
【问题描述】:

我想创建两种流程,它们基本上是两种患者类型,一种是 Category1,另一种是 Catergory2。这些中的每一个都是在特定的时间间隔内生成的,即到达急诊室的速度,并且它们中的每一个都在争夺资源,这就是医生。我不知道如何创建两个不同的进程。终端输出是这样的

 4.4910 Patient_C304: Here I am. [0, 0, 0, 0, 0]
 4.4910 Patient_C304: Waited  0.000
 5.0008 Patient_C304: Finished
Traceback (most recent call last):
  File "/home/o/Documents/hos/bank.py", line 153, in <module>
    simulate(until=maxTime)
  File "/home/o/Documents/hos/hos/lib/python3.8/site-packages/SimPy/Globals.py", line 59, in simulate
    return sim.simulate(until = until)
  File "/home/o/Documents/hos/hos/lib/python3.8/site-packages/SimPy/Simulation.py", line 551, in simulate
    step()
  File "/home/o/Documents/hos/hos/lib/python3.8/site-packages/SimPy/Simulation.py", line 495, in step
    resultTuple = next(proc._nextpoint)
TypeError: 'NoneType' object is not an iterator

这是我的代码:

""" Hospital10: Several doctors with individual queues"""
from SimPy.Simulation import *
from random import expovariate, triangular, seed

# Model components ------------------------

interval_c = [0.02, 0.07, 0.12]
class Source(Process):
    """ Source generates Patients randomly"""

    def generate_C1(self, number, interval, doctors):
        for i in range(number):

            p_C1 = PatientC1(name="Patient_C1%02d" % (i,))
            activate(p_C1, p_C1.visit(doctors))
            t_C1 = expovariate(interval[0])
            yield hold, self, t_C1, 

    def generate_C2(self, number, interval, doctors):
        for i in range(number):
             p_C2 = PatientC2(name="Patient_C2%02d" % (i,))
             activate(p_C2, p_C2.visit(doctors))
             t_C2 = expovariate(interval[1])
             yield hold, self, t_C2

    def generate_C3( self, number, interval, doctors):
        for i in range(number):
             p_C3= PatientC3(name="Patient_C3%02d" % (i,))
             activate(p_C3, p_C3.visit(doctors))
             t_C3 = expovariate(interval[2])
             yield hold, self, t_C3
             
            





def NoInSystem(R):
    """ Total number of Patients in the resource R"""
    return (len(R.waitQ)+len(R.activeQ))


class PatientC1(Process):
    """ Patient arrives, chooses the shortest queue
        is served and leaves
    """

        

    def visit(self, doctors):
        arrive = now()
        Qlength = [NoInSystem(doctors[i]) for i in range(Nd)]
        print("%7.4f %s: Here I am. %s" % (now(), self.name, Qlength))
        for i in range(Nd):
            if Qlength[i] == 0 or Qlength[i] == min(Qlength):
                choice = i  # the chosen queue number
                break

        yield request, self, doctors[choice]
        wait = now()-arrive
        print("%7.4f %s: Waited %6.3f" % (now(), self.name, wait))
        tib = triangular(1.0/timeInHospital)
        yield hold, self, tib
        yield release, self, doctors[choice]

        print("%7.4f %s: Finished" % (now(), self.name))

# Experiment data -------------------------
class PatientC2(Process):
    """ Patient arrives, chooses the shortest queue
        is served and leaves
    """


    def visit(self, doctors):
        arrive = now()
        Qlength = [NoInSystem(doctors[i]) for i in range(Nd)]
        print("%7.4f %s: Here I am. %s" % (now(), self.name, Qlength))
        for i in range(Nd):
            if Qlength[i] == 0 or Qlength[i] == min(Qlength):
                choice = i  # the chosen queue number
                break

        yield request, self, doctors[choice]
        wait = now()-arrive
        print("%7.4f %s: Waited %6.3f" % (now(), self.name, wait))
        tib = triangular(1.0/timeInHospital)
        yield hold, self, tib
        yield release, self, doctors[choice]

        print("%7.4f %s: Finished" % (now(), self.name))



class PatientC3(Process):
    """ Patient arrives, chooses the shortest queue
        is served and leaves
    """


    def visit(self, doctors):
        arrive = now()
        Qlength = [NoInSystem(doctors[i]) for i in range(Nd)]
        print("%7.4f %s: Here I am. %s" % (now(), self.name, Qlength))
        for i in range(Nd):
            if Qlength[i] == 0 or Qlength[i] == min(Qlength):
                choice = i  # the chosen queue number
                break

        yield request, self, doctors[choice]
        wait = now()-arrive
        print("%7.4f %s: Waited %6.3f" % (now(), self.name, wait))
        tib = triangular(1.0/timeInHospital)
        yield hold, self, tib
        yield release, self, doctors[choice]

        print("%7.4f %s: Finished" % (now(), self.name))













maxNumber = 5
maxTime = 400.0  # minutes
timeInHospital = 12.0  # mean, minutes
ARRint = 0.02  # mean, minutes
Nd = 5          # number of doctors
theseed = 12345

# Model/Experiment ------------------------------

seed(theseed)
# kk = [Resource(name="Doctor1"), Resource(name="Doctor2")]
kk = [Resource(name="Doctor1"), Resource(name="Doctor2"), Resource(name="Doctor3"), Resource(name="Doctor4"), Resource(name="Doctor5")]
initialize()
s = Source('Source')
activate(s, s.generate_C1(number=maxNumber, interval=interval_c,
                       doctors=kk), at=0.0)
activate(s, s.generate_C2(number=maxNumber, interval=interval_c,
                       doctors=kk), at=0.0)

activate(s, s.generate_C3(number=maxNumber, interval=interval_c,
                       doctors=kk), at=0.0)
simulate(until=maxTime)

【问题讨论】:

  • 我要到下周才能看到这个,但是……不要让你的班级成为 Process 的后裔。进程只是一个带有yield 的方法,最常用的事件是env.timeout()。使用 env = Environment() 和 env.process() 启动进程。查看文档中的加油站示例。您是对的,如果您希望每个资源都有自己的队列,那么它需要是拥有一个资源的自己的资源池。
  • 谢谢,我等着。但是现在我创建了每个类的对象,然后单独激活它们,然后在最后为所有它们添加了一个 Hold。 ``` p_C1 = PatientC1(name="Patient_C1%02d" % (i,)) activate(p_C1, p_C1.visit(doctors, ReSusRooms)) t_C1 = expovariate(interval[0]) p_C2 = PatientC2(name="Patient_C2 %02d" % (i,)) 激活(p_C2, p_C2.visit(医生、护士、床位)) t_C2 = expovariate(interval[1]) ``

标签: simpy


【解决方案1】:

这侧重于选择短队列并产生访问量

"""
quick sim of pataints visting doctors

programmer Michael R. Gibbs
"""

import simpy
import random
import sys
from typing import Tuple

def get_short(resourceDict) -> Tuple[str, simpy.Resource]:
    """
    finds the resource in a dict with the shortest queue + users

    returns doc's name, and resource
    """
    best_q_len = sys.maxsize
    best_r = None
    best_k = None

    # iter though dict comparing queue lenghts
    for k,v in resourceDict.items():
        q_len = len(v.users) + len(v.queue)
        if q_len < best_q_len:
            best_q_len = q_len
            best_r = v
            best_k = k

    return best_k, best_r

def visit(env, id, pat_type, doc_dict):
    """
    sims a patient meeting with a doc

    queue
    met
    leave
    """

    # select doc with shortest queue
    doc, r = get_short(doc_dict)

    q_len = len(r.users) + len(r.queue)
    print(f'{env.now} - patient {id} of type {pat_type} has queued with doc {doc} queue size {q_len}')

    with r.request() as req:
        # wait in queue
        yield req
        
        # visit with doc
        print(f'{env.now} - patient {id} of type {pat_type} is with doc {doc}')
        yield env.timeout(random.randint(2,10))

        # leave
        print(f'{env.now} - patient {id} of type {pat_type} is done with doc {doc}')

next_id = 1

def gen_visits(env, pat_type, doc_dict):
    """
    gen a stream of patients of pat_type
    """

    global next_id
    
    while True:
        # wait for next arrival
        yield env.timeout(random.randint(1,4))

        #start visit
        env.process(visit(env, 'pat_' + str(next_id), pat_type, doc_dict))
        next_id += 1

# start sim

env = simpy.Environment()

# to create a queue for each doc, make each doc its own resource of cap=1
doc_dict = {'doc_' + str(i): simpy.Resource(env, capacity=1) for i in range(1,4+1)}

# gen different types of pataients
env.process(gen_visits(env, "pat_type_A", doc_dict))
env.process(gen_visits(env, "pat_type_B", doc_dict))

env.run(100)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 2023-03-19
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多