MODULE BankCRN; IMPORT SIM, EVENT, STAT, LIST; FROM EVENT IMPORT EventType, EventNotice, CancelNotice, NoticeTime, Schedule, ScheduleNotice; FROM RAND IMPORT Uniform01, InitGenerator, SeedType; FROM RAND1 IMPORT Expon; FROM NUM IMPORT LIToLR; CONST Minute = 1.0 / 60.0; (* One minute. *) VAR D, U : LONGREAL; (* Buffers. *) NTellers : LONGINT; (* Number of tellers. *) NBusy : LONGINT; (* Nb. of tellers busy. *) NWait : LONGINT; (* Nb. of customers waiting. *) NextArriv : EventNotice; (* Next arrival. *) Rep : LONGINT; (* Current replication. *) AvDelay : LONGREAL; (* Average interarrival time. *) NServed : LONGINT; (* Nb. served today. *) NServedA : LONGINT; MeanExp : LONGREAL; (* Half the mean of the Erlang. *) StatDiff : STAT.Block; E9h45, E10h, E11h, E14h, E15h, Arrival, Departure : EventType; PROCEDURE Proc9h45; BEGIN NTellers := 0; NBusy := 0; NWait := 0; NServed := 0; AvDelay := 2.0 * Minute; ScheduleNotice (Arrival, Expon (AvDelay, 1), NIL, NextArriv); END Proc9h45; PROCEDURE Proc10h; BEGIN U := Uniform01 (3); NTellers := 3; IF U < 0.2 THEN NTellers := 2; IF U < 0.05 THEN NTellers := 1 END END; WHILE ((NWait > 0) AND (NBusy < NTellers)) DO INC (NBusy); DEC (NWait); Schedule (Departure, Expon (MeanExp, 2) + Expon (MeanExp, 2), NIL); END END Proc10h; PROCEDURE Proc11h; BEGIN D := NoticeTime (NextArriv) - SIM.Time (); CancelNotice (NextArriv); ScheduleNotice (Arrival, D / 2.0, NIL, NextArriv); AvDelay := Minute END Proc11h; PROCEDURE Proc14h; BEGIN D := NoticeTime (NextArriv) - SIM.Time (); CancelNotice (NextArriv); ScheduleNotice (Arrival, 2.0 * D, NIL, NextArriv); AvDelay := 2.0 * Minute END Proc14h; PROCEDURE Proc15h; BEGIN CancelNotice (NextArriv) END Proc15h; PROCEDURE Balk () : BOOLEAN; VAR n : CARDINAL; BEGIN RETURN ((NWait > 9) OR ((NWait > 5) AND (5.0 * Uniform01 (4) < LIToLR (NWait - 5)))) END Balk; PROCEDURE ProcArrival; BEGIN ScheduleNotice (Arrival, Expon (AvDelay, 1), NIL, NextArriv); IF NBusy < NTellers THEN INC (NBusy); Schedule (Departure, Expon (MeanExp, 2) + Expon (MeanExp, 2), NIL); ELSE IF NOT Balk () THEN INC (NWait) END END END ProcArrival; PROCEDURE ProcDeparture; BEGIN INC (NServed); IF NWait > 0 THEN DEC (NWait); Schedule (Departure, Expon (Minute, 2) + Expon (Minute, 2), NIL) ELSE DEC (NBusy) END END ProcDeparture; PROCEDURE SimulOneDay; BEGIN SIM.Init; Schedule (E9h45, 9.75, NIL); Schedule (E10h, 10.0, NIL); Schedule (E11h, 11.0, NIL); Schedule (E14h, 14.0, NIL); Schedule (E15h, 15.0, NIL); SIM.Start; END SimulOneDay; BEGIN EVENT.Create (E9h45, Proc9h45, 'Customers start arriving'); EVENT.Create (E10h, Proc10h, 'Bank opening'); EVENT.Create (E11h, Proc11h, '11 hours'); EVENT.Create (E14h, Proc14h, '14 hours'); EVENT.Create (E15h, Proc15h, 'Bank closing'); EVENT.Create (Arrival, ProcArrival, "Arrival of a customer"); EVENT.Create (Departure, ProcDeparture, "Departure of a customer"); STAT.Create (StatDiff, STAT.Tally, 'Diff. on nb. served per day'); FOR Rep := 1 TO 50 DO InitGenerator (1, NewSeed); InitGenerator (2, NewSeed); InitGenerator (3, NewSeed); InitGenerator (4, NewSeed); MeanExp := 1.0; SimulOneDay; NServedA := NServed; InitGenerator (1, LastSeed); InitGenerator (2, LastSeed); InitGenerator (3, LastSeed); InitGenerator (4, LastSeed); MeanExp := 0.9; SimulOneDay; STAT.Update (StatDiff, LIToLR (NServedA - NServed)); END; STAT.Report (StatDiff); END BankCRN.