At the moment I am creating doctors as following:
doctor = simpy.Resource(self.env, capacity=3)
These doctors are requested for a flow of patients using the following:
with self.doctor.request() as req:
yield req2
*patient encounter*
What I would like to do, is initialize the doctors with some kind of fatigue level (and other characteristics) like:
# Class representing a doctor and their characteristics
class Doctor(object):
def __init__(self, env, id, exp_level, fatigue):
self.env = env
self.id = id
self.exp_level = exp_level
self.fatigue = fatigue
self.isAvailable = True
Then in the encounter I would like to access the doctor to add fatigue such as:
with self.doctor.request() as req:
yield req2
*patient encounter*
self.doctor.fatigue += 5
Where once the fatigue crosses a threshold the doctor goes on break and the fatigue is reset, such as:
def monitor_break(self):
while True:
if Doctor.fatigue > 9:
Doctor.fatigue = 0
yield self.env.timeout(15)
Any idea on how to do this?
First I would use a store for your docs instead of using a resource. Second I would decorate the store with a get override to check if the doc needs a nap
something like this
"""
A simple sim where Doctors put themselves on break when they get tired
Programmer Michael R. Gibbs
"""
import simpy
import random
class Doctor():
"""
Doctor that get tired
"""
def __init__(self, env, id):
self.env = env
self.id = id
self.fatigue = 0
class Doc_Pool():
"""
decorates a simpy store
to chekc a doc's fatigue level
and doing a timeout if fatigue is too
high before returning the doc to the pool
"""
def __init__(self, env, num_of_docs, max_fatigue):
self.env = env
self.store = simpy.Store(env)
self.store.items = [Doctor(env, i+1) for i in range(num_of_docs)]
self.max_fatigue = max_fatigue
def get(self):
"""
get a doc from the real store
"""
return self.store.get()
def put(self, doc):
"""
put a doc in the store
unless the doc needs a break
"""
if doc.fatigue > self.max_fatigue:
# needs a break
self.env.process(self._doc_timeout(doc))
else:
self.store.put(doc)
def _doc_timeout(self, doc):
"""
gives the doc a break, then put in store
"""
print(f'{self.env.now:.0f} doctor {doc.id} starting break with fatigue {doc.fatigue:0.2f}')
yield self.env.timeout(doc.fatigue)
doc.fatigue = 0
self.store.put(doc)
print(f'{self.env.now:.0f} doctor {doc.id} ending break')
class Patient():
"""
Simple class to track patients
"""
next_id = 1
def __init__(self):
self.id = self.get_next_id()
@classmethod
def get_next_id (cls):
id =cls.next_id
cls.next_id += 1
return id
def gen_pats(env, doc_store):
"""
Generates the arrival off patients
and queue them up for a doctor visit
"""
while True:
pat = Patient()
print(f'{env.now:.0f} patient {pat.id} has arrived')
yield env.timeout(random.uniform(1,5))
env.process(doc_visit(env, pat, doc_store))
def doc_visit(env, pat, doc_store):
"""
gets a doc, do visit, add fatigue to doc, end visit
"""
doc = yield doc_store.get()
print(f'{env.now:.0f} patient {pat.id} is visiting doctor {doc.id}')
env.timeout(random.uniform(1,6))
doc.fatigue += random.uniform(1,5)
doc_store.put(doc)
print(f'{env.now:.0f} patient {pat.id} visiting doctor {doc.id} has ended')
# boot up sim
env = simpy.Environment()
doc_store = Doc_Pool(env, 3, 10)
env.process(gen_pats(env, doc_store))
env.run(200)
print('end of simulation')