Discrete Event Simulation with OESjs-Core0

How to create and run simulations with the JavaScript-based simulation library OESjs-Core0 available from the OES GitHub repo
Gerd Wagner G.Wagner@b-tu.de

Copyright © 2020 Gerd Wagner (CC BY-NC)

Published 2020-08-17

Abstract

This tutorial article explains how to use the OESjs-Core0 library, which implements a minimal architecture for an Object Event simulator, supporting model variables, object types, event types, next-event time progression and simple simulation experiments.

Table of Contents

List of Figures

List of Tables

Chapter 1. Introduction to Object Event Modeling

Simulation is used widely today: in many scientific disciplines for investigating specific research questions, in engineering for testing the performance of designs, in education for providing interactive learning experiences, and in entertainment for making games.

Both static systems/structures and dynamic systems can be modeled and simulated. Modeling and simulation (M&S) of static structures, such as the surface textures of materials, is only an issue in physics and computer graphics, while M&S of dynamic systems is an issue in all scientific and engineering disciplines, including management science, economics and other social sciences.

A dynamic system may be subject to discrete or continuous state changes. For simulating a dynamic system one has to model

  1. the types of objects it is composed of,
  2. the types of events that cause discrete state changes of objects,
  3. the discrete state changes of objects caused by the occurrence of an event of some type,
  4. the follow-up events caused by the occurrence of an event of some type,
  5. the continuous state changes of objects (described with the help of differential equations).

A (purely) continuous dynamic system does not include events and their causal effects (list items 2-4), but only objects that are subject to continuous state changes (list items 1 and 5). A (purely) discrete dynamic system does not include any continuous state changes of objects (list item 5). Many real-world systems include both discrete and continuous state changes, in which case they may be called hybrid dynamic systems.

In this tutorial, we are only concerned with discrete state changes. Consequently, we only consider purely discrete dynamic systems, also called discrete event systems, which consist of:

This means that for modeling such a system, we have to

  1. describe its object types and event types (in an information model);
  2. specify, for any event type, the state changes of objects and the follow-up events caused by the occurrence of an event of that type (in a process model).

1.1. Making a Conceptual Model of the System under Investigation

Let's look at an example. We model a system of one or more service desks, each of them having its own queue, as a discrete event system:

  • Customers arrive at a service desk at random times.
  • If there is no other customer in front of them, and the service desk is available, they are served immediately, otherwise they have to queue up in a waiting line.
  • The duration of services varies, depending on the individual case.
  • When a service is completed, the customer departs and the next customer is served, if there is still any customer in the queue.

The potentially relevant object types of the system under investigation are:

  • customers,
  • service desks,
  • waiting lines,
  • service clerks, if the service is performed by (one or more) clerks.

The potentially relevant event types are:

  • customer arrivals,
  • service starts,
  • service terminations,
  • customer departures.

1.2. Making a Simulation Design Model

When making a simulation design based on the conceptual model of the system under investigation, wee need to abstract away from many items of the conceptual model for obtaining a sufficiently simple design. The right degree of abstraction depends on the purpose of the model. But abstracting away from too many things may make a model too unnatural and not sufficiently generic, implying that it cannot be easily extended to model additional features (such as more than one service desk).

In our example, the purpose of the simulation model is to compute the maximum queue length and possibly also the service utilization. So, we may abstract away from the following object types:

  • customers: we don't need any information about individual customers.
  • waiting lines: we don't need to know who is next, it's sufficient to know the length of the queue.
  • service clerks: we don't need any information about the service clerk(s).

Notice that, for simplicity, we consider the customer that is currently being served to be part of the queue. In this way, in the simulation program, we can check if the service desk is busy by testing if the length of the queue is greater than 0. In fact, for being able to compute the service utilization and the maximum queue length, the queue length is the only relevant state variable.

