using SimJulia
using Distributions
using RandomStreams
using Distributions
const SEED = 12345
rand_dist(rng::MRG32k3a, Dist::Distribution) = quantile(Dist, rand(rng))
seeds = [SEED, SEED, SEED, SEED, SEED, SEED]
gen = MRG32k3aGen(seeds)
include("tally.jl")
include("tallystore.jl")
println("M/M/1 with processes")
#rates
λ = 1.9
μ = 2.0
ρ = λ/μ
type System
W
arrival
service
counter
arrgen
servgen
function System(text::String)
s = new()
s.W = Tally(text)
s.arrival = Exponential(1.0/λ)
s.service = Exponential(1.0/μ)
s.arrgen = next_stream(gen)
s.servgen = next_stream(gen)
return s;
end
end
function restart(s::System)
init(s.W)
next_substream!(s.arrgen)
next_substream!(s.servgen)
end
function system_set_arrival(s::System, rate::Float64)
s.arrival = Exponential(1.0/rate)
end
function system_set_service(s::System, rate::Float64)
s.service = Exponential(1.0/rate)
end
s = System("Waiting Times")
# Allow a simulation with a fixed number of clients
function source(env::Environment, s::System, limit::Float64)
i = 0
while (true)
yield(Timeout(env, rand_dist(s.arrgen, s.arrival)))
if (now(env) > limit) break end
i += 1
Process(env, customer, s, i)
end
end
function source(env::Environment, s::System, nCusts::Int64)
for i = 1:nCusts
yield(Timeout(env, rand_dist(s.arrgen, s.arrival)))
Process(env, customer, s, i)
end
end
function customer(env::Environment, s::System, idx::Int)
# Record the arrival time in the system
arrive = now(env)
yield(Request(s.counter))
# The simulation clock now contains the time when the client goes to the server.
wait = now(env) - arrive
# Record the waiting time
add(s.W, wait)
yield(Timeout(env, rand_dist(s.servgen, s.service)))
yield(Release(s.counter))
end
function onesim(s::System)
nCustomers = 4000
env = Environment()
s.counter = Resource(env, 1)
Process(env, source, s, nCustomers)
run(env)
end
meanWaits = TallyStore("Average waiting time")
nSims = 100
function simulation(s::System, mw::TallyStore)
for n=1:nSims
restart(s)
onesim(s)
w = average(s.W)
N = nobs(s.W)
add(mw, w)
println("Sim $n. Average waiting time: $w. Number of observations: $N")
end
end
simulation(s, meanWaits)
function ci_normal(n::Int64, mean::Float64, stdev::Float64, α::Float64)
z = quantile(Normal(), 1-α/2)
w = z*stdev/sqrt(n)
# Lower bound
l = mean - w
# Upper bound
u = mean + w
return l, u
end
ci_normal(nobs(meanWaits.t), average(meanWaits.t), stdev(meanWaits.t), 0.05)
function ci_tdist(n::Int64, mean::Float64, stdev::Float64, α::Float64)
z = quantile(TDist(n-1), 1-α/2)
w = z*stdev/sqrt(n)
# Lower bound
l = mean - w
# Upper bound
u = mean + w
return l, u
end
ci_tdist(nobs(meanWaits.t)-1, average(meanWaits.t), stdev(meanWaits.t), 0.05)
Average waiting time according to M/M/1 formulas. In stationnary regime, the mean waiting time is $$ \overline{W} = \frac{\frac{\rho}{\mu}}{1-\rho} = \frac{\rho}{\mu-\lambda}. $$
w = (ρ/μ)/(1-ρ)
meanWaitsFast = TallyStore("Average waiting time in improved system")
μFast = 2.05
ρFast= λ/μFast
wFast = (ρFast/μFast)/(1-ρFast)
system_set_service(s, μFast)
simulation(s, meanWaitsFast)
Δ = Tally("Difference of systems")
for i = 1:nSims
add(Δ, meanWaits.obs[i]-meanWaitsFast.obs[i])
end
ci_tdist(nobs(Δ)-1, average(Δ), stdev(Δ), 0.05)
cor(meanWaits.obs, meanWaitsFast.obs)
reset_stream!(s.arrgen)
reset_stream!(s.servgen)
meanWaitsFast = TallyStore("Average waiting time in improved system")
simulation(s, meanWaitsFast)
Δ = Tally("Difference of systems")
for i = 1:nSims
add(Δ, meanWaits.obs[i]-meanWaitsFast.obs[i])
end
ci_tdist(nobs(Δ)-1, average(Δ), stdev(Δ), 0.05)
cor(meanWaits.obs, meanWaitsFast.obs)
function source_av(env::Environment, s::System, limit::Float64)
i = 0
while (true)
u = rand(s.arrgen)
if (arrival_av)
u = 1-u
end
yield(Timeout(env, quantile(s.arrival, u)))
if (now(env) > limit) break end
i += 1
Process(env, customer_av, s, i)
end
end
function source_av(env::Environment, s::System, nCusts::Int64)
for i = 1:nCusts
u = rand(s.arrgen)
if (arrival_av)
u = 1-u
end
yield(Timeout(env, quantile(s.arrival, u)))
Process(env, customer_av, s, i)
end
end
function customer_av(env::Environment, s::System, idx::Int)
# Record the arrival time in the system
arrive = now(env)
yield(Request(s.counter))
# The simulation clock now contains the time when the client goes to the server.
wait = now(env) - arrive
# Record the waiting time
add(s.W, wait)
u = rand(s.servgen)
if (service_av)
u = 1-u
end
yield(Timeout(env, quantile(s.service, u)))
yield(Release(s.counter))
end
function onesim_av(s::System)
nCustomers = 10000
env = Environment()
s.counter = Resource(env, 1)
Process(env, source_av, s, nCustomers)
run(env)
end
function simulation_av(s::System, mw::TallyStore)
for n=1:nSims
restart(s)
onesim_av(s)
w = average(s.W)
N = nobs(s.W)
add(mw, w)
println("Sim $n. Average waiting time: $w. Number of observations: $N")
end
end
reset_stream!(s.arrgen)
reset_stream!(s.servgen)
system_set_service(s, μ)
arrival_av = false
service_av = false
nSims = 100
meanWaits = TallyStore("Average waiting time")
simulation_av(s, meanWaits)
ci_tdist(nobs(meanWaits.t)-1, average(meanWaits.t), stdev(meanWaits.t), 0.05)
reset_stream!(s.arrgen)
#reset_stream!(s.servgen)
arrival_av = true
service_av = false
meanWaitsAV = TallyStore("Average waiting time - AV")
simulation_av(s, meanWaitsAV)
average(meanWaits.t)
average(meanWaitsAV.t)
mean = (average(meanWaits.t)+average(meanWaitsAV.t))/2
variance(meanWaits.t)
variance(meanWaitsAV.t)
cov(meanWaits.obs, meanWaitsAV.obs)
cor(meanWaits.obs, meanWaitsAV.obs)
σ2 = (variance(meanWaits.t)+variance(meanWaitsAV.t)+2*cov(meanWaits.obs, meanWaitsAV.obs))/4
ci_tdist(2*nSims-1, mean, sqrt(σ2), 0.05)