This code simulates the continuous time Markov chain associated to a M/M/K/K queue and prints the proportion of time where all servers are occupied (the blocking probability). This is compared with the one obtained by the Erlang B formula.
knitr::opts_chunk$set(echo = TRUE)
set.seed(17); # Set seed for reproducibility
N=1e5; # number of events to simulate;
K=10; # number of servers
lambda=0.6*K; # arrival rate
mu=1; # service rate
p_blocking=0; # blocking probability
p_blocking_transient=rep(N, 0); # transient blocking probability
T=0; # simulation time
state=0;
for (i in 1:N) {
U=lambda+state*mu;
time_in_state=rexp(1,U)
T=T+time_in_state;
if (state==K) {
# For the moment, let us find the overall time spent in state K
p_blocking=p_blocking+time_in_state;
}
p_blocking_transient[i]=p_blocking/T;
if (runif(1)<lambda/U){
# An arrival occurred
if (state<K){
# The incoming job has room so it is accepted
state=state+1;
}
} else {
# A departure occurred
state=state-1;
}
}
# The blocking probability by simulation
p_blocking=p_blocking/T;
# The blocking probability by theory (The Erlang B formula)
p_blocking_theory=0;
normalizing_constant=0;
for (i in 0:K){
normalizing_constant = normalizing_constant + (lambda/mu)**i / factorial(i);
}
p_blocking_theory = (lambda/mu)**K / factorial(K);
p_blocking_theory = p_blocking_theory / normalizing_constant;
# Print the blocking probabilities (simulation and theory)
events=1:N;
plot(events, p_blocking_transient, type = "l", lty = 1)
abline(h = p_blocking_theory, col="red")
print(p_blocking)
## [1] 0.0423121
print(p_blocking_theory)
## [1] 0.04314184
This code simulates again the continuous time Markov chain associated to a M/M/K/K queue as above but in aslightl different (equivalent) manner – code written in class on March 18, 2022.
knitr::opts_chunk$set(echo = TRUE)
set.seed(17); # Set seed for reproducibility
N=1e5; # number of events to simulate;
K=10; # number of servers
lambda=0.6*K; # arrival rate
mu=1; # service rate
p_blocking=0; # blocking probability with T
p_blocking_transient=rep(N, 0); # transient blocking probability
p_blocking_theory=0;
T=0; # simulation time
state=0;
for (i in 1:N) {
A=rexp(1,lambda); # Time to next job arrival
D=A+1;
if (state>0){
D=rexp(1,mu*state); # Time to next service completion
}
T=T+min(A,D); # time after i events
# state is updated here
if (state==K){
p_blocking=p_blocking+min(A,D);
}
p_blocking_transient[i]=p_blocking/T;
if(A>D){
if (state>0){
state=state-1;
}
} else {
if (state<K){
state=state+1;
}
}
}
p_blocking=p_blocking/T;
rho=lambda/mu; normalizing_costant=0;
for (i in 0:K){
normalizing_costant = normalizing_costant + rho**i/factorial(i);
}
p_blocking_theory=rho**K/factorial(K);
p_blocking_theory=p_blocking_theory/normalizing_costant;
print(p_blocking)
## [1] 0.04463967
print(p_blocking_theory)
## [1] 0.04314184
events=1:N;
plot(events, p_blocking_transient, type = "l", lty = 1)
abline(h = p_blocking_theory, col="red")