update manual documentation on random variables
authorTom Henderson <tomh@tomh.org>
Tue, 10 Jul 2012 21:52:04 -0700
changeset 8876 3c9838107d8d
parent 8875 c98768d0be38
child 8877 e322283a44dc
update manual documentation on random variables
doc/manual/source/random-variables.rst
--- a/doc/manual/source/random-variables.rst	Tue Jul 10 21:51:44 2012 -0700
+++ b/doc/manual/source/random-variables.rst	Tue Jul 10 21:52:04 2012 -0700
@@ -12,7 +12,7 @@
 **************
 
 |ns3| random numbers are provided via instances of
-:cpp:class:`ns3::RandomVariable`.
+:cpp:class:`ns3::RandomVariableStream`.
 
 * by default, |ns3| simulations use a fixed seed; if there is any randomness in
   the simulation, each run of the program will yield identical results unless
@@ -21,13 +21,18 @@
 * in *ns-3.3* and earlier, |ns3| simulations used a random seed by default; this
   marks a change in policy starting with *ns-3.4*.
 
+* in *ns-3.14* and earlier, |ns3| simulations used a different wrapper class
+  called :cpp:class:`ns3::RandomVariable`.  As of *ns-3.15*, this class has been
+  replaced by :cpp:class:`ns3::RandomVariableStream`; the underlying pseudo-random
+  number generator has not changed.
+
 * 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
   :cpp:func:`ns3::SeedManager::SetSeed` at the beginning of the program; to set
   a run number with the same seed, call :cpp:func:`ns3::SeedManager::SetRun` at
   the beginning of the program; see :ref:`seeding-and-independent-replications`.
 
-* each RandomVariable used in |ns3| has a virtual random number generator
+* each RandomVariableStream used in |ns3| 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);
 
@@ -82,14 +87,14 @@
 :math:`7.6x10^{22}`. The period of the entire generator is :math:`3.1x10^{57}`. 
 
 
-Class :cpp:class:`ns3::RandomVariable` is the public interface to this
-underlying random number generator.  When users create new ``RandomVariables``
-(such as :cpp:class:`ns3::UniformVariable`,
-:cpp:class:`ns3::ExponentialVariable`, etc.), they create an object that uses
+Class :cpp:class:`ns3::RandomVariableStream` is the public interface to this
+underlying random number generator.  When users create new random variables
+(such as :cpp:class:`ns3::UniformRandomVariable`,
+:cpp:class:`ns3::ExponentialRandomVariable`, etc.), they create an object that uses
 one of the distinct, independent streams of the random number generator.
-Therefore, each object of type :cpp:class:`ns3::RandomVariable` has,
+Therefore, each object of type :cpp:class:`ns3::RandomVariableStream` has,
 conceptually, its own "virtual" RNG.  Furthermore, each
-:cpp:class:`ns3::RandomVariable` can be configured to use one of the set of
+:cpp:class:`ns3::RandomVariableStream` 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
@@ -122,8 +127,8 @@
   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);
+  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
+  Ptr<ExponentialRandomVariable> y = CreateObject<ExponentialRandomVarlable> ();
   ...
 
 Which is better, setting a new seed or advancing the substream state?  There is
@@ -154,16 +159,16 @@
 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.
 
-Class RandomVariable
-********************
+Class RandomVariableStream
+**************************
 
 All random variables should derive from class :cpp:class:`RandomVariable`. This
-base class provides a few static methods for globally configuring the behavior
+base class provides a few 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
+Each RandomVariableStream 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 :math:`1.8x10^19` random variables.  Each
 random variable in a single replication can produce up to :math:`7.6x10^22`
 random numbers before overlapping.
@@ -171,7 +176,7 @@
 Base class public API
 *********************
 
-Below are excerpted a few public methods of class :cpp:class:`RandomVariable`
+Below are excerpted a few public methods of class :cpp:class:`RandomVariableStream`
 that access the next value in the substream.::
 
   /**
@@ -181,7 +186,7 @@
   double GetValue (void) const;
   
   /**
-   * \brief Returns a random integer integer from the underlying distribution
+   * \brief Returns a random integer from the underlying distribution
    * \return  Integer cast of ::GetValue()
    */
   uint32_t GetInteger (void) const;
@@ -193,36 +198,33 @@
 ************************
 
 The following types of random variables are provided, and are documented in the
-|ns3| Doxygen or by reading ``src/core/model/random-variable.h``.  Users can also
-create their own custom random variables by deriving from class
-:cpp:class:`RandomVariable`.
+|ns3| Doxygen or by reading ``src/core/model/random-variable-stream.h``.  Users 
+can also create their own custom random variables by deriving from class
+:cpp:class:`RandomVariableStream`.
 
