@anchor{chap:rv}
@node Random variables
@chapter Random variables

@menu
* Quick Overview::
* Background::
* Seeding and independent replications::
* class RandomVariable::
* Base class public API::
* Types of RandomVariables::
* Semantics of RandomVariable objects::
* Using other PRNG::
* More advanced usage::
* Publishing your results::
* Summary::
@end menu

ns-3 contains a built-in pseudo-random number generator (PRNG).
It is important for serious users of the simulator to understand
the functionality, configuration, and usage of this PRNG, and
to decide whether it is sufficient for his or her research use.  

@node Quick Overview
@section Quick Overview

ns-3 random numbers are provided via instances of @code{class RandomVariable}.
@itemize @bullet
@item @strong{by default, ns-3 simulations use a fixed seed}; if there is any 
randomness in the simulation, each run of the program will yield identical
results unless the seed and/or run number is changed.  
@itemize @bullet
@item @strong{in ns-3.3 and earlier, ns-3 simulations used a random seed by 
default; this marks a change in policy starting with ns-3.4}
@end itemize
@item to obtain randomness across multiple simulation runs, you must either
set the seed differently or set the run number differently.  To set a seed, call
@code{SeedManager::SetSeed (uint32_t)} at the beginning of the program;
to set a run number with the same seed, call
@code{SeedManager::SetRun (uint32_t)} at the beginning of the program;
@xref{Seeding and independent replications}
@item each RandomVariable used in ns-3 has a virtual random number 
generator associated with it; all random variables use either a fixed
or random seed based on the use of the global seed (previous bullet);
@item if you intend to perform multiple runs of the same scenario, with
different random numbers, please be sure to read the section on how to
perform independent replications: @xref{Seeding and independent replications}.
@end itemize

Read further for more explanation about the random number facility for
ns-3.

@node Background
@section Background

Simulations use a lot of random numbers; one study 
found that most network simulations spend as much as 50% 
of the CPU generating random numbers.  Simulation users need
to be concerned with the quality of the (pseudo) random numbers and
the independence between different streams of random numbers.  

Users need to be concerned with a few issues, such as:
@itemize @bullet
@item the seeding of the random number generator and whether a 
simulation outcome is deterministic or not,
@item how to acquire different streams of random numbers that are 
independent from one another, and 
@item how long it takes for streams to cycle
@end itemize 

We will introduce a few terms here:  a RNG provides a long sequence
of (pseudo) random numbers.
The length of this sequence is called the @emph{cycle length}
or @emph{period}, after which the RNG will repeat itself.  
This sequence can
be  partitioned into disjoint @emph{streams}.  A stream of a
RNG is a contiguous subset or block of the RNG sequence.
For instance, if the
RNG period is of length N, and two streams are provided from this
RNG, then
the first stream might use the first N/2 values and the second
stream might produce the second N/2 values.  An important property
here is that the two streams are uncorrelated.  Likewise, each
stream can be partitioned disjointedly to a number of 
uncorrelated @emph{substreams}.  The underlying RNG hopefully
produces a pseudo-random sequence of numbers with a very long
cycle length, and partitions this into streams and substreams in an 
efficient manner.
  
ns-3 uses the same underlying random number generator as does
ns-2:  the MRG32k3a generator from Pierre L'Ecuyer.  A
detailed description can be found in 
@uref{http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf,,}.
The MRG32k3a generator provides 1.8x10^19 independent
streams of random numbers, each of which consists of
2.3x10^15 substreams. Each substream has a period
(@emph{i.e.}, the number of random numbers before overlap) of
7.6x10^22. The period of the entire generator is
3.1x10^57. 

Class @code{ns3::RandomVariable} is the public interface to this 
underlying random number generator.  When users create new
RandomVariables (such as UniformVariable, ExponentialVariable, 
etc.), they create an object that uses one of the distinct, independent
streams of the random number generator.  Therefore, each
object of type RandomVariable has, conceptually, its own "virtual" RNG.
Furthermore, each RandomVariable can be configured to use
one of the set of substreams drawn from the main stream.

An alternate implementation would be to allow each RandomVariable
to have its own (differently seeded) RNG.  However, we cannot 
guarantee as strongly that the different sequences would be 
uncorrelated in such a case; hence, we prefer to use a single RNG
and streams and substreams from it.

@anchor{chap:rv:indeprep}
@node Seeding and independent replications
@section Seeding and independent replications

ns-3 simulations can be configured to produce deterministic or
random results.  If the ns-3 simulation is configured to use 
a fixed, deterministic seed with the same run number, it should give 
the same output each time it is run.

By default, ns-3 simulations use a fixed seed and run number.
These values are stored in two @code{ns3::GlobalValue} instances:
@code{g_rngSeed} and @code{g_rngRun}.

A typical use case is to run a simulation as a sequence of independent
trials, so as to compute statistics on a large number of independent
runs.  The user can either change the global seed and rerun the 
simulation, or can advance the substream state of the RNG, which is
referred to as incrementing the run number.  

A class @code{ns3::SeedManager ()} provides an API to control
the seeding and run number behavior.
This seeding and substream state setting must be called before any 
random variables are created; e.g.

@verbatim
  SeedManager::SetSeed (3);  // Changes seed from default of 1 to 3
  SeedManager::SetRun (7);  // Changes run number from default of 1 to 7
  // Now, create random variables
  UniformVariable x(0,10);
  ExponentialVariable y(2902);
  ...
@end verbatim

