# A Repair Problem

Ross, Simulation 5th edition, Section 7.7, p. 124-126

## Description

A system needs \$n\$ working machines to be operational. To guard against machine breakdown, additional machines are kept available as spares. Whenever a machine breaks down it is immediately replaced by a spare and is itself sent to the repair facility, which consists of a single repairperson who repairs failed machines one at a time. Once a failed machine has been repaired it becomes available as a spare to be used when the need arises. All repair times are independent random variables having the common distribution function \$G\$. Each time a machine is put into use the amount of time it functions before breaking down is a random variable, independent of the past, having distribution function \$F\$.

The system is said to “crash” when a machine fails and no spares are available. Assuming that there are initially \$n + s\$ functional machines of which \$n\$ are put in use and \$s\$ are kept as spares, we are interested in simulating this system so as to approximate \$E[T]\$, where \$T\$ is the time at which the system crashes.

## Install packages

``````

In [ ]:

Pkg.update()

``````

## Use Distributions.jl and SimJulia.jl

``````

In [1]:

using Distributions
using ResumableFunctions
using SimJulia

``````

## Define constants

``````

In [2]:

const RUNS = 5
const N = 10
const S = 3
const SEED = 150
const LAMBDA = 100
const MU = 1

srand(SEED)
const F = Exponential(LAMBDA)
const G = Exponential(MU);

``````

## Define the behaviour of a machine

``````

In [3]:

@resumable function machine(sim::Simulation, repair_facility::Resource, spares::Store{Process})
while true
try
@yield timeout(sim, Inf)
catch exc
end
#println("At time \$(now(sim)): \$(active_process(sim)) starts working.")
@yield timeout(sim, rand(F))
#println("At time \$(now(sim)): \$(active_process(sim)) stops working.")
get_spare = get(spares)
@yield get_spare | timeout(sim, 0.0)
if state(get_spare) != SimJulia.idle
interrupt(value(get_spare))
else
throw(SimJulia.StopSimulation("No more spares!"))
end
@yield request(repair_facility)
#println("At time \$(now(sim)): \$(active_process(sim)) repair starts.")
@yield timeout(sim, rand(G))
@yield release(repair_facility)
#println("At time \$(now(sim)): \$(active_process(sim)) is repaired.")
@yield put(spares, active_process(sim))
end
end

``````
``````

Out[3]:

machine (generic function with 1 method)

``````

## Startup procedure

``````

In [4]:

@resumable function start_sim(sim::Simulation, repair_facility::Resource, spares::Store{Process})
procs = Process[]
for i=1:N
push!(procs, @process machine(sim, repair_facility, spares))
end
@yield timeout(sim, 0.0)
for proc in procs
interrupt(proc)
end
for i=1:S
@yield put(spares, @process machine(sim, repair_facility, spares))
end
end

``````
``````

Out[4]:

start_sim (generic function with 1 method)

``````

## One simulation run

``````

In [5]:

function sim_repair()
sim = Simulation()
repair_facility = Resource(sim)
spares = Store{Process}(sim)
@process start_sim(sim, repair_facility, spares)
msg = run(sim)
stop_time = now(sim)
println("At time \$stop_time: \$msg")
stop_time
end

``````
``````

Out[5]:

sim_repair (generic function with 1 method)

``````

## Multiple simulations

``````

In [6]:

results = Float64[]
for i=1:RUNS
push!(results, sim_repair())
end
println("Average crash time: ", sum(results)/RUNS)

``````
``````

At time 5573.772841846017: No more spares!
At time 1438.0294516073466: No more spares!
At time 7077.413276961621: No more spares!
At time 7286.490682742159: No more spares!
At time 6820.788098062124: No more spares!
Average crash time: 5639.298870243853

``````
``````

In [ ]:

``````