-* class :cpp:class:`UniformVariable`
-* class :cpp:class:`ConstantVariable`
-* class :cpp:class:`SequentialVariable`
-* class :cpp:class:`ExponentialVariable`
-* class :cpp:class:`ParetoVariable`
-* class :cpp:class:`WeibullVariable`
-* class :cpp:class:`NormalVariable`
-* class :cpp:class:`EmpiricalVariable`
-* class :cpp:class:`IntEmpiricalVariable`
-* class :cpp:class:`DeterministicVariable`
-* class :cpp:class:`LogNormalVariable`
-* class :cpp:class:`TriangularVariable`
-* class :cpp:class:`GammaVariable`
-* class :cpp:class:`ErlangVariable`
-* class :cpp:class:`ZipfVariable`
+* class :cpp:class:`UniformRandomVariable`
+* class :cpp:class:`ConstantRandomVariable`
+* class :cpp:class:`SequentialRandomVariable`
+* class :cpp:class:`ExponentialRandomVariable`
+* class :cpp:class:`ParetoRandomVariable`
+* class :cpp:class:`WeibullRandomVariable`
+* class :cpp:class:`NormalRandomVariable`
+* class :cpp:class:`LogNormalRandomVariable`
+* class :cpp:class:`GammaRandomVariable`
+* class :cpp:class:`ErlangRandomVariable`
+* class :cpp:class:`TriangularRandomVariable`
+* class :cpp:class:`ZipfRandomVariable`
+* class :cpp:class:`ZetaRandomVariable`
+* class :cpp:class:`DeterministicRandomVariable`
+* class :cpp:class:`EmpiricalRandomVariable`
 
-Semantics of RandomVariable objects
-***********************************
+Semantics of RandomVariableStream 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 :cpp:class:`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.
+RandomVariableStream objects derive from :cpp:class:`ns3::Object` and are
+handled by smart pointers.
 
-RandomVariable objects can also be used in |ns3| attributes, which means
+RandomVariableStream instances can also be used in |ns3| attributes, which means
 that values can be set for them through the |ns3| attribute system.
 An example is in the propagation models for WifiNetDevice:::
 
@@ -234,15 +236,15 @@
         .AddConstructor<RandomPropagationDelayModel> ()
         .AddAttribute ("Variable",
                        "The random variable which generates random delays (s).",
-                       RandomVariableValue (UniformVariable (0.0, 1.0)),
-             MakeRandomVariableAccessor (&RandomPropagationDelayModel::m_variable), 
-                       MakeRandomVariableChecker ())
+                       StringValue ("ns3::UniformRandomVariable"),
+                       MakePointerAccessor (&RandomPropagationDelayModel::m_variable),
+                       MakePointerChecker<RandomVariableStream> ())
         ;
       return tid;
     }
 
 Here, the |ns3| user can change the default random variable for this
-delay model (which is a UniformVariable ranging from 0 to 1) through
+delay model (which is a UniformRandomVariable ranging from 0 to 1) through
 the attribute system.
 
 Using other PRNG
@@ -252,10 +254,56 @@
 random number generator (e.g., the GNU Scientific Library or the Akaroa
 package).  Patches are welcome.
 
-More advanced usage
-*******************
+Setting the stream number
+*************************
+
+The underlying MRG32k3a generator provides 2^64 independent streams.
+In ns-3, these are assigned sequentially starting from the first stream as 
+new RandomVariableStream instances make their first call to GetValue().
+
+As a result of how these RandomVariableStream objects are assigned to
+underlying streams, the assignment is sensitive to perturbations of
+the simulation configuration.  The consequence is that if any aspect of the
+simulation configuration is changed, the mapping of RandomVariables to
+streams may (or may not) change.
+
+As a concrete example, a user running a comparative study between routing
+protocols may find that the act of changing one routing protocol for another
+will notice that the underlying mobility pattern also changed.  
+
+Starting with ns-3.15, some control has been provided to users to allow
+users to optionally fix the assignment of selected RandomVariableStream 
+objects to underlying streams.  This is the ``Stream`` attribute, part
+of the base class RandomVariableStream.  
+
+By partitioning the existing sequence of streams from before:
 
-*To be completed.*
+::
+
+   <-------------------------------------------------------------------------->
+   stream 0                                                     stream (2^64 - 1)
+
+into two equal-sized sets:
+
+::
+
+   <--------------------------------------------------------------------------->
+    ^                             ^^                                    ^
+    |                             ||                                    |
+   stream 0       stream (2^63 - 1) stream 2^63          stream (2^64 - 1)
+   <- automatically assigned -----><-------- assigned by user----------->
+
+The first 2^63 streams continue to be automatically assigned, while
+the last 2^63 are given stream indices starting with zero up to
+2^63-1.
+
+The assignment of streams to a fixed stream number is optional; instances
+of RandomVariableStream that do not have a stream value assigned will
+be assigned the next one from the pool of automatic streams.
+
+To fix a RandomVariableStream to a particular underlying stream, assign
+its ``Stream`` attribute to a non-negative integer (the default value
+of -1 means that a value will be automatically allocated).
 
 Publishing your results
 ***********************