# CS333 Lab A-3: Distributed Discrete Event Simulation

## Goals of this lab:

• Learn about discrete event simulation.
• Construct a framework for distributed discrete event simulation of message-passing systems.
• Use your system to perform a simulation of a "car wash."

## Introduction:

A discrete event is something that occurs at an instant of time. For example, pushing an elevator button, starting of a motor, stopping of a motor, and turning on a light, are all discrete events because there is an instant of time at which each occurs. Activities such as moving a train from point A to point B are not descrete events because they have a time duration. However, we can model an event like this as two separate discrete events: the event of the train leaving point A, and the event of the train arriving at point B. If we associate a time value with each discrete event, then we can model the duration activities as the difference between the times associated with the events marking the beginning and the end of each activity. For example, we can specify that the arrival at point B occurs 3 hours and 37 minutes after leaving point A. Therefore, we can see that if the train leaves point A at 7:53pm, then it will arrives at point B at 11:30pm.

The purpose of a discrete event simulation is to study a complex system by computing the times that would be associated with real events in a real-life situation. In the train example above, suppose that we know that when the train arrives at point B, a load is transferred to a second train that arrives at point C after 45 minutes. That is, the second train's departure from point B is triggered by the first train's arrival, and the arrival at point C occurs with a delay of 45 minutes after the departure from point B. In this simple example, we can use discrete event simulation to determine that the second train will arrive at point C at 12:15am.

One way to carry out a simulation is to use the real-time clock (the clock on the wall) to time the delays, and to read the value on the clock as each event completes in order to see what would happen. However, this would take unnecessarily long. For example, it would be silly to wait 3 hours and 37 minutes to determine the arrival time of the first train when a simple calculation suffices. So, the idea of a discrete event simulation is to compute, as quickly as possible, the physical times that "would" occur in real time in a physical system, but without actually waiting for the delays between events to occur in real time.