State variables can be modeled in the simple form of global variables or in the form of attributes of suitable object types. Consequently, the simplest model we can make for the given problem, called Service-Desk-0, has only one global variable: queueLength. But, as an alternative, more explicit, model, called Service-Desk-1, we will also model the system state in terms of (one or more) ServiceDesk objects having only one property: queueLength. As opposed to the simpler model defining queueLength as a global variable, this model allows defining simulation scenarios with two or more service desks operating simultaneously.

We also look for opportunities to simplify our event model by dropping event types that are not needed, e.g., because their events temporally coincide with events of another type. This is the case with service terminations and customer departure events. Consequently, we can drop the event type service terminations.

There are two situations when a new service can be started: either when the waiting line is empty and a new customer arrives, or when the waiting line is not empty and a service terminates. Therefore, any service start event immediately follows either a customer arrival or a customer departure event, and we may abstract away from service start events and drop the corresponding event type from the design model.

So we only need to consider customer arrival and customer departure events, modeled with the two event types Arrival and Departure.

The event type Arrival is an example of a type of exogenous events, which are not caused by any causal regularity of the system under investigation and, therefore, have to be modeled with a recurrence function that allows to compute the time of the next occurrence of an event of that type. In OES, exogenous event types are a built-in concept such that an OES simulator takes care of creating the next exogenous event whenever an event of that type is processed. This mechanism makes sure that there is a continuous stream of exogenous events throughout a simulation run.

We also have to model the random variations of two variables: (1) the recurrence of (that is, the time in-between two) customer arrival events and (2) the service duration. In a class model, such random variables can be defined as special class-level ("static") operations, with a stereotype «rv», in the class to which they belong, as shown in the diagrams below.

We model the recurrence of customer arrival events as a discrete random variable with a uniform distribution between 1 and 6 minutes, which we express in the class diagram of the information design model by appending the symbolic expression U{1-6} within curly braces to the operation declaration, following the UML syntax for property/method modifiers.

We model the service time random variable with an empirical distribution of 2 minutes with probability 0.3, 3 minutes with probability 0.5 and 4 minutes with probability 0.2, using the symbolic expression Freq{ 2:0.3, 3:0.5, 4:0.2}.

Computationally, object types and event types correspond to classes, either of an object-oriented information model, such as a UML class diagram, or of a computer program written in an object-oriented programming language, such as Java or JavaScript.

1.2.1. Service-Desk-0: Modeling queueLength as a global variable

As discussed above, the simplest model for the service desk problem with maximum queue length statistics (available in the Sim4edu library as Service-Desk-0) has only one global variable: queueLength, which is a non-negative integer, and a global function for computing the random service time, but no object type.

An information model for Service-Desk-0 consists of a special class for defining model variables and functions, and two classes for defining the event types Arrival and Departure, as shown in Figure 1-1. An information design model for Service-Desk-0.

Figure 1-1. An information design model for Service-Desk-0
???

In addition to an information design model for defining the simulation system's state structure, we also need to make a process design model for defining the dynamics of the simulation system. The dynamics of a system consists of events triggering state changes and follow-up events. A process model can be expressed with the help of event rules, which define what happens when an event (of a certain type) occurs, or, more specifically, which state changes and which follow-up events are caused by an event of that type.

Event rules can be expressed with the help of a process model diagram or in pseudo-code, or in a simulation or programming language. The following Event Graph provides a process design model for the Service-Desk-0 simulation scenario. Circles represent events (or, more precisely, event types) and arrows, which may be annotated with a delay expression, such as +serviceTime(), represent event scheduling relationships. An arrow with a mini-diamond at its source end represents a conditional event scheduling relationship where the condition is expressed in brackets below or above the arrow.

Figure 1-2. A process design model in the form of an Event Graph, where the state variable Q stands for queueLength
???

Event Graphs have originally been proposed by L. Schruben (1983). Their visual syntax has been improved and harmonized with the business process modeling language BPMN in the Discrete Event Process Modeling Notation (DPMN) proposed by Wagner (2018) and more thoroughly described in the book Discrete Event Simulation Engineering.

The following table shows the two event rules defined by the above Event Graph, expressed in pseudo-code.

ON (event type)

DO (event routine)

