Introduction To Simulation Using Javascript
Introduction To Simulation Using Javascript
Gerd Wagner
Department of Informatics
Brandenburg University of Technology
P. O. Box 101344
03013 Cottbus, GERMANY
ABSTRACT
JavaScript is a dynamic functional object-oriented programming language that can not only be used for
enriching a web page, but also for implementing various kinds of web applications, including web-based
simulations, which can be executed on front-end devices, such as mobile phones, tablets and desktop
computers, as well as on powerful back-end computers, possibly in some cloud infrastructure. Although
JavaScript cannot compete with strongly typed compiled languages (such as C++, Java and C#) on speed,
it provides sufficient performance for many types of simulations and outperforms its competitors on ease
of use and developer productivity, especially for web-based simulation. This tutorial provides a two-fold
introduction: (1) to JavaScript programming using the topic of simulation, and (2) to simulation using the
programming language JavaScript. It shows how to implement a Monte Carlo simulation, a continuous
state change simulation and a discrete event simulation, using the power of JavaScript and the web.
1 INTRODUCTION TO SIMULATION
“Simulation” is an umbrella term subsuming a variety of use cases and approaches. Since we are only
interested in computer simulation in this article, we can say that a simulation is provided by any computer
program that imitates a static structure or a dynamic system of the real-world. This broad definition
includes using
a general-purpose programming language such as C++, Java, JavaScript, C#, etc., for imple-
menting a simulation program, no matter if it is purely ad-hoc or based on a simulation paradigm;
a simulation language such as Simula, SIMAN, Modelica, NetLogo, etc.;
a simulation platform such as Arena, Simio, AnyLogic, etc.;
an implementation of an abstract process formalism such as Petri Nets, State Charts, DEVS,
Event Graphs, Activity Cycle Diagrams, etc.
Three main categories of simulations are often distinguished:
1. Monte Carlo simulation,
2. continuous simulation, and
3. discrete event simulation.
As explained in Wikipedia, Monte Carlo methods are “a broad class of computational algorithms that
rely on repeated random sampling to obtain numerical results”. In principle, this approach can be used to
solve any computational problem involving random variables. When Monte Carlo methods are used in a
program for estimating certain performance indicators of real-world systems, such as in manufacturing or
financial markets, this is often called Monte Carlo simulation, if the program does not involve the
modeling of time and the simulation of state changes, but only a set of input random variables and a set of
equations for computing the resulting output variables.
Continuous simulation, or more precisely: continuous state change simulation, is concerned with
modeling a dynamic real-world system with the help of differential equations describing its state changes
and simulating it by running a computational model based on a numerical solution of the differential
equations. The computational model includes a discretization of the theoretically continuous time model
by choosing a fixed time increment depending on a suitable granularity of time (e.g., 10 ms or 100 ms),
and then running a fixed increment time progression loop that iteratively computes the next values of all
state variables based on their current values.
Normally, continuous simulation is used for simulating continuous dynamic systems, in which
continuous qualities, such as the spatial position or the velocity of a material object, or the temperature of
an amount of matter, are subject to continuous changes. But continuous simulation can also be used for
simulating discrete dynamic systems, such as biological populations or economic systems, by describing
their discrete state changes approximatively with continuous state changes based on differential equa-
tions.
The term Discrete Event Simulation (DES) has been established as an umbrella term subsuming
various kinds of computer simulation approaches, all based on the general idea of making a computational
model of a discrete dynamic system by representing its state with the help of state variables, and
modeling its dynamics by modeling the events that are responsible for its state changes. There is,
however, no generally accepted definition of DES. Simulation textbooks and tutorials avoid defining the
term “DES” in a precise way.
Pegden (2010) explains that the most fundamental DES approach, which he calls the event worldview,
views a discrete dynamic system as a series of instantaneous events that change the state of the system
over time, such that a DES model needs to define the events in the system and model the state changes
that take place when those events occur. This is also the view adopted in DES textbooks, when they
present implemented discrete event simulations based on the computational paradigm of event scheduling
using a future events list and a next-event time progression loop that iteratively invokes the event routines
of all imminent events.
As we have argued in (Guizzardi and Wagner 2010), objects and events are the most fundamental
ontological categories for understanding and describing real-world systems, and therefore, the traditional
event worldview should be extended to an object-event worldview where a system is viewed to consist of
objects the state of which is changed by events. In this broader view, both objects and events are first-
class citizens, the system state is the aggregation of all objects’ states and the simulation model’s state
variables are provided by the attributes of the system’s objects.
Notice that the object-event worldview is also supported, in some sense, by the success of the object-
oriented modeling and programming paradigm in software engineeering, and by the remarkable fact that
it is historically rooted in the concepts of objects, classes and inheritance originally pioneered by the
simulation language Simula.
2 INTRODUCTION TO JAVASCRIPT
JavaScript was developed in 10 days in May 1995 by Brendan Eich, then working at Netscape, as the
HTML scripting language for their browser Navigator 2. Originally, it was intended to be used for
enriching web pages and web user interfaces. A web page could be enriched by (a) generating browser-
specific HTML content or CSS styling, (b) inserting dynamic HTML content, or (c) producing special
audio-visual effects (animations). A web user interface could be enriched by (a) implementing advanced
user interface components, (b) validating user input on the client side, or (c) automatically pre-filling
certain form fields.
Later, after browsers started supporting the ECMAScript 5.1 standard defined in 2011, JavaScript
mutated into a full-fledged programming language that could be used for programming all kinds of
software applications and tools. At the same time, the back-end JavaScript platform Node.js was
149
Wagner
developed and adopted by an increasing number of web developers who appreciated the new possibility
of using JavaScript not only for browser-based front-end development, but also for all kinds of back-end
tasks.
Today, JavaScript is the most widely used programming language (according to certain measures,
such as the statistics on StackOverflow and GitHub), and a powerful platform, which offers many
advantages over other platforms:
1. It's the only language that enjoys native support in web browsers.
2. It's the only universal language in the sense that it allows
a. building web apps with just one programming language. All other languages (like Java and
C#) can only be used on the back-end and need to be combined with front-end JavaScript, so
developers need to master at least two programming languages.
b. executing the same code (e.g., for constraint validation) on the back-end and the front-end.
3. It's the only language that allows dynamic distribution, that is, executing the same code (e.g., for
business computations) either in the back-end or the front-end, depending on run-time conditions
such as the availability of front-end resources.
4. It combines object-oriented with functional programming.
5. Its dynamism allows various forms of meta-programming, which means it enables developers to
program their own programming concepts, like classes and enumerations.
JavaScript is object-oriented (OO), but in a different way than classical OO programming languages
such as Java and C#. There is no explicit class concept in JavaScript. Rather, classes have to be defined in
the form of special objects, either as constructor functions or as factory objects, using certain code
patterns.
Objects can also be created without instantiating a class, in which case they are untyped, and
properties as well as methods can be defined for specific objects independently of any class definition. At
run time, properties and methods can be added to, or removed from, any object and class.
The version of JavaScript that is currently supported by web browsers is called “ECMAScript 5.1”, or
simply “ES5”, but the next two versions, called “ES6” and “ES7”, with lots of added functionality and
improved syntaxes, are around the corner and are already partially supported by current browsers and
back-end JavaScript environments.
After a brief discussion of the most basic language elements of JavaScript, further concepts are
explained on the fly when they are used for implementing a specific simulation. The following sub-
sections are extracted from my JavaScript Summary article (Wagner 2015), which is recommended for
readers who want to learn more about JavaScript.
150
Wagner
The types of variables, array elements, function parameters and return values are not declared and are
normally not checked by JavaScript engines. Type conversion (casting) is performed automatically.
For testing the equality (or inequality) of two primitive data vales, we use the strict equality predicate
expressed with the triple equality symbol === (and !==) instead of the double equality symbol == (and
!=). Otherwise, for instance, the number 2 would be the same as the string "2", since the condition (2 ==
"2") evaluates to true in JavaScript.
where theNameOfMyF is optional. When it is omitted, the function is anonymous. In any case,
functions are invoked via a variable that references the function. In the above case, this means that the
function is invoked with myF(), and not with theNameOfMyF().
JS functions can have inner functions. The closure mechanism allows a JS function using variables
from its outer scope, and a function created in a closure remembers the environment in which it was
created.
151
Wagner
library like jStat or probability-distributions, supporting all common probability distributions, has to be
used.
Figure 1: A wafer map showing cells on the wafer and cells that don't fully lie within the wafer (image by
Moxfyre, CC BY-SA 3.0).
An important issue is the cost per chip resulting from the chip yield per wafer, which depends on
wafer size, chip size and average number of defective chips. In our simplified example, we assume that
chips may be defective due to random contamination of the wafer, for which we assume a uniform
probability distribution over the wafer’s circle area, obtained using polar coordinates.
A simple browser-based JavaScript program consists of an HTML file defining the user interface, and
an embedded reference to an external JavaScript file, as shown in the following HTML code listing:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8">
<title>Wafer Defects Simulation</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>Simulating the Defects on a Wafer</h1>
<table>
<thead>
<tr><th># Defects</th><th>Avg. # Good Chips</th><th>Avg. Chip Price</th></tr>
</thead>
<tbody id="tbody"></tbody>
</table>
<script src="WaferDefectsSimulation.js"></script>
</body>
</html>
In the external JavaScript file "WaferDefectsSimulation.js", we first define three utility procedures:
1. The function getUniformDecimal generates a uniformly distributed random variate between a
lower bound and an upper bound number.
2. The function generateRandomPointOnCircle generates a random point on a circle based on
uniformly distributed random polar coordinates.
3. The procedure createOutputTableRow creates a HTML table row in the user interface for
showing simulation results to the user.
152
Wagner
Then we define a class Wafer in the form of a constructor function with two parameters denoting the
wafer diameter and the chip size:
The repeated random sampling for input variables, which is characteristic for Monte Carlo simulation,
requires a corresponding loop, which is run within a nested for loop over chip sizes and defect frequencies
in a main procedure:
(function main () {
var s=0, k=0, i=0, wafer=null, p=null,
chipSize = 0.0, nmrOfDefects = 0,
totalNmrOfGoodChips = 0, avgNmrOfGoodChips = 0.0;
var nmrOfExperiments = 50; // # repeated simulation experiments
var waferDiameter = 12; // cm
var waferCost = 5000; // US Dollars
// HTML element for tabular output
var tableEl = document.getElementById("tbody");
// loop over 3 chip sizes
for (s=0; s < 3; s=s+1) {
chipSize = 1 + s * 0.5; // 1 cm, 1.5 cm, 2 cm
// create wafer object for computing the # of cells on wafer
wafer = new Wafer( waferDiameter, chipSize);
153
Wagner
Notice that the main procedure is expressed in the syntax of what is called an “immediately invoked
function expression”. This is a JavaScript approach for creating a scope for variables that would otherwise
pollute the global scope.
The wafer defects simulation can be executed, and its full code inspected, by visiting the web page:
http://oxygen.informatik.tu-cottbus.de/modsim/ex/WaferDefectsSimulation.html.
4 CONTINUOUS SIMULATION
We consider a scenario where a car has to follow another car and maintain a “safe distance”, assuming
that it knows its own velocity and the distance to the leading car, from sensor data. The scenario is
illustrated in Fig. 2.
The leading car has its own independent driving behavior model. One or more following cars have a
car-following behavior model based on two parameters: the security time distance between two cars,
symbolically sT, which consists of the time needed to react and a security buffer, and can be set, e.g., to 2
seconds, and a reaction sensitivity coefficient β that defines how quickly a following car adapts its
velocity v when the current distance d falls below, or exceeds, the security distance v ∙ sT. For adapting its
velocity, a car either accelerates or decelerates, and an equation for computing the car’s acceleration a as
a control action is the main issue of a car-following behavior model.
We use the simple linear equation a = β (d – v ∙ sT), which implies a positive value (hence,
acceleration), when the current distance is greater than the security distance, and a negative value (hence,
deceleration), when it is less that the security distance.
154
Wagner
Notice how the names of both roles, leading car and following car, are attached to the two ends of the
association between cars in the diagram on the left-hand side in Fig. 3. This association models the
possibilities that a car may be a following car or a leading car in a sequence of two or more cars.
The general logic of continuous simulation requires iteratively computing the next values of all state
variables based on their current values. In a general approach, we can use a two-element array for each
state variable v, such that v[0] denotes the current value of v, and v[1] denotes its next value.
We can express this in a design model, as shown on the right-hand side in Fig. 3, by declaring the
three attributes position, velocity and acceleration as arrays with two elements, each holding a decimal
number (for simplicity, we choose a one-dimensional space model as part of our simulation design).
Notice that we have allocated these three attributes, and the two corresponding update functions
computeNextVelocity and computeNextPosition, to a more general class of moving objects, of which cars
are a special case. In terms of object-oriented modeling, this means that the Car class inherits these
attributes and functions from the MovingObject class.
Notice also that the computeAcceleration update function, defining the acceleration behavior of a car,
is encapsulated within the Car class, while computeNextVelocity and computeNextPosition simply
implement Newtonian physics (Δv = a ∙ Δt and Δx = v ∙ Δt, respectively) and are encapsulated within the
MovingObject class.
155
Wagner
});
Notice that computeNextVelocity and computeNextPosition do not have any parameters, but operate
directly on the current acceleration attribute this.acc[0], current velocity attribute this.vel[0] and
current position attribute this.pos[0] of moving objects. The class Car is defined as a subclass of
MovingObject by setting its attribute supertypeName to “MovingObject”:
In addition to these two class definitions, the simulation model also includes the following simulation
parameter definitions in the form of class-level (static) attributes of Car:
After defining the simulation model, the next step is to initialize the simulation by initializing the
simulation time variable t as well as the fixed time increment parameter dt and the simulation end time
parameter endTime, and define the initial state of the simulation by defining initial attribute values for the
leading car1 and the following car2:
Finally, we implement the fixed increment time progression loop that iteratively computes the next
values of all state variables based on their current values:
156
Wagner
// advance time
t = t + dt;
}
Notice that we model the acceleration behavior of the leading car1 by starting with an acceleration of
5 m/s2 and then periodically changing it to -5 m/s2 when an upper limit velocity of 33.33 m/s is exceeded
and raising it again to 5 m/s2 when a lower limit of 16.66 m/s is reached.
The car-following simulation, extended by a simulation log, can be executed, and its full code
inspected, by visiting the web page: http://oxygen.informatik.tu-cottbus.de/modsim/ex/CarFollowing-
2cars.html.
157
Wagner
* shop 1
We use the UML stereotypes «exogenous event type» and «caused event type» for categorizing
classes that represent exogenous event types and caused event types, while we use «object type» for
categorizing classes that represent object types.
As explained in (Wagner 2014), for obtaining a complete simulation design using the object-event
worldview, the information design model of Fig. 4 is complemented with a process design model, e.g., in
the form of an event rule design table as in Table 1. Notice that an event rule combines an event type
expression with an event routine specifying immediate state changes of affected objects and (possibly
delayed) follow-up events.
Table 1: Event rule design table for the inventory management simulation.
ON (event type) DO (event routine)
DailyDemand( quantity) @ t IF quantity <= shop.quantityInStock,
decrement shop.quantityInStock by quantity
IF shop.quantityInStock − quantity < reorderLevel AND
shop.quantityInStock > reorderLevel
schedule Delivery @ t + sampleLeadTime()
with quantity := reorderUpToLevel − quantityInStock
ELSE (if quantity > shop.quantityInStock)
increment shop.lostSales by quantity − shop.quantityInStock
and set shop.quantityInStock := 0
Delivery( quantity) @ t Increment shop.quantityInStock by quantity
Since all event types share an occurrenceTime attribute and an applyRule method, it is natural to
define an abstract type Event that encapsulates these features shared by all event types, as shown in Fig. 5
below. This can be implemented as an abstract class with an abstract method applyRule in an object-
oriented (OO) programming language. In this way, the OO mechanism of method overriding can be used
in the implementation of the next-event time progression loop for invoking the applyRule method on the
next event from the future events list. This means that, while in the code of the next-event time
progression loop the abstract Event::applyRule method is used, when executing the loop, the runtime
environment of the OO programming language (in our case, the JavaScript engine) will apply the specific
applyRule method of the respective event type of the currently processed event (such as
Delivery::applyRule).
In JavaScript, the Event hierarchy shown in Fig. 5 can be simplified by dropping the abstract method
from the Event class. Due to its weakly typed nature, JavaScript does not need abstract methods for
method overriding.
158
Wagner
Event
occurrenceTime : Number
applyRule() : Event[*]
DailyDemand
Delivery
quantity : NonNegativeInteger
quantity : PositiveInteger
shop : SingleProductShop
receiver : SingleProductShop
recurrence() : Integer = 1
sampleLeadTime() : Integer {Emp(1:0.2, 2:0.5, 3:0.3)}
sampleQuantity() : Integer = U(5,10)
applyRule() : Event[*]
applyRule() : Event[*]
Notice that, for simplicity, we have defined the lost sales statistics as an attribute of the object class
SingleProductShop. In general, we would rather have special data structures and code for handling the
output statistics variables.
Since event rules are implemented as methods with the pre-defined name applyRule in the event class
concerned, we obtain the following code for the DailyDemand event class:
var DailyDemand = new cLASS({
Name: "DailyDemand",
supertypeName: "Event",
properties: {
"quantity": {range: "PositiveInteger", label:"quant"},
"shop": {range: SingleProductShop}
},
methods: {
"applyRule": function () {...} // see below
}
});
159
Wagner
The applyRule method takes care of all state changes implied by a DailyDemand event, and of scheduling
Delivery follow-up events. It is defined as follows:
"applyRule": function () {
var q = this.quantity,
prevStockLevel = this.shop.quantityInStock,
followUpEvents = [];
// update lostSales if demand quantity greater than stock level
if (q > prevStockLevel) {
this.shop.lostSales += q - prevStockLevel;
}
// update quantityInStock
this.shop.quantityInStock = Math.max( prevStockLevel - q, 0);
// schedule Delivery if stock level falls below reorder level
if (prevStockLevel > this.shop.reorderLevel &&
prevStockLevel - q <= this.shop.reorderLevel) {
followUpEvents.push( new Delivery({
occTime: this.occTime + Delivery.sampleLeadTime(),
quantity: this.shop.reorderUpToLevel - this.shop.quantityInStock,
receiver: this.shop
}));
}
// since DailyDemand is exogeneous, schedule next DailyDemand event
followUpEvents.push( new DailyDemand({
occTime: this.occTime + DailyDemand.recurrence(),
quantity: DailyDemand.sampleQuantity(),
shop: this.shop
}));
return followUpEvents;
}
In addition to the property definitions and the applyRule method definition, we also have the definitions
of the static recurrence method and the static method sampleQuantity implementing the random variable
demand quantity:
DailyDemand.recurrence = function () {
return 1;
};
DailyDemand.sampleQuantity = function () {
return getUniformInteger( 5, 10);
};
In addition, the random variable lead time is implemented with a static method sampleLeadTime:
Delivery.sampleLeadTime = function () {
var r = getRandomInt( 0, 99);
if (r < 25) return 1; // probability 0.25
160
Wagner
The initial state is defined in terms of initial objects and initial events. In our simple example, there is
only one object, which represents a shop:
var tvShop = new SingleProductShop({
name:"TV",
quantityInStock: 80,
reorderLevel: 50,
reorderUpToLevel: 100
});
In addition, the initial future events list FEL is set up with just one initial DailyDemand event as
follows:
var FEL = new EventList();
FEL.add( new DailyDemand({occTime:1, quantity:25, shop: tvShop}));
The future events list drives the next-event time progression loop, the code of which is as follows:
while (simTime < simEnd) {
logSimulationStep( tvShop, FEL);
nextTime = FEL.getNextOccurrenceTime();
// extract and process next events
nextEvents = FEL.removeNextEvents();
for (i=0; i < nextEvents.length; i++) {
e = nextEvents[i];
// apply event rule
followUpEvents = e.applyRule();
// schedule follow-up events
for (j=0; j < followUpEvents.length; j++) {
FEL.add( followUpEvents[j]);
};
};
simTime = nextTime; // advance simulation time
}
161
Wagner
EventList
events : array<Event>
getNextOccurrenceTime() : Number
add(in newEvt : Event)
removeNextEvents() : array<Event>
6 CONCLUSIONS
We have shown how different types of simulations can be implemented with JavaScript. However, for a
lack of space, we were not able to show how to construct a user interface for our simulations. The web
platform offers excellent technologies for building user interfaces with HTML and CSS, and enriching
them with powerful visualizations using SVG and the Canvas API. For learning more about how to build
a web-browser-based simulator supporting advanced concepts, user interfaces and visualization, using
JavaScript, HTML, CSS and SVG, see my book Introduction to Simulation Using JavaScript (Wagner
2016), from which the material of this tutorial has been extracted.
REFERENCES
Guizzardi, G., and G. Wagner. 2010. “Towards an Ontological Foundation of Discrete Event Simulation.”
In: Johansson B, Jain S, Montoya-Torres J, Hugan J, Yücesan E (Eds.), Proceedings of the 2010
Winter Simulation Conference, Baltimore (MD), USA, 652−664. Piscataway, New Jersey: Institute of
Electrical and Electronics Engineers, Inc. Available from: http://www.informs-sim.org/wsc10papers/
059.pdf
Pegden, C.D. 2010. “Advanced Tutorial: Overview of Simulation World Views.” In: Johansson B, Jain S,
Montoya-Torres J, Hugan J, Yücesan E (Eds.), Proceedings of Winter Simulation Conference,
Baltimore (MD), USA, 643−651. Piscataway, New Jersey: Institute of Electrical and Electronics
Engineers, Inc.
Vigna, S. 2016. “PRNG Shootout.” Accessed April 29, 2016. http://xorshift.di.unimi.it/
Wagner, G. 2014. “Tutorial: Information and Process Modeling for Simulation.” In Proceedings of the
2014 Winter Simulation Conference, edited by A. Tolk, S. Y. Diallo, I. O. Ryzhov, L. Yilmaz, S.
Buckley and J. A. Miller, 103–117. Piscataway, New Jersey: Institute of Electrical and Electronics
Engineers, Inc. Available from: http://informs-sim.org/wsc14papers/includes/files/012.pdf
Wagner, G. 2015. “JavaScript Summary.” Accessed April 28, 2016. http://web-engineering.info/
SummariesCheatsheetsPosters.
Wagner, G. 2016. “Introduction to Simulation Using JavaScript.” Accessed July 1, 2016. http://web-
engineering.info/sim
AUTHOR BIOGRAPHIES
GERD WAGNER is Professor of Internet Technology at the Dep. of Informatics, Brandenburg Univer-
sity of Technology, Germany, and Adjunct Associate Professor at the Dep. of Modeling, Simulation and
Visualization Engineering, Old Dominion University, Norfolk, VA, USA. His research interests include
modeling and simulation, foundational ontologies, knowledge representation and web engineering. His
email address is G.Wagner@b-tu.de.
162