Lecture 20 (April 4, 2019)¶
In this lecture, we discuss how to model a two-server queueing system in series
In [0]:
import numpy as np
import matplotlib.pyplot as plt
import math
import scipy.special as spsp
import scipy.stats as spst
Setting of two-server queueing system in series¶
(1) Consumers arrive following a specific arrival process.
(2) Consumers will be served by the first server. The service follows first come first serve.
(3) Consumers will then be served by the second server. The service again follows first come first serve.
(4) When a cusomers is served by both servers, the customer leaves the system.
Analaysis of the system¶
Events:
We have three possible events:
A consumer arrives (denote the time using t_arrival)
A consumer finished receiving the service from server 1 (denote the time using t_depart1)
A consumer finished receiving the service from server 2 (denote the time using t_depart2)
The system simulation is moving the clock sequentially to the earliest pending event, update the system state, update the pending event time, and then move to the earliest pending event again.
States
Which variables will lead to change in the event times?
• Number of customers waiting for server 1 ($n_1$):
When $n_1$ is updated to $n_1+1$
The system has an arrival and should be expecting another arrival. Thus, we need to generate a new t_arrival.
If $n_1$ is updated to 1, the new arrival will then immediate recieve the service from server 1. Thus, we should generate a new t_depart1.
When $n_1$ is updated to $n_1-1$
If $n_1$ is updated to 0, we have 0 customers receiving service from server 1. Thus, we will update t_depart1 to np.inf.
If $n_1$ is updated to a positive value, we have another customer receiving service from server 1 immediately. Thus, we will generate a new t_depart1.
In addition, this customer will immediately move to server 2. Thus, we will have $n_2=n_2+1$.
• Number of customers waiting for server 2 ($n_2$):
When $n_2$ is updated to $n_2+1$
If $n_2$ is updated to 1, the new arrival will then immediate recieve the service from server 2. Thus, we should generate a new t_depart2.
When $n_2$ is updated to $n_2-1$
If $n_1$ is updated to 0, we have 0 customers receiving service from server 2. Thus, we will update t_depart2 to np.inf.
If $n_1$ is updated to a positive value, we have another customer receiving service from server 2 immediately. Thus, we will generate a new t_depart2.
Algorithm¶
To put it in another way, we have
**Case 1: arrival event**
clock
t=t_arrival
state variable
$n_1=n_1+1$
event time
generate a new t_arrival
if $n_1==1$, generate a new t_depart1.
**Case 2: departure from server 1**
clock
t=t_depart1
state variable
$n_1=n_1-1$
$n_2=n_2+1$
event time
if $n_1=0$, update t_depart1 to np.inf. Otherwise, generate a new t_depart1
if $n_2=1$, generate a new t_depart2.
**Case 3: departure from server 2**
clock
t=t_depart2
state variable
$n_2=n_2-1$
event time
if $n_2=0$, update t_depart2 to np.inf. Otherwise, generate a new t_depart2.
In [0]:
## Arrival: poisson process with λ=100 for this hour.
## Service: Customers will be served in a counter based on first-come first serve with the service time following exponential distribution with λ=110
## Simulation stops when t>T
## Return the average waiting time for customers who finished receiving the service
def two_server_series():
#initialize clock
t=0
#initialize the states
n1=0
n2=0
#generate the pending event times
lmbda_a=100
lmbda_s1=110
lmbda_s2=110
t_arrival=t-1/lmbda_a*np.log(np.random.rand())
t_depart1=np.inf
t_depart2=np.inf
#other initialization
##Collecting system output (history)
##array to store Arrival times
arrival_times=np.array([])
##array to store Departure times
depart1_times=np.array([]) #We do not need this to compute the average time
depart2_times=np.array([])
#while ( condition to continue the simulation):
while(t<1):
#conditional statement that identifies arrival event happens:
if t_arrival==min(t_arrival,t_depart1,t_depart2):
#update clock
t=t_arrival
#store arrival time (history)
arrival_times=np.append(arrival_times, t)
#update system states
n1=n1+1
#update pending event times
t_arrival=t-1/lmbda_a*np.log(np.random.rand())
if n1==1:
t_depart1=t-1/lmbda_s1*np.log(np.random.rand())
#conditional statement that identifies departure from server 1 happens:
elif t_depart1==min(t_arrival,t_depart1,t_depart2):
#update clock
t=t_depart1
#store departure time (history)
depart1_times=np.append(depart1_times,t)
#update system states
n1=n1-1
n2=n2+1
#update pending event times
if n1==0:
t_depart1=np.inf
else:
t_depart1=t-1/lmbda_s1*np.log(np.random.rand())
if n2==1:
t_depart2=t-1/lmbda_s2*np.log(np.random.rand())
#conditional statement that identifies departure from server 2 happens:
else:
#update clock
t=t_depart2
#store departure time (history)
depart2_times=np.append(depart2_times,t)
#update system states
n2=n2-1
#update pending event times
if n2==0:
t_depart2=np.inf
else:
t_depart2=t-1/lmbda_s2*np.log(np.random.rand())
##when simulation stops, we compute the average time in the system
depart2_times=depart2_times[depart2_times<=1]
arrival_times=arrival_times[0:len(depart2_times)]
avg_time=np.mean(depart2_times-arrival_times)
return avg_time
In [0]:
two_server_series()
Out[0]:
0.07995726646118767
In [0]: