There is a lot to be said on Discrete Event Simulations that can be covered here. We refer the readers to the excellent article at Wikipedia and the references therein as an entry point to this interesting field of Computer Science.
Briefly speaking, Discrete Event Simulation (DES) is a technique to model a complex system in order to study its behavior. The system is modeled as a collection of states that change over time. Within DES, the time advances in discrete steps.
A typical model of a system includes (a) entities, which are the active actors in the system and encapsulate the state and logic of the system components, (b) resources, which are consumed by the entities, (c) communication primitives, to coordinate actions between entities across time, and of course, (d) statistics, which is the output of a simulation run.
As we will see shortly, the SIM.JS library provides support for entities, resources (Facility, Buffers and Stores), communication (via Timers, Events and Messages) and statistics (with Data Series, Time Series and Population statistics).
The most common design pattern that appears in DES models is as follows:
1. entity:: 2. do_some_local_computation 3. resource = request_some_shared_resource 4. do_more_local_computation
It is possible that the said resource is not available currently, in which case the request cannot be immediately satisfied and the entity must, therefore, “block” from further execution.
Waiting for resources is only one examples where entities may need to wait. There are other cases as well, for example, wait for a timer to expire, wait to receive message from other entities, wait for a predicate condition to become true, and so on.
There are two broad categories for implementing this “blocking” behavior:
In process-based simulation, the entities behave very much like regular operating system processes. Each entity runs on a separate thread, and when an entity executes a command for which it must block, the entire thread is suspended. When the waiting condition is satisfied, the thread is resumed. In the example given above, the entity thread will block at line 3 until the resource is free, and then will resume to line 4.
In event-based simulation, the entities all run in a single thread. At the time of making a request, the entities provide a callback function that must be invoked when the waiting condition is over. This style of programming is widely used in Graphical User Interface designs where preconfigured callback functions are called by the system when any event of interest occurs (e.g. mouse click). However, it also means that the code must be restructured a little. The above example must be written as:
entity:: do_some_local_computation request_some_shared_resource_with_callback(entity_get_resource) return entity_get_resource (resource):: do_more_local_computation
The proponents of process-based programming claim that their design leads to a better readability of code. Whereas the adherents of event-based programming argue that their approach is more structured since the actions for each different kind of events are encapsulated as different functions.
The SIM.JS library provides event-based programming model, for the following reasons:
The SIM.JS library introduces two class variables in the global namespace: Sim and Random. The Sim class provides all functionality for Discrete Event Simulation, while the Random class provides random number generation capability.
The Sim namespace further provides following classes:
|Sim||The simulator kernel.|
|Sim.Facility||Facility is a resource that is used by entities for a finite duration. There is a limit on the number of entities that can use the facility at a given time. As an example, consider a barbershop (the facility) with m barbers (capacity of facility). The customers arrive at shop and wish to ‘use’ the resource (barber); if all barbers are busy, the customers wait until one barber is available.|
|Sim.Buffer||Buffer is a resource that can store a finite number of tokens. Any entity can store tokens in the buffer if there is free space, or retrieve existing tokens from the buffer if some are available.|
|Sim.Event||Events are external objects that start out in passive state, and at some point in time will be activated or fired. Entities ‘attach’ themselves to events and wait until the event is fired.|
|Sim.Request||When an entity makes a request to the simulation – such as set a timer, use a facility, etc – the simulator returns back a Request object. The entity can use this Request object to further modify the original request.|
|Sim.DataSeries||Data Series is a collection of discrete, time-independent observations, for example, grades of each student in a class, length of rivers in United States. The DataSeries class provides a convenient API for recording and analyzing such observations, such as finding maximum and minimum values, statistical properties like average and standard deviation and so on.|
|Sim.TimeSeries||Time Series is a collection of discrete time-dependent observations. That is, each observation value is associated with a discrete time instance (the time at which the observation was made). For example, the size of queue at time t during the simulation run, number of customers in a restaurant at time t during evening hours.The TimeSeries class provides a convenient API for recording and analyzing such observations, such as finding maximum and minimum values, statistical properties like time-averaged mean and standard deviation and so on.|
|Sim.Population||Population is actually a composite of the above two statistics, which models the behavior of population growth and decline.|