I'm using SimPy library for relatively simple hospital simulation. There are receptionists, nurses, acu and ed doctors. For each of them I assign the timeout. The point is to collect timeouts for each entity that visits patient. Then for each run_simulation
I count mean value of these timeouts. And lastly in Trial_Results_Calculator
class I get mean value of all timeout for all entities for certain amount of runs. Also there is an possibility for patient get to acu 20%.
The problem is with output for Mean Queueing Time for ACU Doctor over Trial : 1123.91
and Mean Queueing Time for ED Doctor over Trial : 791.31
.
The values should be 3-4 times less for both mean queueing times.
import csv
import simpy
import pandas as pd
import random
class g:
mean_inter_arrival = 8
mean_registration = 2
mean_triage = 5
mean_ED_Assessment = 30
mean_ACU_Assessment = 60
prob_to_ACU = 0.2
receptionists = 1
nurses = 2
ED_Doctors = 2
ACU_Doctors = 1
warm_up = 24*60
run_time = 48*60
run_times = 1
class Patient:
def __init__(self, p_id):
self.p_id = p_id
self.q_time_receptionist = 0
self.q_time_nurse = 0
self.q_time_acu_doctor = float("nan")
self.q_time_ed_doctor = float("nan")
self.prob_to_acu = g.prob_to_ACU
self.go_to_acu = False
if random.random() <= self.prob_to_acu:
self.go_to_acu = True
class Hospital_Model:
def __init__(self, run_number):
self.env = simpy.Environment()
self.patient_counter = 0
self.receptionist = simpy.Resource(self.env, capacity=g.receptionists)
self.nurse = simpy.Resource(self.env, capacity=g.nurses)
self.acu_doctor = simpy.Resource(self.env, capacity=g.ACU_Doctors)
self.ed_doctor = simpy.Resource(self.env, capacity=g.ED_Doctors)
self.mean_q_time_receptionist = 0
self.mean_q_time_nurse = 0
self.mean_q_time_acu_doctor = 0
self.mean_q_time_ed_doctor = 0
self.run_number = run_number
self.results_df = pd.DataFrame()
self.results_df["P_ID"] = []
self.results_df["Q_Time_Receptionist"] = []
self.results_df["Q_Time_Nurse"] = []
self.results_df["Q_Time_ACU_Doctor"] = []
self.results_df["Q_Time_ED_Doctor"] = []
self.results_df.set_index("P_ID", inplace=True)
def patient_arrival(self):
while True:
self.patient_counter += 1
patient = Patient(self.patient_counter)
self.env.process(self.attend_hospital(patient))
sampled_interval = random.expovariate(1.0/g.mean_inter_arrival)
yield self.env.timeout(sampled_interval)
def attend_hospital(self, patient):
start_q_receptionist = self.env.now
with self.receptionist.request() as req:
yield req
end_q_receptionist = self.env.now
patient.q_time_receptionist = end_q_receptionist - start_q_receptionist
sampled_dur_wait = random.expovariate(1.0 / g.mean_registration)
yield self.env.timeout(sampled_dur_wait)
start_q_nurse = self.env.now
with self.nurse.request() as req:
yield req
end_q_nurse = self.env.now
patient.q_time_nurse = end_q_nurse - start_q_nurse
sampled_dur_wait = random.expovariate(1.0 / g.mean_triage)
yield self.env.timeout(sampled_dur_wait)
if patient.go_to_acu:
start_q_acu_doctor = self.env.now
with self.acu_doctor.request() as req:
yield req
end_q_acu_doctor = self.env.now
patient.q_time_acu_doctor = end_q_acu_doctor - start_q_acu_doctor
sampled_dur_wait = random.expovariate(1.0 / g.mean_ACU_Assessment)
yield self.env.timeout(sampled_dur_wait)
else:
start_q_ed_doctor = self.env.now
with self.ed_doctor.request() as req:
yield req
end_q_ed_doctor = self.env.now
patient.q_time_ed_doctor = end_q_ed_doctor - start_q_ed_doctor
sampled_dur_wait = random.expovariate(1.0 / g.mean_ED_Assessment)
yield self.env.timeout(sampled_dur_wait)
if self.env.now > g.warm_up:
df_add = pd.DataFrame({"P_ID": [patient.p_id],
"Q_Time_Receptionist": [patient.q_time_receptionist],
"Q_Time_Nurse": [patient.q_time_nurse],
"Q_Time_ACU_Doctor": [patient.q_time_acu_doctor],
"Q_Time_ED_Doctor": [patient.q_time_ed_doctor]})
self.results_df = pd.concat([self.results_df, df_add], axis=0, join='outer')
def calculate_mean_q_time(self):
self.mean_q_time_receptionist = self.results_df["Q_Time_Receptionist"].mean()
self.mean_q_time_nurse = self.results_df["Q_Time_Nurse"].mean()
self.mean_q_time_acu_doctor = self.results_df["Q_Time_ACU_Doctor"].mean()
self.mean_q_time_ed_doctor = self.results_df["Q_Time_ED_Doctor"].mean()
def write_run_results(self):
with open("trial_results_2.csv", "a") as f:
writer = csv.writer(f, delimiter=",")
results_to_write = [self.run_number,
self.mean_q_time_receptionist,
self.mean_q_time_nurse,
self.mean_q_time_acu_doctor,
self.mean_q_time_ed_doctor]
writer.writerow(results_to_write)
def run(self):
self.env.process(self.patient_arrival())
self.env.run(until=g.run_time+g.warm_up)
self.calculate_mean_q_time()
self.write_run_results()
class Trial_Results_Calculator:
def __init__(self):
self.trial_results_df = pd.DataFrame()
def trial_results(self):
print("TRIAL RESULTS")
print("_____________")
self.trial_results_df = pd.read_csv("trial_results_2.csv")
trial_mean_q_time_receptionist = self.trial_results_df["Mean_Q_Time_Receptionist"].mean()
trial_mean_q_time_nurse = self.trial_results_df["Mean_Q_Time_Nurse"].mean()
trial_mean_q_time_acu_doctor = self.trial_results_df["Mean_Q_Time_ACU_Doctor"].mean()
trial_mean_q_time_ed_doctor = self.trial_results_df["Mean_Q_Time_ED_Doctor"].mean()
print(f"Mean Queueing Time for Receptionist over Trial : {round(trial_mean_q_time_receptionist, 2)}")
print(f"Mean Queueing Time for Nurse over Trial : {round(trial_mean_q_time_nurse, 2)}")
print(f"Mean Queueing Time for ACU Doctor over Trial : {round(trial_mean_q_time_acu_doctor, 2)}")
print(f"Mean Queueing Time for ED Doctor over Trial : {round(trial_mean_q_time_ed_doctor, 2)}")
with open("trial_results_2.csv", "w") as f:
writer = csv.writer(f, delimiter=",")
column_headers = ["Run",
"Mean_Q_Time_Receptionist",
"Mean_Q_Time_Nurse",
"Mean_Q_Time_ACU_Doctor",
"Mean_Q_Time_ED_Doctor"]
writer.writerow(column_headers)
for run in range(g.run_times):
print(f"Run {run} of {g.run_times}")
hospital = Hospital_Model(run)
hospital.run()
print()
my_trial_results = Trial_Results_Calculator()
my_trial_results.trial_results()
I got the code from this tutorial: "https://www.youtube.com/watch?v=QV-pJnKrGuc&ab_channel=HSMA"