|
| 1 | +# Ross, Simulation 5th edition: |
| 2 | + |
| 3 | +## A repair problem |
| 4 | + |
| 5 | +### Source |
| 6 | + |
| 7 | +Ross, Simulation 5th edition, Section 7.7, p. 124-126 |
| 8 | + |
| 9 | +### Description |
| 10 | + |
| 11 | +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$. |
| 12 | + |
| 13 | +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. |
| 14 | + |
| 15 | +### Code |
| 16 | + |
| 17 | +```jldoctest |
| 18 | +using Distributions |
| 19 | +using ResumableFunctions |
| 20 | +using SimJulia |
| 21 | +
|
| 22 | +const RUNS = 5 |
| 23 | +const N = 10 |
| 24 | +const S = 3 |
| 25 | +const SEED = 150 |
| 26 | +const LAMBDA = 100 |
| 27 | +const MU = 1 |
| 28 | +
|
| 29 | +srand(SEED) |
| 30 | +const F = Exponential(LAMBDA) |
| 31 | +const G = Exponential(MU) |
| 32 | +
|
| 33 | +@resumable function machine(sim::Simulation, repair_facility::Resource, spares::Store{Process}) |
| 34 | + while true |
| 35 | + try |
| 36 | + @yield Timeout(sim, Inf) |
| 37 | + catch exc |
| 38 | + end |
| 39 | + @yield Timeout(sim, rand(F)) |
| 40 | + get_spare = Get(spares) |
| 41 | + @yield get_spare | Timeout(sim, 0.0) |
| 42 | + state(get_spare) != SimJulia.idle ? interrupt(value(get_spare)) : throw(SimJulia.StopSimulation("No more spares!")) |
| 43 | + @yield Request(repair_facility) |
| 44 | + @yield Timeout(sim, rand(G)) |
| 45 | + @yield Release(repair_facility) |
| 46 | + @yield Put(spares, active_process(sim)) |
| 47 | + end |
| 48 | +end |
| 49 | +
|
| 50 | +@resumable function start_sim(sim::Simulation, repair_facility::Resource, spares::Store{Process}) |
| 51 | + procs = Process[] |
| 52 | + for i=1:N |
| 53 | + push!(procs, @process machine(sim, repair_facility, spares)) |
| 54 | + end |
| 55 | + @yield Timeout(sim, 0.0) |
| 56 | + for proc in procs |
| 57 | + interrupt(proc) |
| 58 | + end |
| 59 | + for i=1:S |
| 60 | + @yield Put(spares, @process machine(sim, repair_facility, spares)) |
| 61 | + end |
| 62 | +end |
| 63 | +
|
| 64 | +function sim_repair() |
| 65 | + sim = Simulation() |
| 66 | + repair_facility = Resource(sim) |
| 67 | + spares = Store{Process}(sim) |
| 68 | + @process start_sim(sim, repair_facility, spares) |
| 69 | + msg = run(sim) |
| 70 | + stop_time = now(sim) |
| 71 | + println("At time $stop_time: $msg") |
| 72 | + stop_time |
| 73 | +end |
| 74 | +
|
| 75 | +results = Float64[] |
| 76 | +for i=1:RUNS |
| 77 | + push!(results, sim_repair()) |
| 78 | +end |
| 79 | +println("Average crash time: ", sum(results)/RUNS) |
| 80 | +
|
| 81 | +# output |
| 82 | +
|
| 83 | +At time 5573.772841846017: No more spares! |
| 84 | +At time 1438.0294516073466: No more spares! |
| 85 | +At time 7077.413276961621: No more spares! |
| 86 | +At time 7286.490682742159: No more spares! |
| 87 | +At time 6820.788098062124: No more spares! |
| 88 | +Average crash time: 5639.298870243853 |
| 89 | +``` |
0 commit comments