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.