Arrival @ t

INCREMENT queueLength
IF queueLength = 1 THEN
  sTime := serviceTime()
  SCHEDULE Departure @ (t + sTime)

Departure @ t

DECREMENT queueLength
IF queueLength > 0 THEN
  sTime := serviceTime()
  SCHEDULE Departure @ (t + sTime)

1.2.2. Service-Desk-1: Modeling queueLength as an attribute

In our extended model (Service-Desk-1) we represent the state variable queueLength as an attribute of an object type ServiceDesk. This results in a model with three classes, the object class ServiceDesk with an attribute queueLength, and the event classes Arrival and Departure, both with a reference property serviceDesk for referencing the service desk at which an event occurs. When we also want to compute the service utilization statistics, we need to add an attribute serviceTime to the Departure class for being able to update the service utilization statistics when a customer departs.

Both event types, Arrival and Departure, now have a many-to-one association with the object type ServiceDesk. This expresses the fact that any such event occurs at a particular service desk, which participates in the event. This association is implemented in the form of a reference property serviceDesk in each of the two event types, as shown in Figure 1-3. An information design model for Service-Desk-1.

Figure 1-3. An information design model for Service-Desk-1
???

In addition to an information model, we need to make a process model, which captures the dynamics of the service desk system consisting of arrival and departure events triggering state changes and follow-up events. The following DPMN Process Diagram provides a process design model for the Service-Desk-1 simulation scenario. As in Event Graphs, circles represent event types and arrows represent event scheduling relationships. DPMN extends Event Graphs by adding object rectangles, attached to event circles, representing state change patterns for objects that are affected by events of that type.

Figure 1-4. A process design model in the form of a DPMN Process Diagram
???

The following table shows the two event rules defined by the DPMN diagram, which now account for the fact that both types of events occur at a particular service desk that is referenced by the event expression parameter sd.

ON (event type)

DO (event routine)

Arrival( sd) @ t

with sd : ServiceDesk

INCREMENT sd.queueLength
IF sd.queueLength = 1 THEN
  sTime := ServiceDesk.serviceTime()
  SCHEDULE Departure( sTime, sd) @(t + sTime)

Departure( sd) @ t

with sd : ServiceDesk

DECREMENT sd.queueLength
IF sd.queueLength > 0 THEN
  sTime := ServiceDesk.serviceTime()
  SCHEDULE Departure( sTime, sd) @(t + sTime)

Chapter 2. Creating Object Event Simulations with OESjs-Core0

The JavaScript-based simulator OESjs-Core0 implements the Object Event Simulation (OES) paradigm, representing a general Discrete Event Simulation approach based on object-oriented modeling and event scheduling. In OES, a model normally defines various types of objects and events, but OESjs-Core0 also supports models without objects, if they define state variables in the form of global model variables, instead.

An OESjs-Core0 simulation consists of the OESjs-Core0 library code and the following files to be created by the simulation developer:

  1. For each object type ObjT, a JS code file ObjT.js.
  2. For each event type EvtT, a JS code file EvtT.js.
  3. A simulation.js file defining further parts of the simulation, such as statistics variables and the initial state.

OESjs-Core0 supports two forms of simulations:

  1. Standalone scenario simulations, which are good for getting a quick impression of a simulation model, e.g., by checking some simple statistics.

  2. Simple simulation experiments, which are defined as a set of replicated simulation scenario runs, providing summary statistics like mean, standard deviation, minimum/maximum and confidence intervals for each statistics variable defined in the underlying model.

Using a simulation library like OESjs-Core0 means that only the model-specific logic has to be coded (in the form of object types, event types, event routines and other functions for model-specific computations), but not the general simulator operations (e.g., time progression and statistics) and the environment handling (e.g., user interfaces for statistics output).

The following sections present the basic concepts of the OESjs-Core0 simulation library, and show how to implement the service desk models described in Chapter 1. Introduction to Object Event Modeling.

