The following are the types of events that occur in the system representing a pediatrician's office :
Whenever an event occurs the system undergoes a state transition and enters a state determined completely by the TYPE of the event and the state of the system at the time of occurrence of the event. The simulation process consists in tracing the state transitions the system undergoes in chronological order from a given initial state at the start of the simulation and terminating at the end of the simulation period. We construct the sequence of state transitions or the equivalent sequence of events from our knowledge of the initial condition and behaviour of the system, and the pattern of arrival of patients into the system.The chronological sequence of events can be generated if
We assume that the servers are free and their queues are empty at the start of the simulation. For the sake of simplicity we also assume that the first arrival coincides with the start of the simulation.
type
EventType = (Arrival,Completion_N,Completion_P,Termination)
PatientType = (N_Patient,P_Patient,NP_Patient)
PatientInfoType = record
PatientId : integer
PatientKind : PatientType
ArrivalSystem : Real
ArrivalPediatrician : Real
end
EventNode = record
EventKind : EventType
EventTime : Real
PatientInfo : PatientInfoType
Next : Pointer to EventNode
end
EventQueueType = record
First, Last : Pointer to EventNode
end
ServerQueueType = record
First, Last : Pointer to EventNode
SIze : Integer
LastUpdate : Real
end
VAR
EventQ : EventQueueType
QUEUE1, QUEUE2 : ServerQueueType
We assume that the operations CreateqFQ, InsertqFQ, DeleteqFQ, and IsemptyqFQ for the abstract data type FIFO queue, and their counterparts CreateqPQ, InsertqPQ, DeleteqPQ, and IsemptyqPQ for the abstract data type priority queue are already defined.
The algorithm also invokes the function PickRandom
FUNCTION PickRandom(Low, High : Real):Real;
that returns a random
number between Low and High. PickRandom uses one of the built-in random
number generators like random() or rand().
Now we state the algorithm in toto.
Algorithm Doctor'sOfficeSimulation
BEGIN
Read and validate input;
Initialize EventQ with the first Arrival and Termination events;
Initialize QUEUE1 and QUEUE2 to be empty;
NurseBusy := False;
PediatricianBusy := False;
REPEAT
CurrentEvent := DeleteqPQ(EventQ);
CurrentTime := CurrentEvent.EventTime;
CASE CurrentEvent.EventKind OF
Arrival : Log event in the log file;
Call CreateNextArrival(EventQ,CurrentTime,AMIN,AMAX,R1,R2);
IF this is a P_Patient THEN
BEGIN
IF PediatricianBusy Then
BEGIN
InsertqFQ(QUEUE2,CurrentEvent);
Update QUEUE2 size stats
end
else { pediatrician is not busy }
begin
Transform CurrentEvent into a Completion_P event
occurring at CurrentTime + PickRandom(S2MIN,S2MAX);
PediatricianBusy := true;
PediatricianBusyFrom := CurrentTime;
InsertqPQ(EventQ,CurrentEvent);
end
end
else { N_Patient or NP_Patient }
begin
if NurseBusy then
begin
InsertqFQ(QUEUE1,CurrentEvent);
Update QUEUE1 size stats
end
else { nurse is not busy }
begin
Transform CurrentEvent into a Completion_N event
occurring at CurrentTime + PickRandom(S1MIN,S1MAX);
NurseBusy := true;
NurseBusyFrom := CurrentTime;
InsertqPQ(EventQ,CurrentEvent);
end
end
Completion_N : Log event in the log file;
Compute response time for nurse, update stats;
IF this is an N_Patient THEN
BEGIN
Update response stats for N_Patients;
IF IsemptyqFQ(QUEUE1) THEN
NurseBusy := FALSE
ELSE
BEGIN
CurrentEvent := DeleteqFQ(QUEUE1);
Update QUEUE1 size stats;
Transform CurrentEvent into a Completion_N event
occurring at CurrentTime + PickRandom(S1MIN,S1MAX);
NurseBusy := true;
NurseBusyFrom := CurrentTime;
InsertqPQ(EventQ,CurrentEvent);
END
END
ELSE { NP_Patient }
BEGIN
CurrentEvent.PatientInfo.ArrivalPediatrician
:= CurrentTime;
IF PediatricianBusy Then
begin
InsertqFQ(QUEUE2,CurrentEvent);
Update QUEUE2 size stats
end
else { pediatrician is not busy }
begin
Transform CurrentEvent into a Completion_P event
occurring at CurrentTime + PickRandom(S2MIN,S2MAX);
PediatricianBusy := true;
PediatricianBusyFrom := CurrentTime;
InsertqPQ(EventQ,CurrentEvent);
end
END
Completion_P : Log event in the log file;
Compute response time for pediatrician, update stats;
IF this is a P_Patient then
Update response stats for P_Patients
ELSE { NP_Patient }
Update response stats for NP_Patients;
IF IsemptyqFQ(QUEUE2) THEN
PediatricianBusy := FALSE
ELSE
BEGIN
CurrentEvent := DeleteqFQ(QUEUE2);
Update QUEUE2 size stats;
Transform CurrentEvent into a Completion_P event
occurring at CurrentTime + PickRandom(S2MIN,S2MAX);
PediatricianBusy := true;
PediatricianBusyFrom := CurrentTime;
InsertqPQ(EventQ,CurrentEvent);
END
Termination : Log event in the log file;
Check if Nurse(Pediatrician) is busy and if so
update busy time for Nurse(Pediatrician);
IF QUEUE1(QUEUE2) is not empty THEN
update QUEUE1(QUEUE2) size stats;
END; { CASE }
UNTIL (CurrentEvent.EventKind = Termination);
Compute Results;
END. { Doctor'sOfficeSimulation }
PROCEDURE CreateNextArrival (var EventQ : EventQueueType;
CurrentTime, AMIN, AMAX, R1, R2 : Real);
{ Creates a node corresponding to an Arrival event that would occur at
CurrentTime + PickRandom(AMIN,AMAX) and places it in EventQ. EventQ is a
priority queue in which events are stored in nondecreasing order of the
event occurrence times.
}
VAR
NewEvent : EventNode;
PatientChoice : Real;
BEGIN
Create a node of type EventNode in NewEvent;
Make assignments to the components of NewEvent so that it represents an
Arrival event occurring at CurrentTime + PickRandom(AMIN,AMAX);
PatientChoice := PickRandom(0,1);
IF PatientChoice > R1 THEN
NewEvent.PatientInfo.PatientKind := P_Patient
ELSE IF PatientChoice <= R1 * R2 THEN
NewEvent.PatientInfo.PatientKind := N_Patient
ELSE
NewEvent.PatientInfo.PatientKind := NP_Patient;
InsertqPQ(EventQ,NewEvent);
END; { CreateNextArrival }
amandala@astro.ocis.temple.edu