RandomVariable API in line with Michelle's comments
authorRaj Bhattacharjea <raj.b@gatech.edu>
Thu, 22 Mar 2007 16:41:01 -0400
changeset 364 9df87117d468
parent 363 60ae55dd5ef1
child 365 2a5cd7125778
RandomVariable API in line with Michelle's comments
src/core/random-variable.cc
src/core/random-variable.h
src/core/rng-stream.cc
src/core/rng-stream.h
--- a/src/core/random-variable.cc	Thu Mar 22 16:02:33 2007 -0400
+++ b/src/core/random-variable.cc	Thu Mar 22 16:41:01 2007 -0400
@@ -89,6 +89,7 @@
 //-----------------------------------------------------------------------------
 // RandomVariable methods
 
+uint32_t      RandomVariable::runNumber = 0;
 bool          RandomVariable::initialized = false;   // True if RngStream seed set 
 bool          RandomVariable::useDevRandom = false;  // True if use /dev/random desired
 bool          RandomVariable::globalSeedSet = false; // True if GlobalSeed called
@@ -101,12 +102,12 @@
   m_generator = new RngStream();
   RandomVariable::Initialize(); // sets the seed for the static object
   m_generator->InitializeStream();
+  m_generator->ResetNthSubstream(RandomVariable::runNumber);
 }
 
 RandomVariable::RandomVariable(const RandomVariable& r)
 {
   m_generator = new RngStream(*r.m_generator);
-  RandomVariable::Initialize();
 }
 
 RandomVariable::~RandomVariable()
@@ -124,29 +125,9 @@
   RandomVariable::useDevRandom = udr;
 }
 
-bool RandomVariable::SetSeed(const Seed& s)
+void RandomVariable::GetSeed(uint32_t seed[6])
 {
-  // Seed this stream with the specified seed
-  if (s.IsRandom())
-    {
-      uint32_t seeds[6];
-      while(true)
-        { // Insure seeds are valid
-          GetRandomSeeds(seeds);
-          if (RngStream::CheckSeed(seeds)) break;
-        }
-      m_generator->SetSeeds(seeds);
-      return true;
-    }
-  // Not random seed, use specified
-  const ConstantSeed& cs = (ConstantSeed&)s;
-  if (!RngStream::CheckSeed(cs.seeds))
-    {
-      cout << "Constant seed failed valid check" << endl;
-      return false; // Seed is not valid
-    }
-  m_generator->SetSeeds(cs.seeds);
-  return true;
+  m_generator->GetState(seed);
 }
 
 //-----------------------------------------------------------------------------
@@ -233,6 +214,11 @@
     }
 }
 