While you can directly run a OESjs Core1 simulation model from a remote website (e.g., from the OES GitHub website), you can only run it from your local file system after changing your browser's default configuration. For FireFox, you have to set the configuration property privacy.file_unique_origin to false by entering about:config in the browser's web address bar.

2.1. Simulation Time

A simulation model has an underlying time model, which can be either discrete time, when setting

sim.model.time = "discrete";

or continuous time, when setting

sim.model.time = "continuous";

Choosing a discrete time model means that time is measured in steps (with equal durations), and all temporal random variables used in the model need to be discrete (i.e., based on discrete probability distributions). Choosing a continuous time model means that one has to define a simulation time granularity, as explained in the next sub-section.

In both cases, the underlying simulation time unit can be either left unspecified (e.g., in the case of an abstract time model), or it can be set to one of the time units "ms", "s", "min", "hour", "day", "week", "month" or "year", as in

sim.model.timeUnit = "hour";

Typical examples of time models are:

  1. An abstract discrete model of time where time runs in steps without any concrete meaning:

    sim.model.time = "discrete";
  2. A concrete discrete model of time in number of days:

    sim.model.time = "discrete";
    sim.model.timeUnit = "day";
  3. A concrete continuous model of time in number of seconds:

    sim.model.time = "continuous";
    sim.model.timeUnit = "s";

2.1.1. Time Granularity

A model's time granularity is the time delay until the next moment, such that the model does not allow considering an earlier next moment. This is captured by the simulation parameter nextMomentDeltaT used by the simulator for scheduling immediate events with a minimal delay. When a simulation model is based on discrete time, nextMomentDeltaT is set to 1, referring to the next time point. When a simulation model is based on continuous time, nextMomentDeltaT is set to the default value 0.001, unless the model parameter sim.model.nextMomentDeltaT is explicitly assigned in the simulation.js file.

2.1.2. Time Progression

An important issue in simulation is the question how the simulation time is advanced by the simulator. The OES paradigm supports next-event time progression and fixed-increment time progression, as well as their combination.

An OESjs-Core0 model with fixed-increment time progression has to define a suitable periodic time event type, like EachSecond or EachDay in the form of an exogenous event type with a recurrence function returning the value 1. Such a model can be used for

  1. modeling continuous state changes (e.g., objects moving in a continuous space), or
  2. making a discrete model that abstracts away from explicit events and uses only implicit periodic time events ("ticks"), which is a popular approach in social science simulation.

Examples of discrete event simulation models with fixed-increment time progression and no explicit events are the Schelling Segregation Model and the Susceptible-Infected-Recovered (SIR) Disease Model.

2.2. Simulation Models

2.2.1. Model Variables and Functions

In the simple model of a service desk discussed in the previous section, we define one (global) model variable, queueLength, one model function, serviceTime(), and two event types, as shown in the following class diagram:

???

Notice that this model does not define any object type, which implies that the system state is not composed of the states of objects, but of the states of model variables (here the state of the model variable queueLength). The discrete random variable for modeling the random variation of service durations is implemented as a model function serviceTime shown in the Global Variables and Functions class. It samples integers between 2 and 4 from the empirical probability distribution Frequency{ 2:0.3, 3:0.5, 4:0.2}. The model can be coded with OESjs-Core0 in the following way:

// (global) model variable
sim.model.v.queueLength = 0;
// (global) model function
sim.model.f.serviceTime = function () {
  var r = math.getUniformRandomInteger( 0, 99);
  if ( r < 30) return 2;         // probability 0.30
  else if ( r < 80) return 3;    // probability 0.50
  else return 4;                 // probability 0.20
};

You can run this Service-Desk-0 model from the project's GitHub website. An example of a run of this model is shown in the following simulation log:

