I want to modify this code to solve the following problem: Lets say we have two nurses. If both nurses are free then a patient can use both nurses and the treatment time is cut in half. A patient can use both nurses only if there aren't any patients waiting in the queue. If there are two (or more) patients in queue then we take 2 patients off the queue and assign them to each nurse.
import simpy
import numpy as np
np.random.seed(1)
# Define arrival and service time distributions
def draw_arrival_time():
# Use an exponential distribution for arrival times
return np.random.exponential(2.0)
def draw_service_time():
# Use a normal distribution for service times
return np.random.normal(5.0, 1.0)
# Arrivals generator function
def patient_generator(env, nurse):
patient_id = 1
while True:
# Create an instance of activity generator
patient = treatment_activity(env, nurse, patient_id)
# Run the activity generator for this patient
env.process(patient)
# Sample time until next arrival
next_arrival = draw_arrival_time()
# Freeze until that time has passed
yield env.timeout(next_arrival)
patient_id += 1
def treatment_activity(env, nurse, patient_id):
# Patient arrival
time_entered_queue = env.now
print("Patient", patient_id, "arrived at", time_entered_queue)
# Request the nurse
with nurse.request() as req:
yield req
# Calculate the time patient left the queue
time_left_queue = env.now
print("Patient", patient_id, "started treatment at", time_left_queue)
# Calculate the waiting time for this patient
waiting_time = time_left_queue - time_entered_queue
# Append the waiting time to the waiting_times list
waiting_times.append(waiting_time)
# Sample treatment time
treatment _time = draw_service_time()
yield env.timeout(treatment_time)
# Set up simulation environment
env = simpy.Environment()
# Set up resources
nurse = simpy.Resource(env, capacity=1)
# Set up parameter values
waiting_times = []
# Start patient arrivals generator
env.process(patient_generator(env, nurse))
# Run the simulation
env.run(until=90)
# Calculate and print statistics
average_waiting_time = np.mean(waiting_times)
print("Average Waiting Time:", average_waiting_time)
I tried using a resource with capacity 2 nurse = simpy.Resource(env, capacity=2) but this didn't work. Then using two nurses with capacity 1 each, but I couldn't keep track of the queue and didn't how to check if both are free.
Here is a quick example of a patient grabbing one or two nurses and setting the treatment time base on the nurse resource request queue size and the number of available nurses.
"""
Simple simulation of nusrses treating a patient.
If there is only one patient and both nureses are available,
both nurses will treat the patient
with a half the treatment time.
If there is more then one patatient each nurse will take one patient
Programmer: Michael R. Gibbs
"""
import simpy
class Patient():
"""
Patient that needs a nurse,
has a id for tracking
"""
last_id = 0
def __init__(self):
self.__class__.last_id += +1
self.id = self.__class__.last_id
def treat_patient(env, patient, nurse_resource):
"""
Main process where a patient:
waits for a nurse (maybe 2)
gets treated
release the nurses
"""
treat_time = 6
# wait for nurse
n_req =nurse_resource.request()
yield n_req
# list of nurses to be released later
n_reqs = [n_req]
# chech if patient queue is empty
if len(nurse_resource.queue ) == 0:
#check if second nurse is available
if nurse_resource.capacity - nurse_resource.count >= 1:
# get second nurse and cut treatment time
n_req_2 = nurse_resource.request()
yield n_req_2
n_reqs.append(n_req_2)
treat_time = treat_time / 2
# start treatment (note no yield here, just drop and go)
print(f'{env.now:.1f}: patient {patient.id} is being treated by {len(n_reqs)} nurses')
yield env.timeout(treat_time)
# release all the nurses, could be 1 or 2
for req in n_reqs:
nurse_resource.release(req)
print(f'{env.now:.1f}: patient {patient.id} treatment is finished by {len(n_reqs)} nurses')
def gen_patients(env, nurse_resource):
yield env.timeout(1)
patient = Patient()
env.process(treat_patient(env, patient, nurse_resource))
print(f'{env.now:.1f}: patient {patient.id} has arrived')
yield env.timeout(1)
patient = Patient()
env.process(treat_patient(env, patient, nurse_resource))
print(f'{env.now:.1f}: patient {patient.id} has arrived')
yield env.timeout(1)
patient = Patient()
env.process(treat_patient(env, patient, nurse_resource))
print(f'{env.now:.1f}: patient {patient.id} has arrived')
yield env.timeout(30)
patient = Patient()
env.process(treat_patient(env, patient, nurse_resource))
print(f'{env.now:.1f}: patient {patient.id} has arrived')
yield env.timeout(1)
patient = Patient()
env.process(treat_patient(env, patient, nurse_resource))
print(f'{env.now:.1f}: patient {patient.id} has arrived')
env = simpy.Environment()
nurse_resource = simpy.Resource(env, capacity=2)
env.process(gen_patients(env, nurse_resource))
env.run(100)