Which is better, setting a new seed or advancing the substream state?
There is no guarantee that the streams
produced by two random seeds will not overlap.  The only way to
guarantee that two streams do not overlap is to use the substream
capability provided by the RNG implementation.
@strong{Therefore, use the substream capability to produce
multiple independent runs of the same simulation.}
In other words, the more statistically rigorous way to configure
multiple independent replications is to use a fixed seed and to
advance the run number.  This implementation allows for a maximum of
2.3x10^15 independent replications using the substreams. 

For ease of use, it is not necessary to control the seed and run number
from within the program; the user can set the 
@code{NS_GLOBAL_VALUE} environment variable as follows:
@verbatim
  NS_GLOBAL_VALUE="RngRun=3" ./waf --run program-name
@end verbatim

Another way to control this is by passing a command-line argument; since
this is an ns-3 GlobalValue instance, it is equivalently done such as follows:
@verbatim
  ./waf --command-template="%s --RngRun=3" --run program-name
@end verbatim
or, if you are running programs directly outside of waf:
@verbatim
  ./build/optimized/scratch/program-name --RngRun=3
@end verbatim
The above command-line variants make it easy to run lots of different
runs from a shell script by just passing a different RngRun index.

@node class RandomVariable
@section class RandomVariable

All random variables should derive from @code{class RandomVariable}.
This base class provides a few static methods for globally configuring
the behavior of the random number generator.  Derived classes
provide API for drawing random variates from the particular
distribution being supported.

Each RandomVariable created in the simulation is given a generator
that is a new RNGStream from the underlying PRNG.  
Used in this manner, the L'Ecuyer implementation allows for a maximum of
1.8x10^19 random variables.  Each random variable in
a single replication can produce up to 7.6x10^22 random
numbers before overlapping.

@node Base class public API
@section Base class public API

Below are excerpted a few public methods of @code{class RandomVariable}
that access the next value in the substream.
@smallformat
@example
  /**
   * \brief Returns a random double from the underlying distribution
   * \return A floating point random value
   */
  double GetValue (void) const;
  
  /**
   * \brief Returns a random integer integer from the underlying distribution
   * \return  Integer cast of ::GetValue()
   */
  uint32_t GetInteger (void) const;
@end example
@end smallformat

We have already described the seeding configuration above.  Different
RandomVariable subclasses may have additional API.

@node Types of RandomVariables
@section Types of RandomVariables

The following types of random variables are provided, and are documented
in the ns-3 Doxygen or by reading @code{src/core/random-variable.h}.  Users
can also create their own custom random variables by deriving from
class RandomVariable.
@itemize @bullet
@item @code{class UniformVariable }
@item @code{class ConstantVariable }
@item @code{class SequentialVariable }
@item @code{class ExponentialVariable }
@item @code{class ParetoVariable }
@item @code{class WeibullVariable }
@item @code{class NormalVariable }
@item @code{class EmpiricalVariable }
@item @code{class IntEmpiricalVariable }
@item @code{class DeterministicVariable }
@item @code{class LogNormalVariable }
@item @code{class TriangularVariable }
@item @code{class GammaVariable }
@item @code{class ErlangVariable }
@item @code{class ZipfVariable }
@end itemize

@node Semantics of RandomVariable objects
@section Semantics of RandomVariable objects

RandomVariable objects have value semantics.  This means that they
can be passed by value to functions.  The can also be passed by
reference to const.  RandomVariables do not derive from 
@code{ns3::Object} and we do not use smart pointers to manage them;
they are either allocated on the stack or else users explicitly manage
any heap-allocated RandomVariables.

RandomVariable objects can also be used in ns-3 attributes, which means
that values can be set for them through the ns-3 attribute system.
An example is in the propagation models for WifiNetDevice:
@smallformat
@example
TypeId
RandomPropagationDelayModel::GetTypeId (void)
{ 
  static TypeId tid = TypeId ("ns3::RandomPropagationDelayModel")
    .SetParent<PropagationDelayModel> ()
    .AddConstructor<RandomPropagationDelayModel> ()
    .AddAttribute ("Variable",
                   "The random variable which generates random delays (s).",
                   RandomVariableValue (UniformVariable (0.0, 1.0)),
         MakeRandomVariableAccessor (&RandomPropagationDelayModel::m_variable), 
                   MakeRandomVariableChecker ())
    ;
  return tid;
}
@end example
@end smallformat
Here, the ns-3 user can change the default random variable for this
delay model (which is a UniformVariable ranging from 0 to 1) through
the attribute system.

@node Using other PRNG
@section Using other PRNG

There is presently no support for substituting a different underlying
random number generator (e.g., the GNU Scientific Library or the Akaroa
package).  Patches are welcome.

@node More advanced usage
@section More advanced usage

@emph{To be completed}

@node Publishing your results
@section Publishing your results

When you publish simulation results, a key piece of configuration 
information that you should always state is how you used the
the random number generator.
@itemize @bullet
@item what seeds you used,
@item what RNG you used if not the default,
@item how were independent runs performed,
@item for large simulations, how did you check that you did not cycle.
@end itemize

It is incumbent on the researcher publishing results to include enough
information to allow others to reproduce his or her results.  It is
also incumbent on the researcher to convince oneself that the random
numbers used were statistically valid, and to state in the paper why
such confidence is assumed.

@node Summary
@section Summary

Let's review what things you should do when creating a simulation.

@itemize @bullet
@item Decide whether you are running with a fixed seed or random seed;
a fixed seed is the default, 
@item Decide how you are going to manage independent replications, if
applicable, 
@item Convince yourself that you are not drawing more random values
than the cycle length, if you are running a very long simulation, and
@item When you publish, follow the guidelines above about documenting your
use of the random number generator.
@end itemize

