Stochastic Simulation in Java
Simulation models can be implemented in many ways  . One can use general-purpose programming languages such as FORTRAN, C, C++, Java, or specialized simulation languages such as GPSS, SIMAN, and SIMSCRIPT. The general-purpose languages may be more familiar to the programmer, but usually do not have the necessary built-in tools to perform simulation. Implementing a model can become complex and tedious. Specialized simulation languages must be learned before models can be implemented, and they are not as widely available and supported as the most popular general-purpose languages.
Over the past few decades, commercial simulation tools with point-and-click graphical user interfaces such as Arena, Automod, Witness, and many others, have become by far the most widely used tools to develop simulation models. Among their main advantages, these tools do not require knowledge of a programming language, provide graphical animation, have automatic facilities to collect statistics and perform experiments, and can sometimes perform optimization to a certain extent. On the other hand, these specialized simulation tools, especially the point-and-click tools, are often too restrictive, because they are usually targeted at a limited class of models. With these tools, simulating a system whose logic is complicated or unconventional may become quite difficult. All the graphical and automatic devices also tend to slow down the simulation significantly. Fast execution times are important for example in a context of optimization, where thousands of variants of a base system may have to be simulated, or for on-line applications where a fast response time is required.
SSJ is an organized set of packages whose purpose is to facilitate simulation programming in the Java language. A first description was given in  . Some of the tools can also be used for modeling (e.g., selecting and fitting distributions). A simulation library, such as SSJ, extends the Java programming language to equip it with the necessary tools for implementing complex models. One can use a familiar programming language, such as Java, with high-level tools for simulation. A simulation project can be divided in several tasks, from modeling to implementation  . SSJ provides tools for model implementation and validation. As these lines are being written, SSJ is still growing. Several new packages, classes, and methods will certainly be added in forthcoming years and others will be refined.
The facilities offered are grouped into different packages, each one having its own user’s guide, in the form of a PDF file. There is also a set of commented examples of simulation programs in a separate directory with its own guide. Programs are given for some of the examples used in the books of Law and Kelton  and Glasserman  , for instance. The best way to learn about SSJ, at the beginning, is probably to study these examples and refer to the user guides of the different packages when needed. The PDF files are the official documentation. There is also a simplified on-line documentation in HTML format, produced via
The packages currently offered are the following:
umontreal.ssj.util contains utility classes used in the implementation of SSJ, and which are often useful elsewhere. For example, there are timers (for CPU usage), utilities to read or format numbers and arrays from/to text, operations on binary vectors and matrices, some mathematical functions and constants, root-finding tools, facilities for SQL database interface, and so on.
umontreal.ssj.util.sort contains utility classes to sort multi-dimensional points.
umontreal.ssj.probdist contains a set of Java classes providing methods to compute mass, density, distribution, complementary distribution, and inverse distribution functions for many discrete and continuous probability distributions, as well as estimating the parameters of these distributions.
umontreal.ssj.probdistmulti contains a set of Java classes providing methods to compute mass, density, distribution, complementary distribution, for some multi-dimensionnal discrete and continuous probability distributions.
umontreal.ssj.rng provides facilities for generating uniform random numbers over the interval \((0,1)\), or over a given range of integer values, and other types of simple random objects such as random permutations.
umontreal.ssj.hups provides classes implementing highly uniform point sets and sequences (HUPS), also called low-discrepancy sets and sequences, and tools for their randomization.
umontreal.ssj.randvar provides a collection of classes for non-uniform random variate generation, primarily from standard distributions.
umontreal.ssj.randvarmulti provides a collection of classes for random number generators for some multi-dimensional distributions.
umontreal::ssj::gof contains tools for performing univariate goodness-of-fit (GOF) statistical tests.
umontreal::ssj::stat provides elementary tools for collecting statistics and computing confidence intervals.
umontreal::ssj::stat::list this subpackage of
stat provides support to manage lists of statistical collectors.
umontreal::ssj::stat::list::lincv this subpackage of
stat.list provides classes that help implement control variables on lists of collectors.
umontreal::ssj::simevents provides and manages the event-driven simulation facilities as well as the simulation clock. Can manage several simulations in parallel, in the same program.
umontreal.ssj.simevents.eventlist this subpackage of
simevents offers several kinds of event list implementations.
umontreal.ssj.functions contains classes that allow one to pass an arbitrary function of one variable as argument to a method and to apply elementary mathematical operations on generic functions.
umontreal::ssj::functionfit provides basic facilities for curve fitting and interpolation with polynomials.
umontreal::ssj::charts provides tools for easy construction, visualization, and customization of \(xy\) plots, histograms, and empirical styled charts from a Java program.
umontreal::ssj::markovchainrqmc contains classes related to Markov chains simulation using randomized quasi-Monte Carlo.
umontreal.ssj.stochprocess implements different kinds of stochastic processes.
SSJ uses some classes from other free Java libraries.
The Colt library , developed at the Centre Européen de Recherche Nucléaire (CERN) in Geneva  , is a large library that provides a wide range of facilities for high performance scientific and technical computing in Java. SSJ uses the class DoubleArrayList from Colt in a few of its classes, namely in packages umontreal::ssj::stat and umontreal.ssj.hups. The reason is that this class provides a very efficient and convenient implementation of an (automatically) extensible array of
double, together with several methods for computing statistics for the observations stored in the array (see, e.g.,
Descriptive). The Colt library is distributed with the SSJ package as colt.jar. It must be added in the CLASSPATH environment variable.
The linear_algebra library is based on public domain LINPACK routines. They were translated from Fortran to Java by Steve Verrill at the USDA Forest Products Laboratory Madison, Wisconsin, USA. The optimization package of Steve Verrill includes Java translations of the MINPACK routines  for nonlinear least squares problems as well as UNCMIN routines  for unconstrained optimization. They were translated from Fortran to Java by Steve Verrill and are in the public domain. They are included in the SSJ distribution as the optimization.jar archive. It is used only in the
probdist package to compute maximum likelihood estimators.
JFreeChart is a free Java library that can generate a wide variety of charts and plots for use in applications, applets and servlets. JFreeChart currently supports, amongst others, bar charts, pie charts, line charts, XY-plots, histograms, scatter plots and time series plots. It is distributed with SSJ as jfreechart-*.jar. JCommon is a free general purpose Java library containing many useful classes used by JFreeChart and other Java packages. It is distributed with SSJ as jcommon-*.jar. JFreeChart (and JCommon) are used in the SSJ package charts to create different kinds of charts.
SSJ also provides an interface to the UNURAN library for nonuniform random number generation  , in the umontreal.ssj.randvar package. UNURAN does not have to be installed to be used with SSJ, because it is linked statically with the appropriate SSJ native library. However, the UNURAN documentation will be required to take full advantage of the library.
Random numbers feed simulation models and allow one to compute statistics. To generate random numbers from any probability distribution, uniform random numbers are required. Such numbers are uniformly distributed in the \([0,1)\) interval, i.e., the probability of getting a given number \(x\) in that interval is the same for all values of \(x\in[0,1)\). Any generated number \(x\) is also independent from any previous or future generated numbers. Although the generated uniforms are not truly independent since one uniform is obtained from the previous uniforms by a mathematical formula, one can consider them independent for simulation purposes. Selection of a random number generator is based on several criteria such as uniformity, performance, and portability  . The package umontreal.ssj.rng contains the needed tools to generate such numbers. It defines an interface called umontreal.ssj.rng.RandomStream implemented by any random number generator supported by SSJ. This interface allows one to easily interchange random number generators since they are accessed through the same set of methods specified by the interface. Only the random number generator setup depends on the type of generator that was chosen.
If one wants to replace uniform random numbers with low-discrepancy point sets for variance reduction, the package umontreal.ssj.hups contains all the necessary facilities. Such highly uniform point sets all inherit from the umontreal.ssj.hups.PointSet which provides a umontreal.ssj.hups.PointSetIterator extending umontreal.ssj.rng.RandomStream. The replacement can be easily done without modifying the model implementation, except the setup-time code.
To generate non-uniform random numbers, one must select a probability distribution based on the empirical data  . SSJ does not provide probability distribution estimation tools, but goodness of fit tests are included to help in model validation. The package umontreal.ssj.probdist contains several standard, commonly-used, probability distributions. It supports discrete and continuous distributions through two different abstract base classes: umontreal.ssj.probdist.ContinuousDistribution and umontreal.ssj.probdist.DiscreteDistribution, respectively. Again, since the distributions inherit from a common class, their access can be independent from the selected distribution, except for the setup case. One can compute the density/mass, distribution, complementary, and inverse distribution functions. These facilities are also accessible through static methods implemented in each distribution class if one does not want to create objects or needs distributions whose parameters vary in time. However, setup-time operations must be performed for each operation, which can be inefficient for certain distributions.
To generate non-uniform random numbers, the packages umontreal.ssj.rng (or umontreal.ssj.hups ) and umontreal.ssj.probdist must be used together. The simplest generation method is to generate a uniform random number using a generator implementing umontreal.ssj.rng.RandomStream (or get a coordinate using a point set iterator) and to apply inversion by using the selected umontreal.ssj.probdist distribution’s umontreal.ssj.probdist.ContinuousDistribution.inverseF method. However, inversion is not the only generation method and sometimes not the most efficient. For some distributions, closed-form inverse functions or fast inversion algorithms exist. For others, inversion is performed using binary or even linear search. In such cases, the performance and precision depends on the complexity of the distribution function which is calculated several times for one inverse. The package umontreal.ssj.randvar acts as glue between uniform random number generators and probability distributions. Continuous or discrete random number generators also inherits from common base classes, namely umontreal.ssj.randvar.RandomVariateGen and umontreal.ssj.randvar.RandomVariateGenInt. All generators use a random stream and a probability distribution for their construction. As opposed to umontreal.ssj.probdist, one can directly instantiate umontreal.ssj.randvar.RandomVariateGen or umontreal.ssj.randvar.RandomVariateGenInt. However, in such cases, only inversion generation method will be available. To use an alternate generation method, one must instantiate a specialized generator class and switch to the given generation algorithm using an object method. Each specialized class also provides static method which perform the same action. Although they allow one to avoid object creation, their signatures are specific to the used distribution and they have to perform setup-time operations on each variate generation, which can become inefficient.
SSJ supports discrete-event, process-driven, continuous or mixed simulation. The discrete-event and continuous simulation are managed by the package umontreal::ssj::simevents. This package manages the simulation clock and the event list, two essential components for all discrete-event simulations. The simulation clock tracks the simulation time whereas the event list stores the scheduled events to execute them in the right order. Events are user-defined subclasses of umontreal.ssj.simevents.Event. When an event occurs, any type of actions can then be taken. The package provides a class called umontreal.ssj.simevents.LinkedListStat<E> which implements a linked list supporting statistical collection. Continuous simulation can be performed using the class umontreal.ssj.simevents.Continuous. It uses the event framework to resolve differential equations numerically at fixed steps in the simulation time.
The package umontreal::ssj::stat provides basic tools for statistical collection. Statistics are collected using statistical probes, i.e, objects implementing the abstract class umontreal.ssj.stat.StatProbe. Two types of probes are supported. The umontreal.ssj.stat.Tally allows to collect observations of the form \(X_1,…,X_n\) whereas umontreal.ssj.simevents.Accumulate collects statistics for a continuous variable evolving in simulation time. During the simulation, one can add observations to such probes. After the simulation, measures can be obtained, such as sample average, sample standard deviation or confidence interval. A statistical report can be obtained for all probes. The package also provides a way to detach statistical collection from the model implementation by using bound properties.
To test a proposed model against empirical data, goodness of fit tests are provided in the package umontreal::ssj::gof. Such tests, e.g. Kolmogorov-Smirnov or Anderson-Darling, compute a statistic using the empirical observations and the proposed distribution. The empirical observations are given as an array whereas the distribution is given as a umontreal.ssj.probdist object. From the computed statistic, it is possible to compute the \(p\)-value which is useful to evaluate the significance of the test.
example.pdf file, in the
doc/pdf subdirectory of the SSJ distribution, explains simulation examples implemented using SSJ. This may be the best starting point to learn SSJ. O ne can find additional information and references in the PDF version of this documentation, available in the
doc/pdf subdirectory of the SSJ distribution.
very package introduced here contains its own reference documentation as a PDF file, in the
doc/pdf subdirectory. This documentation describes in more details how to use the package and provides a description of each class and method.
SSJ was designed and implemented under the supervision of Pierre L’Ecuyer, with the contribution of the following persons
Mathieu Bague, Sylvain Bonnet, Éric Buist, Maxime Dion, Yves Edel, Regina H. S. Hong, Alexander Keller, Pierre L’Ecuyer, Étienne Marcotte, Lakhdar Meliani, François Panneton, Jean-Sebastien Parent-Chartier, Richard Simard, Clément Teule, Pierre-Alexandre Tremblay, Jean Vaucher.
Its development has been supported by NSERC-Canada grant No. ODGP0110050, NATEQ-Québec grant No. 02ER3218, a Killam fellowship, and a Canada Research Chair to the author.