├── README.md ├── SimulationLaundromat.py ├── QueuingSimulation.py ├── QueuingSimulation2serv.py └── server.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # Discrete Event Simulation of a Queue Using Python. 2 | *Written by: Miguel Angel Rizzo Gonzalez* 3 | ![](https://user-images.githubusercontent.com/69512046/93006624-747df780-f52c-11ea-9b3a-8e0f97714b87.jpg) 4 | 5 | ## Project Overview: 6 | - **Generated a Simulation model that outputs the performance measures, such as average length, average waiting time, utilization of the system, etc. to provide information for designing or improving service facilities.** 7 | - **Showed that using this approach, system changes and different layouts can be tested without actually having to carry them out physically.** 8 | - **Simulated over 1000 customer arrivals and departures using Python.** 9 | 10 | 11 | ## Code walkthrough 12 | [https://github.com/miguelrizzog96/Queue_analisis_using_simluation/blob/master/server.ipynb](https://github.com/miguelrizzog96/Queue_analisis_using_simluation/blob/master/server.ipynb) 13 | 14 | ## Why Study Queues? 15 | Waiting to be attended is part of daily life. We wait in restaurants, we do a 16 | line to board a plane, and we stand in line to be served at 17 | official dependencies. The phenomenon of waiting is not limited to human beings: 18 | jobs wait to be processed, planes fly in circles at different heights 19 | until they are allowed to land, and the cars stop at traffic lights. Deleting the 20 | waiting entirely is not a feasible option because the cost of installation and 21 | operation of the operation center can be prohibitive. Our only recourse is to search 22 | the balance between the cost of offering a service and the cost of waiting for it to be served. 23 | Queue analysis is the vehicle to achieve this goal.*(Taha,H.)* 24 | 25 | 26 | ## How does it work? 27 | At its core, a queuing situation involves two parts. 28 | 29 | 1. Someone or something that requests a service—usually referred to as the customer, job, or request. 30 | 2. Someone or something that completes or delivers the services—usually referred to as the server. 31 | 32 | Consider this Example: A filling station that has two dispensers. Cars arrive about every 5 minutes on average according to a Poisson process, this means that the average time between events is known, but the exact timing of events is random. The average time it takes to fill a car is 3 minutes, also a Poisson process. These rates often are actually modeled from actual data to get accurate results. When a car enters the facility, and at least a station is idle, they enter the system. if not they wait in line until a station becomes available, as it can be seen on the following diagram: 33 | 34 | 35 | ![](https://user-images.githubusercontent.com/69512046/94444662-8c808880-0174-11eb-8706-e05c9b4b7eed.JPG) 36 | 37 | 38 | ## Which data do we need? 39 | - λ: the arrival rate (the expected number of consecutive arrivals per the same unit time, e.g. 1 minute) 40 | - μ: the service rate (the expected number of consecutive service completions per the same unit time, e.g. 1 minute) 41 | - the distribution of the data 42 | - c: the number of servers 43 | 44 | 45 | ## Data Visualization 46 | 47 | Here are the distributions of the data and the value counts for other variables like occupation and number of customers in an example model. Below are a few key points of the corresponding system. 48 | 49 | 50 | ![Figure 2020-09-17 074636 (1)](https://user-images.githubusercontent.com/69512046/99907675-87dbda80-2cb4-11eb-8bd9-431acfcdf26a.png) 51 | 52 | ![Figure 2020-09-17 074636 (2)](https://user-images.githubusercontent.com/69512046/99907674-86aaad80-2cb4-11eb-9469-1a2fdd2651f6.png) 53 | 54 | ![Figure 2020-09-17 074636 (3)](https://user-images.githubusercontent.com/69512046/99907672-86121700-2cb4-11eb-994c-aa76205650cf.png) 55 | 56 | ![Figure 2020-10-19 084256](https://user-images.githubusercontent.com/69512046/99907671-84e0ea00-2cb4-11eb-9da5-47c03c67d5db.png) 57 | 58 | | Example Output: | | 59 | | ----------- | ----------- | 60 | | Time Between Arrivals (minutes): | 1.0108 | 61 | | Service Time (minutes): | 0.6494 | 62 | | Utilization: | 0.6418 | 63 | | Expected wait time in line (Wq) (minutes):| 1.5845 | 64 | | Expected number of customers in line (Lq):| 1.5673 | 65 | | Expected number of clients in the system (Ls): | 2.2092 | 66 | | Expected time spent on the system (Ws) (minutes):| 2.2338 | 67 | 68 | ## Model Development Steps 69 | Using Python 3.7.6: 70 | 71 | Parameters used for reference: λ = 1 (Poisson) , μ = 1.5 (Poisson) , c = 1 , n=1000 72 | 73 | - Generated arrival and service times with random number generation using the python library `numpy` 74 | - Generated lists and dataframes with conditional statements to represent the events ocurring in the queue 75 | - Used the generated model for simulating a multiple server queue with n customers 76 | - Generate the output for a range from 1 servers to n numbers of servers 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SimulationLaundromat.py: -------------------------------------------------------------------------------- 1 | import simpy 2 | import random 3 | 4 | 5 | def customer(env, name, washing_machines, driers, wash_time_range, dry_time_range, leave_probability, 6 | leave_probability_full, 7 | queue_lengths,driers_queue_lengths , washing_machines_queue_lengths, 8 | time_in_systems, utilization_washers, 9 | utilization_driers, timeline,dry_only): 10 | 11 | arrival_time = env.now 12 | timeline.append(f"{name} arrives at the laundromat at {arrival_time:.2f}") 13 | 14 | if random.random() < dry_only: 15 | # Check if both washing machines and driers are available 16 | if washing_machines.count == washing_machines.capacity: 17 | if random.random() < leave_probability_full: 18 | timeline.append(f"{name} leaves the laundromat due to full washing machine capacity at {env.now:.2f}") 19 | return 20 | with washing_machines.request() as wash_request: 21 | yield wash_request 22 | start_wash_time = env.now 23 | timeline.append(f"{name} starts using a washing machine at {start_wash_time:.2f}") 24 | wash_time = random.uniform(*wash_time_range) 25 | yield env.timeout(wash_time) 26 | end_wash_time = env.now 27 | timeline.append(f"{name} finishes washing at {end_wash_time:.2f}") 28 | wash_count.append(1) 29 | 30 | # Check if the customer leaves after washing 31 | if random.random() < leave_probability: 32 | timeline.append(f"{name} leaves the laundromat after washing at {end_wash_time:.2f}") 33 | return 34 | if driers.count == driers.capacity: 35 | if random.random() < leave_probability_full: 36 | timeline.append(f"{name} leaves the laundromat due to full driers capacity at {env.now:.2f}") 37 | return 38 | # Check if the customer uses a drier 39 | 40 | with driers.request() as dry_request: 41 | yield dry_request 42 | start_dry_time = env.now 43 | timeline.append(f"{name} starts using a drier at {start_dry_time:.2f}") 44 | dry_time = random.uniform(*dry_time_range) 45 | yield env.timeout(dry_time) 46 | end_dry_time = env.now 47 | timeline.append(f"{name} finishes drying at {end_dry_time:.2f}") 48 | drier_count.append(1) 49 | 50 | leave_time = env.now 51 | timeline.append(f"{name} leaves the laundromat at {leave_time:.2f}") 52 | 53 | # Update metrics 54 | queue_lengths.append(len(washing_machines.queue) + len(driers.queue)) 55 | driers_queue_lengths.append( len(driers.queue)) 56 | washing_machines_queue_lengths.append(len(washing_machines.queue)) 57 | time_in_systems.append(leave_time - arrival_time) 58 | utilization_washers.append(washing_machines.count / washing_machines.capacity) 59 | utilization_driers.append(driers.count / driers.capacity) 60 | 61 | def customer_generator(env, washing_machines, driers, arrival_rate, wash_time_range, 62 | dry_time_range, leave_probability, leave_probability_full, 63 | queue_lengths,driers_queue_lengths, washing_machines_queue_lengths, 64 | time_in_systems, utilization_washers, utilization_driers,timeline,dry_only): 65 | customer_count = 0 66 | while True: 67 | yield env.timeout(random.expovariate(arrival_rate)) 68 | customer_count += 1 69 | env.process(customer(env, f"Customer-{customer_count}", washing_machines, driers, wash_time_range, 70 | dry_time_range, leave_probability, leave_probability_full, 71 | queue_lengths,driers_queue_lengths, washing_machines_queue_lengths, 72 | time_in_systems, utilization_washers, utilization_driers,timeline,dry_only)) 73 | 74 | # Simulation setup 75 | env = simpy.Environment() 76 | washing_machines = simpy.Resource(env, capacity=3) 77 | driers = simpy.Resource(env, capacity=2) 78 | dry_only=0.9 79 | 80 | # Metrics 81 | timeline= [] 82 | queue_lengths = [] 83 | driers_queue_lengths = [] 84 | washing_machines_queue_lengths = [] 85 | time_in_systems = [] 86 | utilization_washers = [] 87 | utilization_driers = [] 88 | wash_count = [] 89 | drier_count = [] 90 | 91 | # Start the simulation 92 | env.process(customer_generator(env, washing_machines, driers, arrival_rate=0.025, wash_time_range=(35, 45), dry_time_range=(15, 30), 93 | leave_probability=0.1, leave_probability_full=0.5, 94 | queue_lengths=queue_lengths,washing_machines_queue_lengths =washing_machines_queue_lengths, 95 | driers_queue_lengths =driers_queue_lengths, 96 | time_in_systems=time_in_systems, 97 | utilization_washers=utilization_washers, 98 | utilization_driers=utilization_driers, timeline=timeline,dry_only=dry_only)) 99 | 100 | env.run(until=870)#minutes870 101 | 102 | # Calculate and print metrics 103 | avg_queue_washing_machine= sum(washing_machines_queue_lengths)/len(washing_machines_queue_lengths) 104 | avg_queue_drier= sum(driers_queue_lengths)/len(driers_queue_lengths) 105 | avg_queue_length = sum(queue_lengths) / len(queue_lengths) 106 | avg_time_in_system = sum(time_in_systems) / len(time_in_systems) 107 | avg_utilization_washers = sum(utilization_washers) / len(utilization_washers) 108 | avg_utilization_driers = sum(utilization_driers) / len(utilization_driers) 109 | total_wash_count = sum(wash_count) 110 | total_drier_count = sum(drier_count) 111 | earnings= sum(drier_count)*3 + sum(wash_count)*4 112 | 113 | 114 | print(f"Average Drier queue: {avg_queue_drier:.2f}") 115 | print(f"Average Washing Machine Queue: {avg_queue_washing_machine:.2f}") 116 | print(f"Average # of People waiting in the system: {avg_queue_length:.2f}") 117 | print(f"Average Time in System: {avg_time_in_system:.2f}") 118 | print(f"Average Utilization of Washers: {avg_utilization_washers:.2%}") 119 | print(f"Average Utilization of Driers: {avg_utilization_driers:.2%}") 120 | print(f"Total Washing Machine Usage: {total_wash_count}") 121 | print(f"Total Drier Usage: {total_drier_count}") 122 | print(f"Earnings: {earnings}") 123 | 124 | 125 | -------------------------------------------------------------------------------- /QueuingSimulation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Sep 12 14:00:13 2020 4 | 5 | @author: Miguel Rizzo 6 | """ 7 | 8 | ##single server 9 | 10 | #Importing Libraries 11 | import pandas as pd 12 | import seaborn as sns 13 | import numpy as np 14 | import matplotlib.pyplot as plt 15 | 16 | 17 | import warnings 18 | warnings.filterwarnings('ignore') 19 | 20 | #Single server, single queue simulation 21 | l = 1 # average number of arrivals per minute 22 | µ =1.5 # average number of people served per minute 23 | ncust =1000# number of customers 24 | c=1 # number of servers 25 | 26 | #generating inter arrival times using exponential distribution 27 | 28 | inter_arrival_times = list(np.random.exponential(scale=1/l,size=ncust)) 29 | 30 | 31 | 32 | arrival_times= []# list of arrival times of a person joining the queue 33 | service_times = [] # list of service times once they reach the front 34 | finish_times = [] # list of finish times after waiting and being served 35 | 36 | arrival_times = [0 for i in range(ncust)] 37 | finish_times = [0 for i in range(ncust)] 38 | 39 | arrival_times[0]=round(inter_arrival_times[0],2)#arrival of first customer 40 | 41 | #Generate arrival times 42 | for i in range(1,ncust): 43 | arrival_times[i]=round((arrival_times[i-1]+inter_arrival_times[i]),2) 44 | 45 | 46 | # Generate random service times for each customer 47 | service_times = list(np.random.exponential(scale=1/µ,size=ncust)) 48 | 49 | 50 | 51 | #finish time for first customer 52 | finish_times[0]=round((arrival_times[0]+service_times[0]),2) 53 | 54 | #generating finish times 55 | for i in range(1,ncust): 56 | finish_times[i] = round((max(arrival_times[i], finish_times[i-1]) + service_times[i]),2) 57 | 58 | # Total time spent in the system by each customer 59 | total_times =[abs(round((finish_times[i]-arrival_times[i]),2)) for i in range(ncust)] 60 | 61 | 62 | 63 | # Time spent@waiting before being served (time spent in the queue) 64 | wait_times = [abs(round((total_times[i] - service_times[i]),2)) for i in range(ncust)] 65 | 66 | 67 | #creating a dataframe with all the data of the model 68 | data = pd.DataFrame(list(zip(arrival_times,service_times,total_times,finish_times,wait_times,inter_arrival_times)), 69 | columns =['arrival_times', 'service_times','total_times','finish_times','wait_times','inter_arrival_times']) 70 | 71 | #generating time between events , and their description (arrivals, departures) 72 | 73 | tbe=list([0]) 74 | timeline=['simulation starts'] 75 | for i in range(1,ncust): 76 | tbe.append(data['arrival_times'][i]) 77 | tbe.append(data['finish_times'][i]) 78 | timeline.append('customer ' +str(i)+' arrived') 79 | timeline.append('customer ' +str(i)+' left') 80 | 81 | 82 | #Creating a dataframe to summarize the time between events 83 | timeline = pd.DataFrame(list(zip(tbe,timeline)), 84 | columns =['time','Timeline']).sort_values(by='time').reset_index() 85 | timeline=timeline.drop(columns='index') 86 | 87 | #generating the number of customers inside the system at any given time of the simulation 88 | 89 | timeline['n']=0 90 | x=0 91 | idletime=0 92 | workingtime=0 93 | for i in range(1,(2*ncust)-2): 94 | if len(((timeline.Timeline[i]).split()))>2: 95 | z=str(timeline['Timeline'][i]).split()[2] 96 | else: 97 | continue 98 | if z =='arrived': 99 | x = x+1 100 | timeline['n'][i]=x 101 | else: 102 | x=x-1 103 | if x==-1: 104 | x=0 105 | timeline['n'][i]=x 106 | 107 | if timeline['n'][i]==0: 108 | idletime=idletime+ timeline['time'][i+1]-timeline['time'][i] 109 | else: 110 | workingtime= workingtime+ timeline['time'][i+1]-timeline['time'][i] 111 | 112 | workingtime=workingtime+timeline['time'][2*ncust-3]-timeline['time'][2*ncust-2] 113 | 114 | 115 | timeline.time.max() 116 | workingtime+idletime 117 | 118 | data['occupied']=[0 for i in range(ncust)] 119 | for i in range(1,ncust): 120 | 121 | if data.arrival_times[i]>data.finish_times[i-1]: 122 | data['occupied'][i]=1 123 | else: 124 | data['occupied'][i]=0 125 | 126 | 127 | t= list() 128 | for i in timeline.index: 129 | if i == (2*ncust) -2 : 130 | continue 131 | x=timeline.time[i+1] 132 | y=timeline.time[i] 133 | t.append(round((x-y),3)) 134 | 135 | t.append(0) 136 | timeline['tbe']=t 137 | Pn=timeline.groupby('n').tbe.agg(sum)/sum(t) 138 | 139 | 140 | 141 | #checking central tendency measures and dispersion of the data 142 | timeline.n.describe() 143 | data.occupied.value_counts() 144 | 145 | timeline['Lq']=0 146 | for i in timeline.index: 147 | if timeline.n[i]>1: 148 | timeline.Lq[i]= timeline['n'][i]-c 149 | 150 | 151 | ocupation= pd.Series(name='ocupation',data=[idletime/data.finish_times.max(), 152 | workingtime/data.finish_times.max()],index=['Idle','Ocuppied']) 153 | #plots 154 | 155 | plt.figure(figsize=(12,4)) 156 | sns.lineplot(x=data.index,y=wait_times,color='black') 157 | plt.xlabel('Customer number') 158 | plt.ylabel('minutes') 159 | plt.title('Wait time of customers') 160 | sns.despine() 161 | plt.show() 162 | 163 | plt.figure(figsize=(7,7)) 164 | sns.distplot(inter_arrival_times,kde=False,color='r') 165 | plt.title('Time between Arrivals') 166 | plt.xlabel('Minutes') 167 | plt.ylabel('Frequency') 168 | sns.despine() 169 | plt.show() 170 | 171 | plt.figure(figsize=(8,8)) 172 | sns.distplot(service_times,kde=False) 173 | plt.title('Service Times') 174 | plt.xlabel('Minutes') 175 | plt.ylabel('Frequency') 176 | sns.despine() 177 | plt.show() 178 | 179 | plt.figure(figsize=(8,8)) 180 | sns.barplot(x=Pn.index,y=Pn,color='g') 181 | plt.title('Probability of n customers in the system') 182 | plt.xlabel('number of customers') 183 | plt.ylabel('Probability') 184 | sns.despine() 185 | plt.show() 186 | 187 | 188 | plt.figure(figsize=(7,7)) 189 | sns.barplot(ocupation.index,ocupation,color='mediumpurple') 190 | plt.title('Utilization %') 191 | plt.xlabel('System state') 192 | plt.ylabel('Probability') 193 | sns.despine() 194 | plt.show() 195 | 196 | 197 | Ls=(sum(Pn*Pn.index)) 198 | Lq=sum((Pn.index[c+1:]-1)*(Pn[c+1:])) 199 | 200 | print('Output:','\n', 201 | 'Time Between Arrivals : ',str(data.inter_arrival_times.mean()),'\n', 202 | 'Service Time: (1/µ)',str(data.service_times.mean()),'\n' 203 | ' Utilization (c): ',str(workingtime/timeline.time.max()),'\n', 204 | 'Expected wait time in line (Wq):',str(data['wait_times'].mean()),'\n', 205 | 'Expected time spent on the system (Ws):',str(data.total_times.mean()),'\n', 206 | 'Expected number of customers in line (Lq):',str(Lq),'\n', 207 | 'Expected number of clients in the system (Ls):',str(Ls),'\n') 208 | 209 | -------------------------------------------------------------------------------- /QueuingSimulation2serv.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Sep 12 14:00:13 2020 4 | 5 | @author: Miguel Rizzo 6 | """ 7 | 8 | ##single server 9 | 10 | #Importing Libraries 11 | import pandas as pd ,seaborn as sns, numpy as np ,matplotlib.pyplot as plt 12 | import warnings 13 | warnings.filterwarnings('ignore') 14 | # set seed for reproducibility 15 | np.random.seed(0) 16 | 17 | #Single server, single queue simulation 18 | l = 1 # average number of arrivals per minute 19 | µ =1.5 # average number of people served per minute 20 | ncust =1000# number of customers 21 | c=1 # number of servers 22 | utilization={} 23 | service_times = [] # list of service times once they reach the front 24 | 25 | #generating inter arrival times using exponential distribution 26 | while c<=5: 27 | if c==1: 28 | inter_arrival_times = list(np.random.exponential(scale=1/l,size=ncust)) 29 | 30 | arrival_times= []# list of arrival times of a person joining the queue 31 | finish_times = [] # list of finish times after waiting and being served 32 | 33 | arrival_times = [0 for i in range(ncust)] 34 | finish_times = [0 for i in range(ncust)] 35 | 36 | arrival_times[0]=round(inter_arrival_times[0],4)#arrival of first customer 37 | 38 | #Generate arrival times 39 | 40 | for i in range(1,ncust): 41 | arrival_times[i]=round((arrival_times[i-1]+inter_arrival_times[i]),4) 42 | 43 | 44 | # Generate random service times for each customer 45 | if c==1: 46 | service_times = list(np.random.exponential(scale=1/µ,size=ncust)) 47 | 48 | 49 | #Generate finish times 50 | finish_times[0]= round((arrival_times[0]+service_times[0]),4) 51 | for i in range(1,ncust): 52 | previous_finish=finish_times[:i] 53 | previous_finish.sort(reverse=True) 54 | previous_finish=previous_finish[:c] 55 | if i< c: 56 | finish_times[i] = round(arrival_times[i] + service_times[i],4) 57 | else: 58 | finish_times[i]=round((max(arrival_times[i],min(previous_finish))+service_times[i]),4) 59 | 60 | 61 | # Total time spent in the system by each customer 62 | total_times =[abs(round((finish_times[i]-arrival_times[i]),4)) for i in range(ncust)] 63 | 64 | 65 | 66 | # Time spent@waiting before being served (time spent in the queue) 67 | wait_times = [abs(round((total_times[i] - service_times[i]),4)) for i in range(ncust)] 68 | 69 | 70 | #creating a dataframe with all the data of the model 71 | data = pd.DataFrame(list(zip(arrival_times,finish_times,service_times,total_times,wait_times,inter_arrival_times)), 72 | columns =['arrival_times','finish_times', 'service_times','total_times','wait_times','inter_arrival_times']) 73 | 74 | #generating the timeline , and their description (arrivals, departures) 75 | 76 | tbe=list([0]) 77 | timeline=['simulation starts'] 78 | for i in range(0,ncust): 79 | tbe.append(data['arrival_times'][i]) 80 | tbe.append(data['finish_times'][i]) 81 | timeline.append('customer ' +str(i+1)+' arrived') 82 | timeline.append('customer ' +str(i+1)+' left') 83 | 84 | 85 | #generating a dataframe with the timeline and description of events 86 | 87 | timeline = pd.DataFrame(list(zip(tbe,timeline)), 88 | columns =['time','Timeline']).sort_values(by='time').reset_index() 89 | timeline=timeline.drop(columns='index') 90 | 91 | #generating the number of customers inside the system at any given time of the simulation 92 | # and recording idle and working times 93 | 94 | timeline['n']=0 95 | x=0 96 | for i in range(1,(2*ncust)-1): 97 | if len(((timeline.Timeline[i]).split()))>2: 98 | z=str(timeline['Timeline'][i]).split()[2] 99 | else: 100 | continue 101 | if z =='arrived': 102 | x = x+1 103 | timeline['n'][i]=x 104 | else: 105 | x=x-1 106 | if x==-1: 107 | x=0 108 | timeline['n'][i]=x 109 | 110 | 111 | 112 | #computing time between events 113 | t= list() 114 | for i in timeline.index: 115 | if i == (2*ncust) -2 : 116 | continue 117 | if i < 2*ncust: 118 | x=timeline.time[i+1] 119 | else: 120 | x=timeline.time[i] 121 | y=timeline.time[i] 122 | t.append(round((x-y),4)) 123 | 124 | t.append(0) 125 | timeline['tbe']=t 126 | 127 | #computing the probability of 'n' customers being in the system 128 | 129 | Pn=timeline.groupby('n').tbe.agg(sum)/sum(t) 130 | Tn=timeline.groupby('n').tbe.agg('count') 131 | 132 | 133 | #checking central tendency measures and dispersion of the data 134 | timeline.n.describe() 135 | 136 | 137 | #computing expected number of customers in the system 138 | Ls=(sum(Pn*Pn.index)) 139 | 140 | 141 | #computing expected customers waiting in line 142 | Lq=sum((Pn.index[c+1:]-1)*(Pn[c+1:])) 143 | 144 | #plots 145 | 146 | 147 | plt.figure(figsize=(12,4)) 148 | sns.lineplot(x=data.index,y=wait_times,color='black').set(xticklabels=[]) 149 | plt.xlabel('Customer number') 150 | plt.ylabel('minutes') 151 | plt.title('Wait time of customers with '+str(c)+ ' servers') 152 | sns.despine() 153 | plt.show() 154 | 155 | if c==1: 156 | plt.figure(figsize=(7,7)) 157 | sns.distplot(inter_arrival_times,kde=False,color='r') 158 | plt.title('Time between Arrivals') 159 | plt.xlabel('Minutes') 160 | plt.ylabel('Frequency') 161 | sns.despine() 162 | plt.show() 163 | 164 | plt.figure(figsize=(8,8)) 165 | sns.distplot(service_times,kde=False) 166 | plt.title('Service Times') 167 | plt.xlabel('Minutes') 168 | plt.ylabel('Frequency') 169 | sns.despine() 170 | plt.show() 171 | 172 | plt.figure(figsize=(8,8)) 173 | sns.barplot(x=Pn.index,y=Pn,color='g') 174 | plt.title('Probability of n customers in the system with '+str(c)+ ' servers') 175 | plt.xlabel('number of customers') 176 | plt.ylabel('Probability') 177 | sns.despine() 178 | plt.show() 179 | 180 | ############################ 181 | '''plt.figure(figsize=(7,7)) 182 | sns.barplot(['Idle','Occupied'],[Pn[0],1-Pn[0]],color='mediumpurple') 183 | plt.title('Utilization %') 184 | plt.xlabel('System state') 185 | plt.ylabel('Probability') 186 | sns.despine() 187 | plt.show()''' 188 | ########################## 189 | utilization.setdefault(c,(Ls-Lq)/c) 190 | 191 | 192 | print('Output:','\n', 193 | 'Servers : '+str(c),'\n ' 194 | 'Time Between Arrivals : ',str(data.inter_arrival_times.mean()),'\n', 195 | 'Service Time: (1/µ)',str(data.service_times.mean()),'\n' 196 | ' Utilization (c): ',str((Ls-Lq)/c),'\n', 197 | 'Expected wait time in line (Wq):',str(data['wait_times'].mean()),'\n', 198 | 'Expected time spent on the system (Ws):',str(data.total_times.mean()),'\n', 199 | 'Expected number of customers in line (Lq):',str(Lq),'\n', 200 | 'Expected number of clients in the system (Ls):',str(Ls),'\n ' 201 | 'Expected number of occupied servers :',str(Ls-Lq),'\n') 202 | 203 | c=c+1 204 | 205 | utilization=pd.Series(utilization) 206 | plt.figure(figsize=(6,6)) 207 | sns.pointplot(x=utilization.index,y=utilization) 208 | plt.xlabel('Number of servers') 209 | plt.ylabel('Utilization') 210 | plt.title('number of servers vs Utilization') 211 | 212 | -------------------------------------------------------------------------------- /server.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Discrete Event Simulation of a Queue using Python\n", 8 | "\n", 9 | "\n", 10 | "\n", 11 | "### Objective: Generate a Simulation model that outputs the performance measures, such as average length, average waiting time, utilization of the system, etc. to provide information for designing or improving service facilities.\n", 12 | "##### Data:\n", 13 | "- λ: the arrival rate (the expected number of consecutive arrivals per the same unit time, e.g. 1 minute)\n", 14 | "- μ: the service rate (the expected number of consecutive service completions per the same unit time, e.g. 1 minute)\n", 15 | "- the distribution of the data\n", 16 | "- c: the number of servers = 1" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 2, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "#Importing Libraries\n", 26 | "import pandas as pd ,seaborn as sns, numpy as np ,matplotlib.pyplot as plt\n", 27 | "import warnings\n", 28 | "warnings.filterwarnings('ignore')\n", 29 | "# set seed for reproducibility\n", 30 | "np.random.seed(0)\n" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "#Single or multiple server queue simulation\n", 40 | "l = 1 # average number of arrivals per minute\n", 41 | "µ =1.5 # average number of people served per minute\n", 42 | "ncust =1000# number of customers\n", 43 | "c=1 # number of servers\n", 44 | "#empty dictionary for computing the utilization with each configuration of servers\n", 45 | "utilization={}" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | " ### For this project the data will be generated using random number generation, in an actual study the rates should be modeled from real data to get more accurate results. \n" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 8, 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "data": { 62 | "image/png": "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\n", 63 | "text/plain": [ 64 | "
" 65 | ] 66 | }, 67 | "metadata": { 68 | "needs_background": "light" 69 | }, 70 | "output_type": "display_data" 71 | }, 72 | { 73 | "data": { 74 | "image/png": "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\n", 75 | "text/plain": [ 76 | "
" 77 | ] 78 | }, 79 | "metadata": { 80 | "needs_background": "light" 81 | }, 82 | "output_type": "display_data" 83 | } 84 | ], 85 | "source": [ 86 | " #generating inter arrival times using exponential distribution\n", 87 | "inter_arrival_times = list(np.random.exponential(scale=1/l,size=ncust))\n", 88 | "\n", 89 | " #plotting data\n", 90 | "plt.figure(figsize=(4,4))\n", 91 | "sns.distplot(inter_arrival_times,kde=False,color='r',bins=20)\n", 92 | "plt.title('Time between Arrivals')\n", 93 | "plt.xlabel('Minutes')\n", 94 | "plt.ylabel('Frequency')\n", 95 | "sns.despine()\n", 96 | "plt.show()\n", 97 | "\n", 98 | " # Generate random service times for each customer \n", 99 | "service_times = list(np.random.exponential(scale=1/µ,size=ncust)) \n", 100 | "\n", 101 | "#service time distribution plot\n", 102 | "plt.figure(figsize=(4,4))\n", 103 | "sns.distplot(service_times,kde=False,bins=20)\n", 104 | "plt.title('Service Times')\n", 105 | "plt.xlabel('Minutes')\n", 106 | "plt.ylabel('Frequency')\n", 107 | "sns.despine()\n", 108 | "plt.show()\n" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 4, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "arrival_times= []# list of arrival times of a person joining the queue\n", 118 | "service_times = [] # list of service times once they reach the front\n", 119 | "finish_times = [] # list of finish times after waiting and being served\n", 120 | " \n", 121 | "arrival_times = [0 for i in range(ncust)]\n", 122 | "finish_times = [0 for i in range(ncust)]\n", 123 | " \n", 124 | "arrival_times[0]=round(inter_arrival_times[0],4)#arrival of first customer\n", 125 | "#Generate arrival times\n", 126 | "for i in range(1,ncust):\n", 127 | " arrival_times[i]=round((arrival_times[i-1]+inter_arrival_times[i]),4)\n", 128 | " " 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 6, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "\n", 138 | "#Generating finish times\n", 139 | "finish_times[0]= round((arrival_times[0]+service_times[0]),4)\n", 140 | "for i in range(1,ncust):\n", 141 | " previous_finish=finish_times[:i]\n", 142 | " previous_finish.sort(reverse=True)\n", 143 | " previous_finish=previous_finish[:c]\n", 144 | " if i< c:\n", 145 | " finish_times[i] = round(arrival_times[i] + service_times[i],4)\n", 146 | " else:\n", 147 | " finish_times[i]=round((max(arrival_times[i],min(previous_finish))+service_times[i]),4) \n", 148 | " \n", 149 | " # Total time spent in the system by each customer\n", 150 | "total_times =[abs(round((finish_times[i]-arrival_times[i]),4)) for i in range(ncust)]\n", 151 | " \n", 152 | " # Time spent@waiting before being served (time spent in the queue)\n", 153 | "wait_times = [abs(round((total_times[i] - service_times[i]),4)) for i in range(ncust)]" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 12, 159 | "metadata": {}, 160 | "outputs": [ 161 | { 162 | "data": { 163 | "image/png": "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\n", 164 | "text/plain": [ 165 | "
" 166 | ] 167 | }, 168 | "metadata": { 169 | "needs_background": "light" 170 | }, 171 | "output_type": "display_data" 172 | } 173 | ], 174 | "source": [ 175 | "#plotting Wait times\n", 176 | "plt.figure(figsize=(12,4))\n", 177 | "sns.lineplot(x=data.index,y=wait_times,color='black').set(xticklabels=[])\n", 178 | "plt.xlabel('Customer number')\n", 179 | "plt.ylabel('minutes')\n", 180 | "plt.title('Wait time of customers')\n", 181 | "sns.despine()\n", 182 | "plt.show()" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 7, 188 | "metadata": {}, 189 | "outputs": [ 190 | { 191 | "data": { 192 | "text/html": [ 193 | "
\n", 194 | "\n", 207 | "\n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | "
arrival_timesfinish_timesservice_timestotal_timeswait_timesinter_arrival_times
01.79493.06441.2694591.26950.00001.794872
12.14943.86200.7976261.71260.91500.354532
23.13897.36593.5038864.22700.72310.989520
33.58757.87590.5100134.28843.77840.448650
44.29328.17670.3008223.88353.58270.705746
\n", 267 | "
" 268 | ], 269 | "text/plain": [ 270 | " arrival_times finish_times service_times total_times wait_times \\\n", 271 | "0 1.7949 3.0644 1.269459 1.2695 0.0000 \n", 272 | "1 2.1494 3.8620 0.797626 1.7126 0.9150 \n", 273 | "2 3.1389 7.3659 3.503886 4.2270 0.7231 \n", 274 | "3 3.5875 7.8759 0.510013 4.2884 3.7784 \n", 275 | "4 4.2932 8.1767 0.300822 3.8835 3.5827 \n", 276 | "\n", 277 | " inter_arrival_times \n", 278 | "0 1.794872 \n", 279 | "1 0.354532 \n", 280 | "2 0.989520 \n", 281 | "3 0.448650 \n", 282 | "4 0.705746 " 283 | ] 284 | }, 285 | "execution_count": 7, 286 | "metadata": {}, 287 | "output_type": "execute_result" 288 | } 289 | ], 290 | "source": [ 291 | " #creating a dataframe with all the data of the model\n", 292 | " \n", 293 | "data = pd.DataFrame(list(zip(arrival_times,finish_times,service_times,total_times,wait_times,inter_arrival_times)), \n", 294 | " columns =['arrival_times','finish_times', 'service_times','total_times','wait_times','inter_arrival_times']) \n", 295 | "\n", 296 | "#Printing the first 5 rows of the data\n", 297 | "data.head()\n", 298 | " " 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": 8, 304 | "metadata": {}, 305 | "outputs": [ 306 | { 307 | "data": { 308 | "text/html": [ 309 | "
\n", 310 | "\n", 323 | "\n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | "
timeTimeline
00.0000simulation starts
11.7949customer 1 arrived
22.1494customer 2 arrived
33.0644customer 1 left
43.1389customer 3 arrived
\n", 359 | "
" 360 | ], 361 | "text/plain": [ 362 | " time Timeline\n", 363 | "0 0.0000 simulation starts\n", 364 | "1 1.7949 customer 1 arrived\n", 365 | "2 2.1494 customer 2 arrived\n", 366 | "3 3.0644 customer 1 left\n", 367 | "4 3.1389 customer 3 arrived" 368 | ] 369 | }, 370 | "execution_count": 8, 371 | "metadata": {}, 372 | "output_type": "execute_result" 373 | } 374 | ], 375 | "source": [ 376 | "tbe=list([0])\n", 377 | "timeline=['simulation starts']\n", 378 | "for i in range(0,ncust):\n", 379 | " tbe.append(data['arrival_times'][i])\n", 380 | " tbe.append(data['finish_times'][i])\n", 381 | " timeline.append('customer ' +str(i+1)+' arrived')\n", 382 | " timeline.append('customer ' +str(i+1)+' left')\n", 383 | " \n", 384 | " \n", 385 | "#generating a dataframe with the timeline and description of events\n", 386 | " \n", 387 | "timeline = pd.DataFrame(list(zip(tbe,timeline)), \n", 388 | " columns =['time','Timeline']).sort_values(by='time').reset_index()\n", 389 | "timeline=timeline.drop(columns='index')\n", 390 | "\n", 391 | "#printing the first 5 rows of the data\n", 392 | "timeline.head()\n", 393 | " " 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": 9, 399 | "metadata": {}, 400 | "outputs": [], 401 | "source": [ 402 | "#generating the number of customers inside the system at any given time of the simulation\n", 403 | " \n", 404 | "timeline['n']=0\n", 405 | "x=0\n", 406 | "for i in range(1,(2*ncust)-1):\n", 407 | " if len(((timeline.Timeline[i]).split()))>2:\n", 408 | " z=str(timeline['Timeline'][i]).split()[2]\n", 409 | " else:\n", 410 | " continue\n", 411 | " if z =='arrived':\n", 412 | " x = x+1\n", 413 | " timeline['n'][i]=x\n", 414 | " else:\n", 415 | " x=x-1\n", 416 | " if x==-1:\n", 417 | " x=0\n", 418 | " timeline['n'][i]=x" 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": 25, 424 | "metadata": {}, 425 | "outputs": [], 426 | "source": [ 427 | " #computing time between events\n", 428 | " t= list()\n", 429 | " for i in timeline.index:\n", 430 | " if i == (2*ncust) -2 :\n", 431 | " continue\n", 432 | " if i < 2*ncust:\n", 433 | " x=timeline.time[i+1]\n", 434 | " else:\n", 435 | " x=timeline.time[i]\n", 436 | " y=timeline.time[i]\n", 437 | " t.append(round((x-y),4))\n", 438 | " \n", 439 | " t.append(0) \n", 440 | " timeline['tbe']=t" 441 | ] 442 | }, 443 | { 444 | "cell_type": "code", 445 | "execution_count": 26, 446 | "metadata": {}, 447 | "outputs": [ 448 | { 449 | "data": { 450 | "text/html": [ 451 | "
\n", 452 | "\n", 465 | "\n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | "
timeTimelinentbe
00.0000simulation starts01.7949
11.7949customer 1 arrived10.3545
22.1494customer 2 arrived20.9150
33.0644customer 1 left10.0745
43.1389customer 3 arrived20.4486
\n", 513 | "
" 514 | ], 515 | "text/plain": [ 516 | " time Timeline n tbe\n", 517 | "0 0.0000 simulation starts 0 1.7949\n", 518 | "1 1.7949 customer 1 arrived 1 0.3545\n", 519 | "2 2.1494 customer 2 arrived 2 0.9150\n", 520 | "3 3.0644 customer 1 left 1 0.0745\n", 521 | "4 3.1389 customer 3 arrived 2 0.4486" 522 | ] 523 | }, 524 | "execution_count": 26, 525 | "metadata": {}, 526 | "output_type": "execute_result" 527 | } 528 | ], 529 | "source": [ 530 | "#show results\n", 531 | "timeline.head()" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 16, 537 | "metadata": {}, 538 | "outputs": [ 539 | { 540 | "data": { 541 | "text/plain": [ 542 | "n\n", 543 | "0 0.325243\n", 544 | "1 0.219846\n", 545 | "2 0.170902\n", 546 | "3 0.105298\n", 547 | "4 0.075201\n", 548 | "5 0.051893\n", 549 | "6 0.023801\n", 550 | "7 0.011716\n", 551 | "8 0.006875\n", 552 | "9 0.003647\n", 553 | "10 0.001898\n", 554 | "11 0.001082\n", 555 | "12 0.000796\n", 556 | "13 0.000399\n", 557 | "14 0.001388\n", 558 | "15 0.000014\n", 559 | "Name: tbe, dtype: float64" 560 | ] 561 | }, 562 | "execution_count": 16, 563 | "metadata": {}, 564 | "output_type": "execute_result" 565 | } 566 | ], 567 | "source": [ 568 | " #computing the probability and time spent of 'n' customers in the system\n", 569 | " \n", 570 | "Pn=timeline.groupby('n').tbe.agg(sum)/sum(t)\n", 571 | "Tn=timeline.groupby('n').tbe.agg('count')\n", 572 | "timeline.groupby('n').tbe.agg(sum)/sum(t)" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": 18, 578 | "metadata": {}, 579 | "outputs": [ 580 | { 581 | "data": { 582 | "image/png": "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\n", 583 | "text/plain": [ 584 | "
" 585 | ] 586 | }, 587 | "metadata": { 588 | "needs_background": "light" 589 | }, 590 | "output_type": "display_data" 591 | }, 592 | { 593 | "data": { 594 | "image/png": "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\n", 595 | "text/plain": [ 596 | "
" 597 | ] 598 | }, 599 | "metadata": { 600 | "needs_background": "light" 601 | }, 602 | "output_type": "display_data" 603 | } 604 | ], 605 | "source": [ 606 | "#plotting results\n", 607 | "plt.figure(figsize=(8,8))\n", 608 | "sns.barplot(x=Pn.index,y=Pn,color='g')\n", 609 | "plt.title('Probability of n customers in the system')\n", 610 | "plt.xlabel('number of customers')\n", 611 | "plt.ylabel('Probability')\n", 612 | "sns.despine()\n", 613 | "plt.show()\n", 614 | "\n", 615 | "plt.figure(figsize=(7,7))\n", 616 | "sns.barplot(['Idle','Occupied'],[Pn[0],1-Pn[0]],color='mediumpurple')\n", 617 | "plt.title('Utilization %')\n", 618 | "plt.xlabel('System state')\n", 619 | "plt.ylabel('Probability')\n", 620 | "sns.despine()\n", 621 | "plt.show()" 622 | ] 623 | }, 624 | { 625 | "cell_type": "code", 626 | "execution_count": 23, 627 | "metadata": {}, 628 | "outputs": [], 629 | "source": [ 630 | "\n", 631 | " #computing expected number of customers in the system\n", 632 | "Ls=(sum(Pn*Pn.index))\n", 633 | " \n", 634 | " #computing expected customers waiting in line\n", 635 | "Lq=sum((Pn.index[c+1:]-1)*(Pn[c+1:]))\n", 636 | " " 637 | ] 638 | }, 639 | { 640 | "cell_type": "code", 641 | "execution_count": 24, 642 | "metadata": {}, 643 | "outputs": [ 644 | { 645 | "name": "stdout", 646 | "output_type": "stream", 647 | "text": [ 648 | "Output: \n", 649 | " Servers : 1 \n", 650 | " Time Between Arrivals : 0.9771710118681556 \n", 651 | " Service Time: (1/µ) 0.6605173880529018 \n", 652 | " Utilization (c): 0.6747568638633048 \n", 653 | " Expected wait time in line (Wq): 1.11596 \n", 654 | " Expected time spent on the system (Ws): 1.7764768999999998 \n", 655 | " Expected number of customers in line (Lq): 1.1409669337718809 \n", 656 | " Expected number of clients in the system (Ls): 1.8157237976351857 \n", 657 | " Expected number of occupied servers : 0.6747568638633048 \n", 658 | "\n" 659 | ] 660 | } 661 | ], 662 | "source": [ 663 | "# Model Results\n", 664 | "print('Output:','\\n',\n", 665 | " 'Servers : '+str(c),'\\n '\n", 666 | " 'Time Between Arrivals : ',str(data.inter_arrival_times.mean()),'\\n',\n", 667 | " 'Service Time: (1/µ)',str(data.service_times.mean()),'\\n'\n", 668 | " ' Utilization (c): ',str((Ls-Lq)/c),'\\n',\n", 669 | " 'Expected wait time in line (Wq):',str(data['wait_times'].mean()),'\\n',\n", 670 | " 'Expected time spent on the system (Ws):',str(data.total_times.mean()),'\\n',\n", 671 | " 'Expected number of customers in line (Lq):',str(Lq),'\\n',\n", 672 | " 'Expected number of clients in the system (Ls):',str(Ls),'\\n '\n", 673 | " 'Expected number of occupied servers :',str(Ls-Lq),'\\n')" 674 | ] 675 | } 676 | ], 677 | "metadata": { 678 | "kernelspec": { 679 | "display_name": "Python 3", 680 | "language": "python", 681 | "name": "python3" 682 | }, 683 | "language_info": { 684 | "codemirror_mode": { 685 | "name": "ipython", 686 | "version": 3 687 | }, 688 | "file_extension": ".py", 689 | "mimetype": "text/x-python", 690 | "name": "python", 691 | "nbconvert_exporter": "python", 692 | "pygments_lexer": "ipython3", 693 | "version": "3.7.6" 694 | } 695 | }, 696 | "nbformat": 4, 697 | "nbformat_minor": 4 698 | } 699 | --------------------------------------------------------------------------------