Table 2-1. Simulation Log
StepTimeSystem StateFuture Events
00queueLength: 0CustomerArrival@1
11queueLength: 1CustomerDeparture@4, CustomerArrival@4
24queueLength: 1CustomerDeparture@6, CustomerArrival@7
36queueLength: 0CustomerArrival@7
47queueLength: 1CustomerDeparture@11, CustomerArrival@13
511queueLength: 0CustomerArrival@13
613queueLength: 1CustomerDeparture@15, CustomerArrival@19
715queueLength: 0CustomerArrival@19
............
49114queueLength: 0CustomerArrival@117
50117queueLength: 1CustomerArrival@118, CustomerDeparture@119
51118queueLength: 2CustomerDeparture@119, CustomerArrival@119
52119queueLength: 2CustomerArrival@121, CustomerDeparture@123
53121queueLength: 3CustomerDeparture@123, CustomerArrival@124
54123queueLength: 2CustomerArrival@124, CustomerDeparture@126
55124queueLength: 3CustomerArrival@125, CustomerDeparture@126
56125queueLength: 4CustomerDeparture@126, CustomerArrival@128
57126queueLength: 3CustomerArrival@128, CustomerDeparture@128
58128queueLength: 3CustomerArrival@129, CustomerDeparture@131
59129queueLength: 4CustomerDeparture@131, CustomerArrival@133
60131queueLength: 3CustomerArrival@133, CustomerDeparture@135
61133queueLength: 4CustomerDeparture@135, CustomerArrival@137
62135queueLength: 3CustomerArrival@137, CustomerDeparture@137
63137queueLength: 3CustomerArrival@139, CustomerDeparture@141
64139queueLength: 4CustomerDeparture@141, CustomerArrival@142
65141queueLength: 3CustomerArrival@142, CustomerDeparture@144
66142queueLength: 4CustomerDeparture@144, CustomerArrival@147
67144queueLength: 3CustomerArrival@147, CustomerDeparture@148
68147queueLength: 4CustomerDeparture@148, CustomerArrival@148
69148queueLength: 4CustomerArrival@149, CustomerDeparture@151
70149queueLength: 5CustomerDeparture@151, CustomerArrival@151
............

2.2.2. Object Types

Object types are defined in the form of classes. Consider the object type ServiceDesk defined in the following Service-Desk-1 model:

???

While queueLength was defined as a global variable in the Service-Desk-0 model, it is now defined as an attribute of the object type ServiceDesk:

class ServiceDesk extends oBJECT {
  constructor({ id, name, queueLength}) {
    super( id, name);
    this.queueLength = queueLength;
  }
  static serviceTime() {
    var r = math.getUniformRandomInteger( 0, 99);
    if ( r < 30) return 2;         // probability 0.3
    else if ( r < 80) return 3;    // probability 0.5
    else return 4;                 // probability 0.2
  }
}
ServiceDesk.labels = {"queueLength":"qLen"};  // for the log

Notice that, in OESjs, object types are defined as subtypes of the pre-defined class oBJECT, from which they inherit an integer-valued id attribute and an optional name attribute. When a property has a label (defined by the class-level (map-valued) property labels), it is shown in the simulation log.

You can run this simulation model from the project's GitHub website.

2.2.3. Event Types

In OES, there is a distinction between two kinds of events:

  1. events that are caused by other event occurrences during a simulation run;
  2. exogenous events that seem to happen spontaneously, but may be caused by factors, which are external to the simulation model.

Here is an example of an exogenous event type definition in OESjs-Core0:

class CustomerArrival extends eVENT {
  constructor({ occTime, serviceDesk}) {
    super( occTime);
    this.serviceDesk = serviceDesk;
  }
  onEvent() {
    ...
  }
  ...
}

The definition of the CustomerArrival event type includes a reference property serviceDesk, which is used for referencing the service desk object at which a customer arrival event occurs. In OESjs, event types are defined as subtypes of the pre-defined class eVENT, from which they inherit an attribute occTime, which holds the occurrence time of an event. As opposed to objects, events do normally not have an ID, nor a name.

Each event type needs to define an onEvent method that implements the event rule for events of the defined type. Event rules are discussed below.

Exogenous events occur periodically. They are therefore defined with a recurrence function, which provides the time in-between two events (often in the form of a random variable). The recurrence function is defined as a class-level ("static") method:

