Skip to content

Commit d739d58

Browse files
committed
Merge branch 'release-0.4' of https://github.com/BenLauwens/SimJulia.jl into release-0.4
2 parents 6d45fe7 + 29af4f0 commit d739d58

5 files changed

Lines changed: 318 additions & 15 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2+
examples/.ipynb_checkpoints
13
docs/build
24
docs/site
35
*.cov

docs/src/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# SimJulia
1+
# Overview
22

3-
a combined continuous time / discrete event process oriented simulation framework written in [Julia](http://julialang.org/) inspired by the Simula library [DISCO](http://www.akira.ruc.dk/~keld/research/DISCO/), the Python library [SimPy](https://simpy.readthedocs.io/) and the standalone [QSS](https://sourceforge.net/projects/qssengine/) solver.
3+
SimJulia is a discrete event process oriented simulation framework written in [Julia](http://julialang.org/) inspired by the Python library [SimPy](https://simpy.readthedocs.io/).
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# A Repair Problem\n",
8+
"Ross, Simulation 5th edition, Section 7.7, p. 124-126"
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"metadata": {},
14+
"source": [
15+
"## Description\n",
16+
"\n",
17+
"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$.\n",
18+
"\n",
19+
"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."
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"metadata": {},
25+
"source": [
26+
"## Install packages"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": null,
32+
"metadata": {
33+
"collapsed": false
34+
},
35+
"outputs": [],
36+
"source": [
37+
"Pkg.update()\n",
38+
"Pkg.add(\"Distributions\")\n",
39+
"Pkg.add(\"SimJulia\")"
40+
]
41+
},
42+
{
43+
"cell_type": "markdown",
44+
"metadata": {},
45+
"source": [
46+
"## Use Distributions.jl and SimJulia.jl"
47+
]
48+
},
49+
{
50+
"cell_type": "code",
51+
"execution_count": 13,
52+
"metadata": {
53+
"collapsed": true
54+
},
55+
"outputs": [],
56+
"source": [
57+
"using Distributions\n",
58+
"using ResumableFunctions\n",
59+
"using SimJulia"
60+
]
61+
},
62+
{
63+
"cell_type": "markdown",
64+
"metadata": {},
65+
"source": [
66+
"## Define constants"
67+
]
68+
},
69+
{
70+
"cell_type": "code",
71+
"execution_count": 14,
72+
"metadata": {
73+
"collapsed": false
74+
},
75+
"outputs": [],
76+
"source": [
77+
"const RUNS = 5\n",
78+
"const N = 10\n",
79+
"const S = 3\n",
80+
"const SEED = 150\n",
81+
"const LAMBDA = 100\n",
82+
"const MU = 1\n",
83+
"\n",
84+
"srand(SEED)\n",
85+
"F = Exponential(LAMBDA)\n",
86+
"G = Exponential(MU);"
87+
]
88+
},
89+
{
90+
"cell_type": "markdown",
91+
"metadata": {},
92+
"source": [
93+
"## Define the behaviour of a machine"
94+
]
95+
},
96+
{
97+
"cell_type": "code",
98+
"execution_count": 15,
99+
"metadata": {
100+
"collapsed": false
101+
},
102+
"outputs": [
103+
{
104+
"data": {
105+
"text/plain": [
106+
"machine (generic function with 1 method)"
107+
]
108+
},
109+
"execution_count": 15,
110+
"metadata": {},
111+
"output_type": "execute_result"
112+
}
113+
],
114+
"source": [
115+
"@resumable function machine(sim::Simulation, repair_facility::Resource, spares::Store{Coroutine})\n",
116+
" while true\n",
117+
" try\n",
118+
" @yield Timeout(sim, Inf)\n",
119+
" catch exc\n",
120+
" end\n",
121+
" #println(\"At time $(now(sim)): $(active_process(sim)) starts working.\")\n",
122+
" @yield Timeout(sim, rand(F))\n",
123+
" #println(\"At time $(now(sim)): $(active_process(sim)) stops working.\")\n",
124+
" get_spare = Get(spares)\n",
125+
" @yield get_spare | Timeout(sim, 0.0)\n",
126+
" if state(get_spare) != SimJulia.idle\n",
127+
" interrupt(value(get_spare))\n",
128+
" else\n",
129+
" throw(SimJulia.StopSimulation(\"No more spares!\"))\n",
130+
" end\n",
131+
" @yield Request(repair_facility)\n",
132+
" #println(\"At time $(now(sim)): $(active_process(sim)) repair starts.\")\n",
133+
" @yield Timeout(sim, rand(G))\n",
134+
" @yield Release(repair_facility)\n",
135+
" #println(\"At time $(now(sim)): $(active_process(sim)) is repaired.\")\n",
136+
" @yield Put(spares, active_process(sim))\n",
137+
" end\n",
138+
"end"
139+
]
140+
},
141+
{
142+
"cell_type": "markdown",
143+
"metadata": {},
144+
"source": [
145+
"## Startup procedure"
146+
]
147+
},
148+
{
149+
"cell_type": "code",
150+
"execution_count": 16,
151+
"metadata": {
152+
"collapsed": false
153+
},
154+
"outputs": [
155+
{
156+
"data": {
157+
"text/plain": [
158+
"start_sim (generic function with 1 method)"
159+
]
160+
},
161+
"execution_count": 16,
162+
"metadata": {},
163+
"output_type": "execute_result"
164+
}
165+
],
166+
"source": [
167+
"@resumable function start_sim(sim::Simulation, repair_facility::Resource, spares::Store{Coroutine})\n",
168+
" procs = Coroutine[]\n",
169+
" for i=1:N\n",
170+
" push!(procs, @coroutine machine(sim, repair_facility, spares))\n",
171+
" end\n",
172+
" @yield Timeout(sim, 0.0)\n",
173+
" for proc in procs\n",
174+
" interrupt(proc)\n",
175+
" end\n",
176+
" for i=1:S\n",
177+
" @yield Put(spares, @coroutine machine(sim, repair_facility, spares))\n",
178+
" end\n",
179+
"end"
180+
]
181+
},
182+
{
183+
"cell_type": "markdown",
184+
"metadata": {},
185+
"source": [
186+
"## One simulation run"
187+
]
188+
},
189+
{
190+
"cell_type": "code",
191+
"execution_count": 17,
192+
"metadata": {
193+
"collapsed": false
194+
},
195+
"outputs": [
196+
{
197+
"data": {
198+
"text/plain": [
199+
"sim_repair (generic function with 1 method)"
200+
]
201+
},
202+
"execution_count": 17,
203+
"metadata": {},
204+
"output_type": "execute_result"
205+
}
206+
],
207+
"source": [
208+
"function sim_repair()\n",
209+
" sim = Simulation()\n",
210+
" repair_facility = Resource(sim)\n",
211+
" spares = Store(Coroutine, sim)\n",
212+
" @coroutine start_sim(sim, repair_facility, spares)\n",
213+
" msg = run(sim)\n",
214+
" stop_time = now(sim)\n",
215+
" println(\"At time $stop_time: $msg\")\n",
216+
" stop_time\n",
217+
"end"
218+
]
219+
},
220+
{
221+
"cell_type": "markdown",
222+
"metadata": {},
223+
"source": [
224+
"## Multiple simulations"
225+
]
226+
},
227+
{
228+
"cell_type": "code",
229+
"execution_count": 18,
230+
"metadata": {
231+
"collapsed": false
232+
},
233+
"outputs": [
234+
{
235+
"name": "stdout",
236+
"output_type": "stream",
237+
"text": [
238+
"At time 5573.772841846017: No more spares!\n",
239+
"At time 1438.0294516073466: No more spares!\n",
240+
"At time 7077.413276961621: No more spares!\n",
241+
"At time 7286.490682742159: No more spares!\n",
242+
"At time 6820.788098062124: No more spares!\n",
243+
"5639.298870243853\n"
244+
]
245+
}
246+
],
247+
"source": [
248+
"results = Float64[]\n",
249+
"for i=1:RUNS\n",
250+
" push!(results, sim_repair())\n",
251+
"end\n",
252+
"println(sum(results)/RUNS)"
253+
]
254+
},
255+
{
256+
"cell_type": "code",
257+
"execution_count": null,
258+
"metadata": {
259+
"collapsed": true
260+
},
261+
"outputs": [],
262+
"source": []
263+
},
264+
{
265+
"cell_type": "code",
266+
"execution_count": null,
267+
"metadata": {
268+
"collapsed": true
269+
},
270+
"outputs": [],
271+
"source": []
272+
}
273+
],
274+
"metadata": {
275+
"kernelspec": {
276+
"display_name": "Julia 0.6.0",
277+
"language": "julia",
278+
"name": "julia-0.6"
279+
},
280+
"language_info": {
281+
"file_extension": ".jl",
282+
"mimetype": "application/julia",
283+
"name": "julia",
284+
"version": "0.6.0"
285+
}
286+
},
287+
"nbformat": 4,
288+
"nbformat_minor": 2
289+
}

src/resources/containers.jl

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@ const Request = Put
3838

3939
Request(res::Resource; priority::Int=0) = Put(res, 1; priority=priority)
4040

41-
macro request(res, req, expr)
42-
esc(quote
43-
$req = Request($res)
44-
$expr
45-
if state($req) == SimJulia.triggered
46-
@yield Release($res)
47-
else
48-
cancel($res, $req)
49-
end
50-
end)
51-
end
52-
5341
function request(func::Function, res::Resource; priority::Int=0)
5442
req = Request(res; priority=priority)
5543
try

test/containers.jl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,28 @@ con = Container(sim, 10.0; level=5.0)
5757
@coroutine my_producer(sim, con)
5858
run(sim)
5959

60-
60+
function source(sim::Simulation, server::Resource)
61+
i = 0
62+
while true
63+
i += 1
64+
yield(Timeout(sim, rand()))
65+
@process customer(sim, server, i)
66+
end
67+
end
68+
69+
function customer(sim::Simulation, server::Resource, i::Int)
70+
request(server) do req
71+
println(now(sim), ", customer $i arrives")
72+
yield(req | Timeout(sim, rand()))
73+
if state(req) != SimJulia.idle
74+
println(now(sim), ", customer $i starts being served")
75+
yield(Timeout(sim, rand()))
76+
end
77+
println(now(sim), ", customer $i leaves")
78+
end
79+
end
80+
81+
sim = Simulation()
82+
server = Resource(sim, 1)
83+
@process source(sim, server)
84+
run(sim, 10.0)

0 commit comments

Comments
 (0)