+void RandomVariable::SetRunNumber(uint32_t n)
+{
+  runNumber = n;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // UniformVariable methods
--- a/src/core/random-variable.h	Thu Mar 22 16:02:33 2007 -0400
+++ b/src/core/random-variable.h	Thu Mar 22 16:41:01 2007 -0400
@@ -113,22 +113,17 @@
    * \return A copy of this object
    */  
   virtual RandomVariable*   Copy() const = 0;
-
+  
   /**
-   * \brief Use a private seed and private stream for this generator.
-   * 
-   * This function explicitly overrides all other seeding behavior for
-   * this object.  For example, even if another seeding method has been
-   * used (either by default or calls to UseDevRandom, UseGlobalSeed, etc.)
-   * a call to SetSeed explicitly re-seeds this generator. Example:
-   * \code
-   * UniformVariable x(0,10);//with no other code, defaults to time of day seed
-   * x.SetSeed(...); //overrides time of day seed
-   * \endcode
-   * \param s Seed to use.  Can either be a RandomSeed or ConstantSeed.
-   * \return true if valid seed.
+   * \brief Get the internal state of the RNG
+   *
+   * This function is for power users who understand the inner workings
+   * of the underlying RngStream method used.  It returns the internal
+   * state of the RNG via the input parameter.
+   * \param seed Output parameter; gets overwritten with the internal state of
+   * of the RNG.
    */
-  bool SetSeed(const Seed& s);
+  virtual void GetSeed(uint32_t seed[6]);
   
   /**
    * \brief Set seeding behavior
@@ -168,16 +163,49 @@
    * \return True if seed is valid.
    */ 
   static void UseGlobalSeed(const Seed& s);
-
+  
+  /**
+   * \brief Set the run number of this simulation
+   *
+   * These RNGs have the ability to give independent sets of trials for a fixed
+   * global seed.  For example, suppose one sets up a simulation with
+   * RandomVariables with a given global seed.  Suppose the user wanted to
+   * retry the same simulation with different random values for validity,
+   * statistical rigor, etc.  The user could either change the global seed and
+   * re-run the simulation, or could use this facility to increment all of the
+   * RNGs to a next substream state.  This predictably advances the internal
+   * state of all RandomVariables n steps.  This should be called immediately
+   * after the global seed is set, and before the creation of any
+   * RandomVariables.  For example:
+   * \code
+   * RandomVariable::UseGlobalSeed(ConstantSeed(1,2,3,4,5,6));
+   * int N = atol(argv[1]); //read in run number from command line
+   * RandomVariable::SetRunNumber(N);
+   * UniformVariable x(0,10);
+   * ExponentialVariable y(2902);
+   * \endcode
+   * In this example, N could successivly be equal to 1,2,3, etc. and the user
+   * would continue to get independent runs out of the single simulation.  For
+   * this simple example, the following might work:
+   * \code
+   * ./simulation 0
+   * ...Results for run 0:...
+   *
+   * ./simulation 1
+   * ...Results for run 1:...
+   * \endcode
+   */
+  static void SetRunNumber(uint32_t n);
 private:
-  static bool initialized;     // True if package seed is set 
   static void Initialize();    // Initialize  the RNG system
   static void GetRandomSeeds(uint32_t seeds[6]);
 private:
+  static bool initialized;     // True if package seed is set 
   static bool useDevRandom;    // True if using /dev/random desired
   static bool globalSeedSet;   // True if global seed has been specified
   static int  devRandom;       // File handle for /dev/random
   static uint32_t globalSeed[6]; // The global seed to use
+  static uint32_t runNumber;
 protected:
   static unsigned long heuristic_sequence;
   RngStream* m_generator;  //underlying generator being wrapped
--- a/src/core/rng-stream.cc	Thu Mar 22 16:02:33 2007 -0400
+++ b/src/core/rng-stream.cc	Thu Mar 22 16:41:01 2007 -0400
@@ -378,6 +378,19 @@
        Cg[i] = Bg[i];
 }
 
+//-------------------------------------------------------------------------
+// Reset Stream to Nth SubStream.
+//
+void RngStream::ResetNthSubstream (uint32_t N)
+{
+   if(N==0) return;
+   for(uint32_t i=0;i<N;++i) {
+      MatVecModM(A1p76, Bg, Bg, m1);
+      MatVecModM(A2p76, &Bg[3], &Bg[3], m2);
+   }
+   for (int i = 0; i < 6; ++i)
+       Cg[i] = Bg[i];
+}
 
 //-------------------------------------------------------------------------
 bool RngStream::SetPackageSeed (const uint32_t seed[6])
--- a/src/core/rng-stream.h	Thu Mar 22 16:02:33 2007 -0400
+++ b/src/core/rng-stream.h	Thu Mar 22 16:41:01 2007 -0400
@@ -31,6 +31,7 @@
   void ResetStartStream ();
   void ResetStartSubstream ();
   void ResetNextSubstream ();
+  void ResetNthSubstream(uint32_t N);
   void SetAntithetic (bool a);
   void IncreasedPrecis (bool incp);
   bool SetSeeds (const uint32_t seed[6]);