class CustomerArrival extends eVENT {
  ...
  static recurrence() {
    return math.getUniformRandomInteger( 1, 6);
  }
}

Notice that the recurrence function of CustomerArrival is coded with the library method math.getUniformRandomInteger, which allows sampling from discrete uniform probability distribution functions.

In the case of an exogenous event type definition, a createNextEvent method has to be defined for assigning event properties and returning the next event of that type, which is scheduled by invoking the recurrence function for setting its ocurrenceTime and by copying all participant references (such as the serviceDesk reference).

class CustomerArrival extends eVENT {
  ...
  createNextEvent() {
    return new CustomerArrival({
      occTime: this.occTime + CustomerArrival.recurrence(),
      serviceDesk: this.serviceDesk
    });
  }
  static recurrence() {...}
}

The second event type of the Service-Desk-1 model, Departure, is an example of a type of caused events:

class CustomerDeparture extends eVENT {
  constructor({ occTime, serviceDesk}) {
    super( occTime);
    this.serviceDesk = serviceDesk;
  }
  onEvent() {
    ...
  }
}

A caused event type does neither define a recurrence function nor a createNextEvent method.

2.2.4. Event Rules

An event rule for an event type defines what happens when an event of that type occurs, by specifying the caused state changes and follow-up events. In OESjs, event rules are coded as onEvent methods of the class that implements the event type. These methods return a set of events (more precisely, a set of JS objects representing events).

Notice that in the DES literature, event rule methods are called event routines.

For instance, in the CustomerArrival class, the following event rule method is defined:

class CustomerArrival extends eVENT {
  ...
  onEvent() {
    var followupEvents=[];
    // increment queue length due to newly arrived customer
    this.serviceDesk.queueLength++;
    // update statistics
    sim.stat.arrivedCustomers++;
    if (this.serviceDesk.queueLength > sim.stat.maxQueueLength) {
      sim.stat.maxQueueLength = this.serviceDesk.queueLength;
    }
    // if the service desk is not busy
    if (this.serviceDesk.queueLength === 1) {
      followupEvents.push( new CustomerDeparture({
        occTime: this.occTime + ServiceDesk.serviceTime(),
        serviceDesk: this.serviceDesk
      }));
    }
    return followupEvents;
  }
}

The context of this event rule method is the event that triggers the rule, that is, the variable this references a JS object that represents the triggering event. Thus, the expression this.serviceDesk refers to the service desk object associated with the current customer arrival event, and the statement this.serviceDesk.queueLength++ increments the queueLength attribute of this service desk object (as an immediate state change).

The following event rule method is defined in the CustomerDeparture class.

class CustomerDeparture extends eVENT {
  ...
  onEvent() {
    var followupEvents=[];
    // decrement queue length due to departure
    this.serviceDesk.queueLength--;
    // update statistics
    sim.stat.departedCustomers++;
    // if there are still customers waiting
    if (this.serviceDesk.queueLength > 0) {
      // start next service and schedule its end/departure
      followupEvents.push( new CustomerDeparture({
        occTime: this.occTime + ServiceDesk.serviceTime(),
        serviceDesk: this.serviceDesk
      }));
    }
    return followupEvents;
  }
}

2.2.6. Library Methods for Sampling from Probability Distribution Functions

Random variables are implemented as functions that sample from specific probability distribution functions (PDFs). Simulation frameworks typically provide a library of predefined parametrized PDF sampling methods, which can be bound to a (possibly seeded) stream of pseudo-random numbers.

The OESjs-Core0 simulator does not support seeding and provides only two predefined parametrized PDF sampling functions:

Probability Distribution FunctionOES-Core-0 Library MethodExample
UniformgetUniformRandomNumber( lowerBound, upperBound)math.getUniformRandomNumber( 0.5, 1.5)
Discrete UniformgetUniformRandomInteger( lowerBound, upperBound)math.getUniformRandomInteger( 1, 6)

2.3. Simulation Scenarios

For obtaining a complete executable simulation scenario, a simulation model has to be complemented with simulation parameter settings and an initial system state.

