all rights reserved
*******************
d e m o s r e f e r e n c e m a n u a l
by
graham birtwistle
computer science, university of bradford
copyright (c) january 1979 by g.m.birtwistle. all
rights reserved. this manual, or parts thereof,
may not be reproduced in any form without written
permission from the author.
it is made available on the strict
understanding that it must not be shown or made
available in any way to p.r.hills, or to any
employee of p.r.hills, or to any employer of
p.r.hills, or to anyone co-operating with him.
chapter 1
introduction
this manual documents the latest version of demos. it is not a
teaching text - for that see simula begin ]2[ and demos ]1[; however
demos ]1[ does not mention many of the features herein outlined.
demos has been implemented as a flat, monolithic context so that
its external declaration is the same for every simula implementation:
external class demos
however it was coded in several logical layers, and a chapter is
devoted to each.
layout of the manual
the rest of chapter 1 introduces it all by giving a demos model
for a reasonably tough problem (another version of this problem is
given in the ecsl manual ]clementson, 3[).
chapter 2 covers the reporting aids class tab and class reportq.
all demos facilities are prefixed by tab which, amongst other things,
allows reportq membership. on generation, each facility object is
entered into a special reportq reserved for its type. for example,
all res objects are entered into resq, all waitq objects into waitqq,
and so on. it is now very easy to write routines to report or reset
each and every facility object created during program execution.
chapter 3 explains the data collection devices - count
(incidences), tally (time independent data), histogram (tally plus a
bar chart), accumulate (time dependent data), and regression (for
linear regressions). each of these classes is prefixed by tab.
chapter 4 outlines the demos random number generators (taken from
downham androberts ]downham, 5[ and its method of generating well
spread seeds (due to ohlin ]ohlin, 7[). well spread seeds are dealt
with in 4.1; dist, the prefix to all distribution objects, in 4.2;
distributions producing real results (constant, empirical, erlang,
negexp, normal, and uniform) in 4.3; distributions producing integer
1introduction page 1-2
results (poisson, randint) in 4.4; and distributions producing
boolean results (draw) in 4.5. 4.6 outlines readdist, a global
routine for creating distributions from descriptions supplied on inf.
chapter 5 documents class entity and its local scheduling
routines. demos implements its own event list as a leftist priority
tree. this is mainly for pedagogic reasons, but it doesn't degrade
performance by much. should you wish to alter the event list
strategy, e.g. by introducing priorities (this is given as an example
on page 5-14), it is now much easier.
chapter 6 outlines the global scheduling routines hold,
passivate; also time.
chapter 7 documents the queueing facilities. only demos entities
may be queued; if you wish to queue other items, you will either have
to write the routines yourself or use simset (demos doesn't). the
types of queue implemented are: queue (usually for holding several
coopted entities until they are required by their masters) in 7.1;
waitq (master/slave synchronisation) in 7.2; and condq (waits until)
in 7.3.
chapter 8 documents resource and its subclasses res (for the
mutual exclusion synchronisation); and bin (for the producer/consumer
synchronisation).
chapter 9 clears up most of the remaining odds and ends; the
underlying reporting aids, tracing, error messages, report and reset,
queue and event list snapping, and epsilon - the grain of time.
chapter 10 documents the demos prefix; the variables it contains
and the prefix initialising and finalising actions.
the last chapter, chapter 11, explains how to redirect the
standard input file inf and output file outf.
finally, there are the references; three appendices giving an
indented listing of the demos source (appendix a), a set of 21 sample
programs (appendix b); their automatic reports (appendix c); and at
the very end, the index.
1introduction page 1-3
worked example
production line
a factory has one entrance guarded by a weighbridge over which all
incoming and outgoing vehicles must pass. only one vehicle can move
in this area at a time.
aluminium sheets are delivered to the factory in vans. the
sheets are fed onto production lines, formed into cans, filled, capped
and then placed in containers. the containers are removed by lorries.
the vans arrive at the factory periodically. once across the
weighbridge (which takes two minutes in or out), each van goes to the
rear of the factory to an unloading area where its load is removed
with the assistance of a crane. the load of aluminium sheets fills
three empty hoppers one by one. (full hoppers are then fitted onto
the production lines.) each van then leaves, again passing over the
weighbridge. to prevent congestion, at most four vans are allowed in
the factory grounds at a time.
a pool of seven vans serves the factory. a res 'vanspaces' is
used to limit the number in the factory grounds to 4 at any one time.
unloading takes place when the crane and empty hoppers are available
(an unloading, which fills three hoppers, may start even if only one
or two are free; but the crane is only released by its owning van
when three hoppers have been filled. the filling of each hopper takes
about 5 minutes (normal, mean = 5, standard deviation = 1). after
exiting, the van returns with a new load in about 108 minutes (98 +
negexp(0.1)).
n.b. all the simulation timings are given in minutes.
1introduction page 1-4
resource diagram for class van
------------<-----------------------
! !
! ----------<---------------- !
! ! ! !
! ! --------<--------- ! !
! ! ! ! ! !
---------- ! ! !
! enter ! ! ! !
---------- ! ! !
! ! ! ! !
! -------->------- ! ! !
! ! ! ! !
! ----<---- ! ! ! !
! ! ! ! ! ! !
---------- ! ! ! ! !
! get ! ! ! ! ! !
! crane ! ! ! ! ! !
---------- ! ! ! ! !
! ! ! ! ! !
! ! ! ! ! !
---->---- ! --<-- ! ! ! ! !
! ! ! ! ! ! ! ! ! !
empty ! ! ---------- ! +++ +++ +++ !
hoppers! 5 ! ! unload ! ! + 1 + + 1 + + 4 + !
----- ---------- ! +++ +++ +++ !
! ! ! ! crane weigh- van !
----<---- ! ----- ! bridge spaces !
! ! ! ! ! ! !
full ! ! ---------- ! ! ! ! !
hoppers! 3 ! ! return ! ! ! ! ! !
----- ! crane ! ! ! ! ! !
---------- ! ! ! ! !
! ! ! ! ! ! !
! ---->---- ! ! ! !
! ! ! ! !
! --------<------- ! ! !
! ! ! ! !
---------- ! ! !
! leave ! ! ! !
---------- ! ! !
! ! ! ! ! !
! ! -------->--------- ! !
! ! ! !
! ---------->---------------- !
! !
------------>-----------------------
1introduction page 1-5
entity class van;
begin
integer k;
enter:
vanspaces.acquire(1);
weighbridge.acquire(1);
hold(2.0);
weighbridge.release(1);
unload:
crane.acquire(1);
for k := 1 step 1 until 3 do
begin
emptyhoppers.take(1);
hold(fill.sample);
fullhoppers.give(1);
end;
crane.release(1);
leave:
weighbridge.acquire(1);
hold(2.0);
weighbridge.release(1);
vanspaces.release(1);
nextload:
hold(98.0 + nexttrip.sample);
repeat;
end***van***;
a full hopper fits onto a production line (of which there are five).
the aluminium sheets are removed from the hopper and processed one by
one. as the sheets pass down the line, they are formed into cans,
filled with liquid x and capped. it takes two hoppers to fill one
container. if all goes smoothly, the processing time per hopper is 25
minutes.
the containers are loaded onto articulated trucks. the trucks
wait outside the factory until a loading bay is free. they take three
minutes to cross the weighbridge (in and out) and then manoeuvre into
a loading bay. when the lorry is loaded, it departs via the
weighbridge.
lorries arrive roughly every 10 minutes (negexp(1/10)). they
enter the factory grounds when they have a bay (there are 6 bays in
the model) and the weighbridge. once in, they accept two containers
and then leave.
1introduction page 1-6
resource diagram for class lorry
----->------ ------<-----
! ! ! !
! --------- !
! ! enter ! !
! --------- !
! ! ! !
! ! ------>--- !
! ! ! !
! *** ! !
! *** bayq ! !
! *** ! !
! ! !
+++ +++ weigh-
+ 6 + bays + 1 +
+++ +++ bridge
! ! !
! ! !
! ! !
! ! !
! ------<--- !
! ! !
! --------- !
! ! leave ! !
! --------- !
! ! ! !
-----<------ ------>-----
entity class lorry;
begin
new lorry("lorry").schedule(nextlorry.sample);
enter:
bays.acquire(1);
weighbridge.acquire(1);
hold(3.0);
weighbridge.release(1);
load:
bayq.wait;
exit:
weighbridge.acquire(1);
hold(3.0);
weighbridge.release(1);
bays.release(1);
end***lorry***;
when a hopper is put on the line, the plant starts producing cans.
the first can is ready ten minutes later. if there is no waiting
container, production is halted but can continue without penalty when
one arrives. after a further fifteen minutes, the hopper has to be
replaced with another possible production line halt. twenty five
1introduction page 1-7
minutes later the second hopper will have been emptied, but the last
can will not arrive at the end of the production line until another
five minutes have elapsed.
a second container load can be started on the production line
immediately after the first if required, there being no need to wait
for the final can of the first load to be ready before the first can
of the second can be started.
resource diagram for class production
--------------<-------------
! !
! ------<---- !
! ! ! !
--------------- ! !
! start first ! ! !
! batch ! ! !
bayq --------------- ! !
*** coopt a ! ! !
***========== ! ! !
*** lorry " ! ! !
" ! ! !
" ! --<-- ! !
--------------- ! ! ! !
! load and ! ! ! Full !
! continue ! ! ! 3 Hoppers !
--------------- ! ----- !
! ! ! !
----<------ ! ! !
! ! ! !
! --<-- ! --<-- !
! ! ! ! ! !
! ! ! --------------- !
! 5 ! ! ! second ! !
----- ! ! batch ! !
empty ! --------------- !
hoppers ! ! " ! !
--<-- " ! !
" ! !
schedule " ! !
<=========== -------------->-------------
lorry l.
1introduction page 1-8
entity class production;
begin
ref(lorry)l;
firsthopper:
fullhoppers.take(1);
hold(10.0);
findtruck:
l :- bayq.coopt;
hold(15.0);
emptyhoppers.give(1);
secondhopper:
fullhoppers.take(1);
hold(25.0);
emptyhoppers.give(1);
l.schedule(10.0);
repeat;
end***production line***;
the driving program reads:
begin
external class demos;
demos
begin
ref(rdist)nextlorry, fill, nexttrip;
ref(res)weighbridge, crane, bays, vanspaces;
ref(bin)fullhoppers, emptyhoppers;
ref(waitq)bayq;
entity class van.............;
entity class lorry...........;
entity class production......;
integer k;
nextlorry :- new negexp("next lorry", 0.05);
fill :- new normal("fill hopper", 5.0, 1.0);
nexttrip :- new negexp("van return", 0.1);
weighbridge :- new res("weighbridge", 1);
crane :- new res("crane", 1);
bays :- new res("bays", 6);
vanspaces :- new res("van spaces", 4);
bayq :- new waitq("await container");
fullhoppers :- new bin("full hoppers", 3);
emptyhoppers :- new bin("empty hoppers", 5);
new lorry("l").schedule(0.0);
for k := 1 step 1 until 7 do
new van("v").schedule((k-1)*14);
for k := 1 step 1 until 5 do
new production("p-line").schedule(0.0);
hold(480.0);
end;
end;
1introduction page 1-9
the automatic demos report
clock time = 480.000
**********************************************************************
* *
* r e p o r t *
* *
**********************************************************************
d i s t r i b u t i o n s
*************************
title / (re)set/ obs/type / a/ b/ seed
next lorry 0.000 41 negexp 0.100 33427485
fill hopper 0.000 74 normal 5.000 1.000 22276755
van return 0.000 24 negexp 0.100 46847980
r e s o u r c e s
*****************
title / (re)set/ obs/ lim/ min/ now/ % usage/ av. wait/qmax
weighbridge 0.000 121 1 0 1 65.417 1.168 4
crane 0.000 24 1 0 0 81.393 8.943 2
bays 0.000 33 6 0 0 88.570 12.900 4
van spaces 0.000 24 4 0 3 40.525 0.000 1
b i n s
*******
title / (re)set/ obs/init/ max/ now/ av. free/ av. wait/qmax
full hoppers 0.000 73 3 3 0 0.516 5.477 5
empty hopper 0.000 71 5 8 2 2.571 0.219 1
w a i t q u e u e s
*********************
title / (re)set/ obs/ qmax/ qnow/ q average/zeros/ av. wait
await contai 0.000 38 4 0 0.315 27 3.977
await contai* 0.000 38 3 1 0.578 12 6.743
program execution time 2.94 seconds (5 garbage collections took 0.460
seconds). run on 1979/1/20.
1 chapter 2
classes tab and reportq
to enable automatic reporting, user-generated data collection devices,
random number generators, queues, and resources are individually
placed into special reportqs on creation. each such type of demos
facility is prefixed by tab which gives its objects the capability of
joining a reportq.
-----------
! reportq !
!---------!
! last --!---------------------->---------------
! first --!---->---- !
! report ! ! !
! reset ! ! !
----------- ---------- ---------- ----------
! tab ! ! tab ! ! tab !
!--------! !--------! !--------!
! next -!--->! next -!--->! next !
! report ! ! report ! ! report !
! reset ! ! reset ! ! reset !
---------- ---------- ----------
reportq with three tabs
each type of demos facility has its own special reportq:
accumq - for accumulate objects
binq - for bin objects
condqq - for condq objects
countq - for count objects
distq - for rdist (except empirical), idist, and bdist objects
empq - for empirical objects
queueq - for queue objects
regressq - for regression objects
resq - for res objects
tallyq - for tally objects
waitqq - for waitq objects
1classes tab and reportq page 2-2
and on creation, each tab object enters the appropriate reportq at the
end (as its new last).
given ref(tab)t and ref(reportq)r, t.report prints the current
status of t on the next line of outf, r.report prints the current
status of each of its tab members on successive lines (from first
through to last, i.e. the order in which they were created). the
global routine report goes through the demos defined reportq's one by
one and reports them if they are not empty. the algorithm is:
]ref(reportq)q;[
for q :- distq, empq, accumq, ... , condqq do
if q.first =/= none then
begin
2 new lines;
q.report;
end;
(the mechanism for the global routine reset is very similar). report
is called automatically by the system when closing down a simulation
unless switched off by a call on noreport.
1classes tab and reportq page 2-3
2.1 class tab
class tab is used as prefix to data collection devices (count, tally,
accumulate, regression, and histogram), random stream generators
(constant, empirical, erlang, negexp, normal, uniform, poisson,
randint, and draw), resources (res and bin), and queues (queue, condq,
and waitq). its main function is to define the common portion of its
sub-classes: namely a distinguishing title, the capability of being
chained in a reportq, a primitive reset routine, a primitive report
routine, and writetrn - the common portion of their report routines.
tab
!
!
-----------------------------------------------
! ! ! !
! ! ! !
data collection queues resources random number
devices generators
chapter 3 chapter 7 chapter 8 chapter 4
tab object : new tab("stream");
-------------------
! tab !
-------------------
! title "stream" !
! obs 0 !
! resetat 0.0 !
! next none !
! join(r) !
! report !
! reset !
! writetrn !
-------------------
outline
class tab(title); value title; text title;
virtual: procedure report, reset;
begin
integer obs;
real resetat;
ref(tab)next;
procedure join(r); ref(reportq)r;
procedure report;
procedure reset;
procedure writetrn;
1classes tab and reportq page 2-4
actions:
if title.length 12 then title :- title.sub(1,12);
reset;
end***tab***;
actions
the actions of the class body curtail the length of title to 12
characters should it be longer, and call reset (remember that this is
virtual). reset sets resetat to the current clock time (= object
creation time in the first instance), and sets obs to zero.
attributes
text title is a user-supplied descriptive text, cut off at 12
characters if initially longer.
integer obs records the number of observations (since resetat).
real resetat initially records the time of creation of the
object. it is updated to the current clock time by each call on
reset. it reflects the start of the time interval over which
observations have been collected.
ref(tab)next points to the next tab in this tab's reportq.
procedure join(r) places the tab object into the named reportq as
last object in that reportq.
procedure report sends one line to outf. it simply calls
writetrn and then outf.outimage. it is redefined in each demos
sub-class of tab.
procedure reset sets obs to zero and resetat to time. this reset
is usually redefined in a sub-class and reinitialises the object so
that data collection etc. can start again over a fresh time period.
this is useful for erasing results gathered during a 'cold start', or
when results are to be tabulated over successive time periods. it is
specified as virtual to enable easy redefinition and to simplify the
writing of the routine reset local to class reportq.
procedure writetrn writes (to the standard outfile outf) a part
line containing the tab's title (columns 1-12), reset time (resetat,
columns 14-23), and the number of observations recorded since resetat
(obs, columns 24-30). resetat is usually printed fixed point, but
should its value be very small (less than 0.1) or too large (=
1000000.0) to fit into columns 14-23 in the chosen format, it is
printed floating point.
1classes tab and reportq page 2-5
2.2 class reportq
reportq objects are used to chain together like tab objects created by
the user. the following reportqs are generated by demos:
accumq - for accumulate objects
binq - for bin objects
condqq - for condq objects
countq - for count objects
distq - for rdist (except empirical), idist, and bdist objects
empq - for empirical objects
queueq - for queue objects
regressq - for regression objects
resq - for res objects
tallyq - for tally objects
waitqq - for waitq objects
each time a fresh (sub-class of) tab object is created, it is
entered into the appropriate reportq at the end. thus these objects
will be reported in the order of their creation.
reportq essentially contains a linked list for tab objects and
two routines reset and report, each of which scans the list tab object
by tab object and calls the local reset or report routine belonging to
the currently referenced tab object.
reportq object : new reportq("tab", x, y);
-------------------
! reportq !
!-----------------!
! h "tab" !
! l1 == x !
! l2 == y !
! first !
! last !
! report !
! reset !
-------------------
1classes tab and reportq page 2-6
outline
class reportq(h, l1, l2); value h; text h, l1, l2;
begin
ref(tab)first, last;
procedure report;
procedure reset;
end***reportq***;
actions
none.
attributes
text h, text l1, and text l2 provide the headings for the actual
reports (see also report below).
ref(tab)first references none (the reportq is empty) or the first
tab in the reportq.
ref(tab)last references none (the reportq is empty) or the last
tab in the reportq.
procedure report prints out a centred heading (h) underlined by
asterisks, followed by a line consisting of l1 concatenated with l2.
thereunder follow the individual tab reports usually line by line (the
exceptions are histoq, empq, and waitqq).
procedure reset moves along the tabs, one by one one, and calls
the reset procedure of each.