To accomplish this in a sequential program, one uses a queue of events that are ready to be performed. This event queue is kept sorted in increasing time order, and the program processes the events in increasing time order. The program is started with one or more events initially in the queue, and has built-in knowledge about how each kind of event causes other events to be added to the event queue. (For example, it may know that if one event occurs at time t, then a related event should occur 5 time units later, at time t+5, so it would put that new event in its queue.

When simulations grow large and have a lot of concurrency (have many events that could be processed simultaneously), it can be helpful to distribute the work of processing events across many simulators, with each simulator responsible for processing certain kinds of events. Like the sequential version, each simulator maintains its own event queue and processes events in time order. Some events may cause new events to be put into the local event queue. However, some of the events may need to be sent elsewhere for processing.

Each simulator may proceed independently, processing events in its event queue. It is not a problem if some of the simulators are "ahead" of others in terms of the times that they are assigning to events. In fact, this is desirable. However, the trick is that you must guarantee that no simulator receives an event whose time is earlier than any event already processed by that simulator, because otherwise the events would be processed out of order. Another way of saying this is that we cannot allow time to go "backwards" at any of the simulators.

In an "optimistic" approach to distributed discrete event simulation, one assumes that such a problem will not occur, and, if a problem does arise, it "rolls back" the simulation to an earlier point and restarts from there. However, we will use a "conservative" approach, in which we will guarantee that events cannot arrive out of order. In other words, before it processes an event with time t, a simulator must be certain that it will not be receiving any more events to process with times earlier than t.

We assume that each simulator knows the set of "incoming neighbors" (simulators from which it might receive events). If a simulator knows that the current simulation time of each of its incoming neighbors is greater than time t, then it is safe for the simulator to process events at time t or earlier. Sometimes, this knowledge is available automatically: if a simulator has already received events with times greater than t from each of its incoming neighbors, then it is safe to advance its local simulation to time t. However, if a simulator does not receive an event with time greater than t from one of its neighbors, it may have to wait indefinitely before processing the next event. There are many possible approaches to solving this problem, and every solution some advantages and disadvantages. We will let you decide on your own solution to this problem, but here are some ideas.

• Each simulator can periodically send its current simulation time to its outgoing neighbors, even if it has no real events to send them. These "null" messages let the neighbors determine if it is safe to advance the simulation. However, many of these messages may be sent needlessly because a simulator is not waiting for them.

• If a simulator is waiting, it can "poll" each of its incoming neighbors to determine its latest simulation time. If each responds with a time greater than t, then it is safe to advance the simulation to time t. However, it could become necessary to poll repeatedly until each neighbor reaches time t, causing a lot of message traffic even if the neighbors have not advanced in time.

## Directions:

Be sure that you have read the introduction carefully. Then read over the rest of the assignment before starting.

1. Overview of the Simulated System: In this project, you will construct a distributed discrete event simulation of a car wash. The car wash is viewed as a message-passing system consisting of several distinct components: a source where cars enter the system, two or more physical car wash stations, an attendant who decides where each car should go, and an exit where cars leave the system. A schematic diagram of message communication among these components is given below.

The components have the following functionality:

• Source: Generates cars at random times and sends them to the attendant. You may assume that it takes 0 time units to send a car from the source to the attendant.

• Attendant: Directs cars to the car wash stations according to the following rules. If all car wash stations are busy washing cars, then each arriving car is queued at the attendant. If one or more car wash stations is idle (not busy washing a car), then the car at the head of the queue, if any, is sent to that an idle car wash station. If multiple car wash stations are idle, it's up to the attendant where to send the next car. You may assume that it takes 0 time units to send a car from the Attendant to a car washer.

• Car wash stations: Wash cars, one at a time. The washing time of each station is fixed (an input parameter to your program), but different car wash stations may have different washing times within the same simulated system. After each car is washed, it is sent to the exit, and the car wash station notifies the attendant that it is idle, ready to accept another car. e named as CarWasher2. Initially, all car wash stations are idle.

2. Sequential simulator (optional): (As a stepping stone to your distributed discrete event simulation system, you may want to start by implementing a sequential discrete event simulator. You will not turn in this part of the assignment, so you may be tempted to go straight to the distributed version. However, at a minimum, you should understand how you would design the sequential version before tackling the distributed one.)

Implement a sequential discrete event simulator. The parameters of your program should be: the number of car wash stations, the processing time of each station (separately), the range of random numbers chosen for the arrival times of the cars (smallest random number and largest random number), and the closing time (when the source will stop sending new cars into the system). Note that two par ameters are used for the car source to generate cars, allowing you to control both the minimum and maximum time interval between the arrival of two cars.

Your simulator should maintain a sorted event list and process events in time order. To process each event, you should remove it from the event list, PRINT out the name of the event which includes the time at which it occurs, and insert any triggered events (with appropriate times) to the event list with the appropriate times. Remember that it is legal for one event to trigger multiple events. For example, the arrival of a car at a car wash station may cause two new events to be queued: sending a car to the exit and sending an "idle" message to the attendant.

Each event has a sender, a receiver, content, and its associated time. For example, the event [18, attendant, Station3, Car10] denotes that the attendant sends Car10 to Station3 at time 18.

In addition, your simulator should maintain a car queue which keeps track of the cars queued at the attendant.

Be sure to test your sequential simulator thoroughly, especially if you plan to use the code as a building block for your distributed simulation.

3. Distributed Simulation: Now modify your simulator so that it can be used for distributed discrete event simulation. Your main task is to implement 3 types of modules. Whenever a module removes an event from its event queue for processing, it should print out all the information about that event (time, content of message, etc.).

• Source: The parameters of this module include smallest random number, largest random number, and the terminate time. The meanings of these parameters are the same as in the sequential version above.

• Attendant: The only parameter of this module is the number of car wash stations. The attendant does not have to know the processing time of each car wash (unless you want it to). Note that it is safe for the attendant to process an event with time component t only when it can be certain that it has already received all messages with times up to time t. Also note that the messages the attendant receives may not be in time order due to the nature of distributed simulation.

• Station: You will instantiate this module multiple times. For each instance, you will provide a parameter that indicates the amount of time this car wash station needs to wash one car. The inputs are messages received from the attendant and the outputs are messages sent to an exit module.

In your distributed simulator, message passing is achieved by publishing a tuple whose type matches that of the message. The message can be in the form of [time, sender, receiver, content], or in the form of [time, receiver, content], or even in the form of [time, content], depending upon how you design your system.

Note: To avoid deadlock at the end of the program, one simple approach is to let the CarSource module sending a "Terminate" (or "NULL") message after it finishes generating cars. After delivering all queued cars, the Attendant processes the "Terminate" message by forwarding the "Terminate" message to all the car washers. In this way, all modules can terminate gracefully. Otherwise, the Attendant and all CarWashers will wait indefinitely.

4. Visualization:Using EUPHORIA, construct a simple visualization of your simulation system. For example, you could have the attendant publish it's queue length, updated over time. Also, you could have each station publish a flag saying whether or not it is busy, etc. Then you could connect this status information to Euphoria for visualization. If you want to get fancy, you could allow the user to control the input parameters for the modules (such as the random values for car arrivals, termination time, and length of time to wash a car at each station.) Keep in mind that as you watch the system, different components will be operating at different logical times simultaneously. (Even if you do a fancy visualization, you should still print out the events processed by each component.)