In general, we may have more than one simulation scenario for a simulation model. For instance, the same model could be used in two different scenarios with different initial states. However, only from OES Core 1 upwards, multiple scenarios per model will be supported.

A simulation scenario consists of

  1. a simulation model,
  2. simulation parameter settings, such as setting a value for durationInSimTime, and
  3. an initial state definition.

An empty template for the simulation.js file has the following structure:

// ***** Simulation Model *******************
sim.model.time = "...";  // discrete or continuous
sim.model.timeIncrement = ...;   // optional
sim.model.timeUnit = "...";  // optional (ms|s|min|hour|day|week|month|year)
sim.model.v.aModelVariable = ...;  // (developer-defined) model variables
sim.model.f.aModelFunction = ...;  // (developer-defined) model functions
sim.model.objectTypes = [...];  // (developer-defined) object types
sim.model.eventTypes = [...];  // (developer-defined) event types
// ***** Simulation Parameters **************
sim.scenario.durationInSimTime = ...;
// ***** Initial State **********************
sim.scenario.setupInitialState = function () {
  // Initialize model variables
  ...
  // Create initial objects
  ...
  // Schedule initial events
  ...
};
// ***** Ex-Post Statistics *****************
sim.model.statistics = {...};

We briefly discuss each group of scenario information items in the following sub-sections.

2.3.1. Simulation Scenario Parameters

In OESjs-Core0, the only simulation parameter is durationInSimTime, which defines the duration of a simulation run in terms of simulation time. By default, when this attribute is not set, the simulation runs forever.

2.3.2. Initial State

Defining an initial state means:

  1. assigning initial values to global model variables, if there are any;
  2. defining which objects exist initially, and assigning initial values to their properties;
  3. defining which events are scheduled initially.

A setupInitialState procedure takes care of these initial state definitions. A global model variable is initialized in the following way:

sim.scenario.setupInitialState = function () {
  // Initialize model variables
  sim.model.v.queueLength = 0;
  // Create initial objects
  ...
  // Schedule initial events
  ...
};

An initial state object is created by instantiating an object type of the simulation model with suitable initial property values, as shown in the following example:

sim.scenario.setupInitialState = function () {
  // Initialize model variables
  ...
  // Create initial objects
  let serviceDesk1 = new ServiceDesk({id: 1, queueLength: 0});
  // Schedule initial events
  ...
};

Notice that object IDs are positive integers, but when used as keys in the map sim.objects, they are converted to strings.

Instead of assigning a fixed value to a property like queueLength for defining an object's initial state, as in queueLength: 0, we can also assign it a fixed expression, as in queueLength: Math.round(12/30).

An initial event is scheduled by adding it to the Future Events List (FEL), as shown in the following example:

sim.scenario.setupInitialState = function () {
  // Initialize model variables
  ...
  // Create initial objects
  let desk1 = new ServiceDesk({id: 1, queueLength: 0});
  // Schedule initial events
  sim.FEL.add( new CustomerArrival({occTime:1, serviceDesk: desk1}));
};

2.3.3. Using Model Parameters in the Initial State

Initial objects or events can be parametrized with the help of model parameters.

2.4. Statistics

In scientific and engineering simulation projects the main goal is getting estimates of the values of certain variables or performance indicators with the help of statistical methods. In educational simulations, statistics can be used for observing simulation runs and for learning the dynamics of a simulation model.

For collecting statistics, suitable statistics variables have to be defined, as in the following example:

sim.model.setupStatistics = function () {
  sim.stat.arrivedCustomers = 0;
  sim.stat.departedCustomers = 0;
  sim.stat.maxQueueLength = 0;
};

Statistics variables have to be updated in onEvent methods. For instance, the variables arrivedCustomers and maxQueueLength are updated in the onEvent method of the CustomerArrival event class:

class CustomerArrival extends eVENT {
  ...
  onEvent() {
    ...
    // update statistics
    sim.stat.arrivedCustomers++;
    if (this.serviceDesk.queueLength > sim.stat.maxQueueLength) {
      sim.stat.maxQueueLength = this.serviceDesk.queueLength;
    }
    ...
  }
}

