2 (* BANK DEPARTMENT SERVICE SIMULATION *)
6 UNIT PRIORITYQUEUE: CLASS;
7 (* HEAP AS BINARY LINKED TREE WITH FATHER LINK*)
11 UNIT QUEUEHEAD: CLASS;
12 (* HEAP ACCESING MODULE *)
15 UNIT MIN: FUNCTION: ELEM;
17 IF ROOT=/= NONE THEN RESULT:=ROOT.EL FI;
20 UNIT INSERT: PROCEDURE(R:ELEM);
21 (* INSERTION INTO HEAP *)
27 ROOT.LEFT,ROOT.RIGHT,LAST:=ROOT
51 UNIT DELETE: PROCEDURE(R: ELEM);
71 IF X.LESS(X.UP) THEN CALL CORRECT(X.EL,FALSE)
72 ELSE CALL CORRECT(X.EL,TRUE) FI;
75 UNIT CORRECT: PROCEDURE(R:ELEM,DOWN:BOOLEAN);
76 (* CORRECTION OF THE HEAP WITH STRUCTURE BROKEN BY R *)
77 VAR X,Z:NODE,T:ELEM,FIN,LOG:BOOLEAN;
82 IF Z.NS =0 THEN FIN:=TRUE ELSE
83 IF Z.NS=1 THEN X:=Z.LEFT ELSE
84 IF Z.LEFT.LESS(Z.RIGHT) THEN X:=Z.LEFT ELSE X:=Z.RIGHT
86 IF Z.LESS(X) THEN FIN:=TRUE ELSE
97 IF X=NONE THEN LOG:=TRUE ELSE LOG:=X.LESS(Z); FI;
106 IF X=NONE THEN LOG:=TRUE ELSE LOG:=X.LESS(Z);
115 UNIT NODE: CLASS (EL:ELEM);
116 (* ELEMENT OF THE HEAP *)
117 VAR LEFT,RIGHT,UP: NODE, NS:INTEGER;
118 UNIT LESS: FUNCTION(X:NODE): BOOLEAN;
120 IF X= NONE THEN RESULT:=FALSE
121 ELSE RESULT:=EL.LESS(X.EL) FI;
126 UNIT ELEM: CLASS(PRIOR:REAL);
127 (* PREFIX OF INFORMATION TO BE STORED IN NODE *)
129 UNIT VIRTUAL LESS: FUNCTION(X:ELEM):BOOLEAN;
131 IF X=NONE THEN RESULT:= FALSE ELSE
132 RESULT:= PRIOR< X.PRIOR FI;
135 LAB:= NEW NODE(THIS ELEM);
143 UNIT SIMULATION: PRIORITYQUEUE CLASS;
144 (* THE LANGUAGE FOR SIMULATION PURPOSES *)
146 VAR CURR: SIMPROCESS, (*ACTIVE PROCESS *)
147 PQ:QUEUEHEAD, (* THE TIME AXIS *)
151 UNIT SIMPROCESS: COROUTINE;
152 (* USER PROCESS PREFIX *)
153 VAR EVENT, (* ACTIVATION MOMENT NOTICE *)
154 EVENTAUX: EVENTNOTICE,
155 (* THIS IS FOR AVOIDING MANY NEW CALLS AS AN RESULT OF *)
156 (* SUBSEQUENT PASSIVATIONS AND ACTIVATIONS *)
159 UNIT IDLE: FUNCTION: BOOLEAN;
161 RESULT:= EVENT= NONE;
164 UNIT TERMINATED: FUNCTION :BOOLEAN;
169 UNIT EVTIME: FUNCTION: REAL;
170 (* TIME OF ACTIVATION *)
172 IF IDLE THEN CALL ERROR1;
174 RESULT:= EVENT.EVENTTIME;
177 UNIT ERROR1:PROCEDURE;
180 WRITELN(" AN ATTEMPT TO ACCESS AN IDLE PROCESS TIME");
183 UNIT ERROR2:PROCEDURE;
186 WRITELN(" AN ATTEMPT TO ACCESS A TERMINATED PROCESS TIME");
198 UNIT EVENTNOTICE: ELEM CLASS;
199 (* A PROCESS ACTIVATION NOTICE TO BE PLACED ONTO THE TIME AXIS PQ *)
200 VAR EVENTTIME: REAL, PROC: SIMPROCESS;
202 UNIT VIRTUAL LESS: FUNCTION(X: EVENTNOTICE):BOOLEAN;
203 (* OVERWRITE THE FORMER VERSION CONSIDERING EVENTTIME *)
205 IF X=NONE THEN RESULT:= FALSE ELSE
206 RESULT:= EVENTTIME< X.EVENTTIME OR
207 (EVENTTIME=X.EVENTTIME AND PRIOR< X.PRIOR); FI;
213 UNIT MAINPROGRAM: SIMPROCESS CLASS;
214 (* IMPLEMENTING MASTER PROGRAM AS A PROCESS *)
219 UNIT TIME:FUNCTION:REAL;
220 (* CURRENT VALUE OF SIMULATION TIME *)
222 RESULT:=CURRENT.EVTIME
225 UNIT CURRENT: FUNCTION: SIMPROCESS;
226 (* THE FIRST PROCESS ON THE TIME AXIS *)
231 UNIT SCHEDULE: PROCEDURE(P:SIMPROCESS,T:REAL);
232 (* ACTIVATION OF PROCESS P AT TIME T AND DEFINITION OF "PRIOR"- PRIORITY *)
233 (* WITHIN TIME MOMENT T *)
235 IF T<TIME THEN T:= TIME FI;
236 IF P=CURRENT THEN CALL HOLD(T-TIME) ELSE
237 IF P.IDLE AND P.EVENTAUX=NONE THEN (* HAS NOT BEEN SCHEDULED YET*)
238 P.EVENT,P.EVENTAUX:= NEW EVENTNOTICE(RANDOM);
241 IF P.IDLE (* P HAS ALREADY BEEN SCHEDULED *) THEN
242 P.EVENT:= P.EVENTAUX;
243 P.EVENT.PRIOR:=RANDOM;
246 P.EVENT.PRIOR:=RANDOM;
247 CALL PQ.DELETE(P.EVENT)
249 P.EVENT.EVENTTIME:= T;
250 CALL PQ.INSERT(P.EVENT) FI;
253 UNIT HOLD:PROCEDURE(T:REAL);
254 (* MOVE THE ACTIVE PROCESS T MINUTES BACK ALONG PQ *)
257 CALL PQ.DELETE(CURRENT.EVENT);
258 CURRENT.EVENT.PRIOR:=RANDOM;
259 IF T<0 THEN T:=0; FI;
260 CURRENT.EVENT.EVENTTIME:=TIME+T;
261 CALL PQ.INSERT(CURRENT.EVENT);
265 UNIT PASSIVATE: PROCEDURE;
266 (* REMOVE THE ACTVE PROCESS FROM PQ AND ACTIVATE THE NEXT ONE *)
268 CALL PQ.DELETE(CURRENT.EVENT);
273 UNIT RUN: PROCEDURE(P:SIMPROCESS);
274 (* ACTIVATE P IMMEDIATELY AND DELAY THE FORMER FIRST PROCESS BY REDEFINING*)
277 CURRENT.EVENT.PRIOR:=RANDOM;
280 P.EVENT.EVENTTIME:=TIME;
281 CALL PQ.CORRECT(P.EVENT,FALSE)
283 IF P.EVENTAUX=NONE THEN
284 P.EVENT,P.EVENTAUX:=NEW EVENTNOTICE(0);
285 P.EVENT.EVENTTIME:=TIME;
287 CALL PQ.INSERT(P.EVENT)
291 P.EVENT.EVENTTIME:=TIME;
293 CALL PQ.INSERT(P.EVENT);
298 UNIT CANCEL:PROCEDURE(P: SIMPROCESS);
299 (* REMOVE PROCESS P FROM PQ AND CONTINUE SIMULATION *)
301 IF P= CURRENT THEN CALL PASSIVATE ELSE
302 CALL PQ.DELETE(P.EVENT);
306 UNIT CHOICEPROCESS:PROCEDURE;
307 (* CHOOSE THE FIRST PROCESS FROM PQ TO BE ACTIVATED *)
311 CURR:= PQ.MIN QUA EVENTNOTICE.PROC;
312 IF CURR=NONE THEN WRITE(" ERROR IN THE HEAP"); WRITELN;
314 ELSE ATTACH(CURR); FI;
318 PQ:=NEW QUEUEHEAD; (* SIMULATION TIME AXIS*)
319 CURR,MAINPR:=NEW MAINPROGRAM;
320 MAINPR.EVENT,MAINPR.EVENTAUX:=NEW EVENTNOTICE(0);
321 MAINPR.EVENT.EVENTTIME:=0;
322 MAINPR.EVENT.PROC:=MAINPR;
323 CALL PQ.INSERT(MAINPR.EVENT);
324 (* THE FIRST PROCESS TO BE ACTIVATED IS MAIN PROGRAM *)
331 UNIT LISTS:SIMULATION CLASS;
332 (* WE WISH TO USE LISTS FOR QUEUEING PROCESSES DURING SIMULATION*)
335 (*WE WILL USE TWO WAY LISTS *)
336 VAR SUC1,PRED1:LINKAGE;
338 UNIT HEAD:LINKAGE CLASS;
339 (* EACH LIST WILL HAVE ONE ELEMENT ESTABLISHED *)
340 UNIT FIRST:FUNCTION:LINK;
342 IF SUC1 IN LINK THEN RESULT:=SUC1
343 ELSE RESULT:=NONE FI;
345 UNIT EMPTY:FUNCTION:BOOLEAN;
347 RESULT:=SUC1=THIS LINKAGE;
350 SUC1,PRED1:=THIS LINKAGE;
353 UNIT LINK:LINKAGE CLASS;
354 (* ORDINARY LIST ELEMENT PREFIX *)
362 UNIT INTO:PROCEDURE(S:HEAD);
367 IF S.SUC1=/=NONE THEN
370 PRED1.SUC1:=THIS LINKAGE;
371 S.PRED1:=THIS LINKAGE;
376 UNIT ELEM:LINK CLASS(SPROCESS:SIMPROCESS);
377 (* USER DEFINED PROCESS WILL BE JOINED INTO LISTS *)
386 (*BEGIN OF BANK DEPARTMENT SIMULATION*)
389 UNIT OFFICE:LISTS CLASS; (*AN OFFICE*)
391 UNIT TILL:SIMPROCESS CLASS(QUEUE:HEAD);
392 (* TELLER WITH CUSTOMERS QUEUEING UP *)
393 UNIT VIRTUAL SERVICE:PROCEDURE;
394 (* SERVICE OF THIS TELLER WILL BE PRECISED LATER *)
396 VAR CSTM:CUSTOMER, (*THE CUSTOMER BEING SERVED*)
402 REST:=REST+TIME-PAUSE;
403 WHILE NOT QUEUE.EMPTY DO
404 (* SERVE ALL QUEUE *)
405 CSTM:=QUEUE.FIRST QUA ELEM.SPROCESS;
407 CALL SCHEDULE(CSTM,TIME);
414 UNIT CUSTOMER:SIMPROCESS CLASS;
416 VAR ELLIST:ELEM, K:INTEGER;
417 UNIT ARRIVAL:PROCEDURE(S:TILL);
418 (* ATTACHING TELLER S *)
421 ELLIST:=NEW ELEM(THIS CUSTOMER);
422 CALL ELLIST.INTO(S.QUEUE);
423 IF S.IDLE THEN CALL SCHEDULE(S,TIME) FI;
432 UNIT BANKDEPARTMENT:OFFICE CLASS;
435 UNIT COUNTER:TILL CLASS;
436 VAR PAYTIME:REAL; (*RANDOM SERVICE TIME*)
437 UNIT VIRTUAL SERVICE:PROCEDURE;
439 WRITELN(" THE PAY DESK SERVES CUSTOMER NO",CSTM.K,
441 CALL CSTM.ELLIST.OUT;
448 UNIT TELLER:TILL CLASS(NUMBER:INTEGER);
449 VAR SERVICETIME:REAL;
450 UNIT VIRTUAL SERVICE:PROCEDURE;
453 WRITELN(" THE TELLER NO",NUMBER," WAS IDLE FOR",REST:10:4,
455 CALL CSTM.ELLIST.OUT;
456 N:=CSTM QUA BANKCUSTOMER.NO;
457 WRITELN(" THE CUSTOMER NO",CSTM.K,
458 " BEGINS TO BE SERVED BY THE TELLER NO",NUMBER,
460 ACCOUNT(N):=ACCOUNT(N)+CSTM QUA BANKCUSTOMER.AMOUNT;
461 IF ACCOUNT(N)<0 THEN CALL CSTM.ARRIVAL(CONTROL);FI;
462 SERVICETIME:=RANDOM*7+3;
463 CALL HOLD(SERVICETIME);
469 UNIT BANKCUSTOMER:CUSTOMER CLASS(NO:INTEGER,AMOUNT:REAL);
470 (* BANK CUSTOMER. AMOUNT- THE MONEY TO BE PAID AT THE BANK *)
471 VAR ARRIVALTIME,STAYTIME:REAL,CHOOSETELLER:INTEGER;
476 WRITELN(" THE CUSTOMER NO",K," ARRIVED AT",TIME:10:4);
477 CHOOSETELLER:=RANDOM*5+1;
478 CALL ARRIVAL(TELLERS(CHOOSETELLER));
479 IF AMOUNT<0 THEN CALL ARRIVAL(CTR); FI;
480 STAYTIME:=TIME-ARRIVALTIME;
481 WRITELN(" THE CUSTOMER NO",K," STAYED AT THE BANK FOR",
482 STAYTIME:10:4," SEC; STATE OF ACCOUNT",ACCOUNT(NO):10:4);
485 VAR TELLERS:ARRAYOF TELLER,ACCOUNT:ARRAYOF REAL;
486 VAR CTR:COUNTER, CONTROL:TILL,I:INTEGER;
488 BEGIN (* NEW BANK DEPARTMENT GENERATION *)
489 CTR:=NEW COUNTER(NEW HEAD);
490 ARRAY TELLERS DIM(1:5); (* WE DEAL WITH 5 TELLES *)
491 FOR I:=1 TO 5 DO TELLERS(I):=NEW TELLER(NEW HEAD,I); OD;
492 ARRAY ACCOUNT DIM(1:100);
493 (* WE DEAL WITH 100 ACOUNTS IN THIS BANK DEPARTMENT *)
494 FOR I:=1 TO 100 DO ACCOUNT(I):=RANDOM*901+100; OD;
495 (* AN ACCOUNT VALUE CAN FLUCTUATE FROM 100 TO 1000$ *)
501 BEGIN (* OF PROGRAM *)
502 PREF BANKDEPARTMENT BLOCK
503 UNIT GENERATOR:SIMPROCESS CLASS;
504 (* CUSTOMERS GENERATION *)
507 CALL SCHEDULE(NEW BANKCUSTOMER(RANDOM*100+1,
508 RANDOM*9996+5),TIME);
509 CALL HOLD(RANDOM*10);
510 CALL SCHEDULE(NEW BANKCUSTOMER(RANDOM*100+1,
511 -(RANDOM*900+5)),TIME);
512 CALL HOLD(RANDOM*10);
516 WRITELN(" BANK DEPARTMENT SERVICE SIMULATION");
518 CALL SCHEDULE(NEW GENERATOR,TIME);