So far, the lessons on stochastics used the mathematical notion of stochastic distribution to describe how to model stochastic behavior. Simulating a model with stochastic behavior using a computer is however not stochastic at all. Computer systems are deterministic machines, and have no notion of varying results.

Pseudorandom number generator and seed

A pseudorandom number generator is used to create stochastic results instead. It starts with an initial seed, an integer number. From this seed, a function creates a stream of ‘random’ values. When looking at the values there does not seem to be any pattern. It is not truly random however. Using the same seed again gives exactly the same stream of numbers. This is the reason to call the function a pseudorandom number generator, as a true random number generator would never produce the exact same stream of numbers.

Simulation and initial seed

A sample of a distribution uses one or more numbers from the stream to compute its value. The value of the initial seed thus decides the value of all samples drawn in the simulation. By default, a different seed is used each time you run a simulation, leading to different results each time. You can also explicitly state what seed you want to use when simulating a model. See the Stochastic distributions and seeds page of the simulator for information on how to supply a custom seed for simulation.

While doing a stochastic simulation study, performing several experiments with the same initial seed invalidates the results, as it is equivalent to copying the outcome of a single experiment a number of times. On the other hand, when looking for the cause of a bug in the model, performing the exact same experiment is useful as outcomes of previous experiments should match exactly.

Sampling and tuple results

The seed determines the next sampled value. Whenever a distribution is sampled, the seed changes to the one that follows in the stream of random numbers generated by the pseudorandom number generator. This ensures that the next time the distribution is sampled, it results in a different sampled value.

In CIF, the seed is stored with the distribution and its parameters. Therefore, sampling does not only result in the sampled value, it also results in an updated distribution, with the same parameters, but a different seed value.

Consider the following CIF specification:

automaton coin_toss:
  disc dist bool d = bernoulli(0.5);
  disc bool outcome;

    edge do (outcome, d) := sample d goto result;

The bernoulli function to create a Bernoulli distribution with parameter 0.5 (the chance for true). This Bernoulli distribution, along with its parameter and the seed, are stored in variable d. When the distribution in variable d is sampled (sample d), the result is both a sampled value, and a distribution (as a tuple). The distribution is the same distribution with the same parameters, but with an updated seed. The sampled value is usually stored in a variable (outcome in this case). The changed distribution is usually assigned to the same variable that contains the distribution that is sampled, to ensure that we can use the same variable for the next sampling. In other words, variable d is updated with the changed distribution each time it is sampled. The result of sampling is assigned to two variables, using tuple unpacking.