In certain cases, a statistics variable can only be computed at the end of a simulation run. For this purpose, there is the option to define a computeFinalStatistics procedure:

sim.model.computeFinalStatistics = function () {
  // percentage of business days without stock-outs
  sim.stat.serviceLevel = (sim.time - sim.stat.nmrOfStockOuts) / sim.time * 100;
};

After running a simulation scenario, the statistics results are shown in a table:

Table 2-2. Statistics
arrivedCustomers289
departedCustomers288
maxQueueLength4

2.5. Simulation Experiments

There are different types of simulation experiments. In the simplest case, a simulation scenario is run repeatedly for being able to compute aggregate statistics.

An experiment type is defined for a given simulation model and an experiment of that type is run on top of a given simulation scenario for that model.

A simple experiment type is defined with a sim.experimentType record on top of a model by defining (1) the number of replications and (2) possibly a list of seed values, one for each replication. The following code shows an example of a simple experiment type definition:

1
2
3
4
sim.experimentType = {
  title: "Simple Experiment with 10 replications, each running for 1000 time units (days)",
  nmrOfReplications: 10
};

Running this simple experiment means running the underlying scenario 10 times. The resulting statistics are composed of the statistics for each replication complemented with summary statistics listing averages, standard deviations, min/max values and confidence intervals, as shown in the following table:

Experiment Results
ReplicationStatistics
arrivedCustomersdepartedCustomersmaxQueueLength
12852837
22742746
32852854
42872865
52842846
63002994
72882865
82862844
92862854
102952936
Average287285.95.1
Std.dev.6.8486.5061.101
Minimum2742744
Maximum3002997
CI Lower282.9281.94.4
CI Upper291289.65.7

2.6. Using the Simulation Log

The OESjs-Core0 simulator can generate a simulation log, which allows to inspect the evolving states of a simulation run. Inspecting the simulation log can help to understand the dynamics of a model, or it can be used for finding logical flaws in it.

The contents of the simulation log can be controlled by defining labels for those object properties that are to be displayed in the log. For instance, in the case of the Service-Desk-1 model, a label "qLen" is defined for the queueLength property of ServiceDesk objects by setting

ServiceDesk.labels = {"queueLength":"qLen"};

This results in the following simulation log:

StepTimeSystem StateFuture Events
00ServiceDesk-1{ qLen: 0}CustomerArrival@1
11ServiceDesk-1{ qLen: 1}CustomerDeparture@5, CustomerArrival@6
25ServiceDesk-1{ qLen: 0}CustomerArrival@6
36ServiceDesk-1{ qLen: 1}CustomerArrival@7, CustomerDeparture@10
47ServiceDesk-1{ qLen: 2}CustomerDeparture@10, CustomerArrival@10
510ServiceDesk-1{ qLen: 2}CustomerArrival@12, CustomerDeparture@13
612ServiceDesk-1{ qLen: 3}CustomerDeparture@13, CustomerArrival@16
713ServiceDesk-1{ qLen: 2}CustomerArrival@16, CustomerDeparture@16
816ServiceDesk-1{ qLen: 2}CustomerDeparture@19, CustomerArrival@21
919ServiceDesk-1{ qLen: 1}CustomerArrival@21, CustomerDeparture@23

Appendix A. Simulator Architecture

OES Core 0 is the minimal architecture for an OE simulator, supporting

The OES Core 0 simulator's information architecture is described by the following class diagram, which defines the names of classes, properties and methods/functions:

The Run-Standalone-Scenario procedure is described by the following activity diagram:

Index

C

  • continuous dynamic system, 1

D

  • discrete dynamic system, 1
  • discrete event system, 1
  • dynamic system, 1

E

  • event routine, 1
  • event rule, 1
  • exogenous event, 1

O

  • occurrence time, 1

P

  • probability distribution function, 1

R

  • random variable, 1, 2
  • recurrence, 1, 2