--- a/src/core/random-variable.cc Tue Dec 30 11:35:31 2008 -0800
+++ b/src/core/random-variable.cc Tue Jan 13 17:15:44 2009 -0500
@@ -16,6 +16,7 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+// Author: Hadi Arbabi<marbabi@cs.odu.edu>
//
#include <iostream>
@@ -41,6 +42,78 @@
namespace ns3{
//-----------------------------------------------------------------------------
+// Seed Manager
+//-----------------------------------------------------------------------------
+
+uint32_t SeedManager::seed_[6]={1,2,3,4,5,6};
+bool SeedManager::seedSet=false;
+uint32_t SeedManager::runNumber=0;
+
+void SeedManager::SetSeed(uint32_t seed[6])
+{
+ if (SeedManager::seedSet)
+ {
+ cerr << "Seed Manager already set!" << endl;
+ cerr << "Call to SeedManager::SetSeed(...) ignored" << endl;
+ return;
+ }
+ SeedManager::seed_[0]=seed[0];
+ SeedManager::seed_[1]=seed[1];
+ SeedManager::seed_[2]=seed[2];
+ SeedManager::seed_[3]=seed[3];
+ SeedManager::seed_[4]=seed[4];
+ SeedManager::seed_[5]=seed[5];
+ if (!RngStream::CheckSeed(SeedManager::seed_))
+ NS_FATAL_ERROR("Invalid seed");
+
+ SeedManager::seedSet = true;
+}
+
+void SeedManager::GetSeed(uint32_t seed[6])
+{
+ for (int i=0; i<6; i++)
+ {
+ seed[i] = seed_[i];
+ }
+}
+
+void SeedManager::SetSeed(uint32_t seed)
+{
+ uint32_t s[6];
+ s[0]=s[1]=s[2]=s[3]=s[4]=s[5]=seed;
+ SetSeed(s);
+}
+
+uint32_t SeedManager::GetSeed()
+{
+ uint32_t s[6];
+ GetSeed(s);
+ return s[0];
+}
+
+void SeedManager::SetRun(uint32_t run)
+{
+ runNumber=run;
+}
+
+uint32_t SeedManager::GetRun()
+{
+ return runNumber;
+}
+
+bool SeedManager::CheckSeed (uint32_t seed)
+{
+ uint32_t s[6];
+ s[0]=s[1]=s[2]=s[3]=s[4]=s[5]=seed;
+ return RngStream::CheckSeed(s);
+}
+
+bool SeedManager::CheckSeed (uint32_t seed[6])
+{
+ return RngStream::CheckSeed(seed);
+}
+
+//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// RandomVariableBase methods
@@ -54,63 +127,24 @@
virtual double GetValue() = 0;
virtual uint32_t GetInteger();
virtual RandomVariableBase* Copy(void) const = 0;
- virtual void GetSeed(uint32_t seed[6]);
- static void UseDevRandom(bool udr = true);
- static void UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2,
- uint32_t s3, uint32_t s4, uint32_t s5);
- static void SetRunNumber(uint32_t n);
-private:
- static void GetRandomSeeds(uint32_t seeds[6]);
-private:
- 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
- friend class RandomVariableInitializer;
protected:
- static unsigned long heuristic_sequence;
- static RngStream* m_static_generator;
- static uint32_t runNumber;
static void Initialize(); // Initialize the RNG system
static bool initialized; // True if package seed is set
RngStream* m_generator; //underlying generator being wrapped
};
-
-
bool RandomVariableBase::initialized = false; // True if RngStream seed set
-bool RandomVariableBase::useDevRandom = false; // True if use /dev/random
-bool RandomVariableBase::globalSeedSet = false; // True if GlobalSeed called
-int RandomVariableBase::devRandom = -1;
-uint32_t RandomVariableBase::globalSeed[6];
-unsigned long RandomVariableBase::heuristic_sequence;
-RngStream* RandomVariableBase::m_static_generator = 0;
-uint32_t RandomVariableBase::runNumber = 0;
-//the static object random_variable_initializer initializes the static members
-//of RandomVariable
-static class RandomVariableInitializer
-{
- public:
- RandomVariableInitializer()
- {
-// RandomVariableBase::Initialize(); // sets the static package seed
-// RandomVariableBase::m_static_generator = new RngStream();
-// RandomVariableBase::m_static_generator->InitializeStream();
- }
- ~RandomVariableInitializer()
- {
- delete RandomVariableBase::m_static_generator;
- }
-} random_variable_initializer;
RandomVariableBase::RandomVariableBase()
: m_generator(NULL)
{
-// m_generator = new RngStream();
-// m_generator->InitializeStream();
-// m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ // it's better to be initialzed first and then set run number,
+ // it happens in GetValue() automatically
+ //m_generator = new RngStream();
+ //m_generator->InitializeStream();
+ //m_generator->ResetNthSubstream(SeedManager::GetRun());
}
RandomVariableBase::RandomVariableBase(const RandomVariableBase& r)
@@ -132,115 +166,16 @@
return (uint32_t)GetValue();
}
-void RandomVariableBase::UseDevRandom(bool udr)
-{
- RandomVariableBase::useDevRandom = udr;
-}
-
-void RandomVariableBase::GetSeed(uint32_t seed[6])
-{
- if(!m_generator)
- {
- m_generator = new RngStream();
- m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
- }
- m_generator->GetState(seed);
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// RandomVariableBase static methods
-void RandomVariableBase::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2,
- uint32_t s3, uint32_t s4, uint32_t s5)
-{
- if (RandomVariableBase::globalSeedSet)
- {
- NS_FATAL_ERROR ("Random number generator already initialized! "
- "Call to RandomVariableBase::UseGlobalSeed() ignored");
- }
- RandomVariableBase::globalSeed[0] = s0;
- RandomVariableBase::globalSeed[1] = s1;
- RandomVariableBase::globalSeed[2] = s2;
- RandomVariableBase::globalSeed[3] = s3;
- RandomVariableBase::globalSeed[4] = s4;
- RandomVariableBase::globalSeed[5] = s5;
- if (!RngStream::CheckSeed(RandomVariableBase::globalSeed))
- NS_FATAL_ERROR("Invalid seed");
-
- RandomVariableBase::globalSeedSet = true;
-}
-
void RandomVariableBase::Initialize()
{
+ uint32_t s[6];
if (RandomVariableBase::initialized) return; // Already initialized and seeded
RandomVariableBase::initialized = true;
- if (!RandomVariableBase::globalSeedSet)
- { // No global seed, try a random one
- GetRandomSeeds(globalSeed);
- }
- // Seed the RngStream package
- RngStream::SetPackageSeed(globalSeed);
+ SeedManager::GetSeed(s);
+ RngStream::SetPackageSeed(s);
}
-void RandomVariableBase::GetRandomSeeds(uint32_t seeds[6])
-{
- // Check if /dev/random exists
- if (RandomVariableBase::useDevRandom && RandomVariableBase::devRandom < 0)
- {
- RandomVariableBase::devRandom = open("/dev/random", O_RDONLY);
- }
- if (RandomVariableBase::devRandom > 0)
- { // Use /dev/random
- while(true)
- {
- for (int i = 0; i < 6; ++i)
- {
- ssize_t bytes_read = read (RandomVariableBase::devRandom,
- &seeds[i], sizeof (seeds[i]));
- if (bytes_read != sizeof (seeds[i]))
- {
- NS_FATAL_ERROR ("Read from /dev/random failed");
- }
- }
- if (RngStream::CheckSeed(seeds)) break; // Got a valid one
- }
- }
- else
- { // Seed from time of day (code borrowed from ns2 random seeding)
- // Thanks to John Heidemann for this technique
- while(true)
- {
- timeval tv;
- gettimeofday(&tv, 0);
- seeds[0] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- gettimeofday(&tv, 0);
- seeds[1] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- gettimeofday(&tv, 0);
- seeds[2] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- gettimeofday(&tv, 0);
- seeds[3] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- gettimeofday(&tv, 0);
- seeds[4] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- gettimeofday(&tv, 0);
- seeds[5] = (tv.tv_sec^tv.tv_usec^(++heuristic_sequence <<8))
- & 0x7fffffff;
- if (RngStream::CheckSeed(seeds)) break; // Got a valid one
- }
- }
-}
-
-void RandomVariableBase::SetRunNumber(uint32_t n)
-{
- runNumber = n;
-}
-
-
+//-------------------------------------------------------
RandomVariable::RandomVariable()
: m_variable (0)
@@ -277,33 +212,14 @@
{
return m_variable->GetInteger ();
}
-void
-RandomVariable::GetSeed(uint32_t seed[6]) const
-{
- return m_variable->GetSeed (seed);
-}
-void
-RandomVariable::UseDevRandom(bool udr)
-{
- RandomVariableBase::UseDevRandom (udr);
-}
-void
-RandomVariable::UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2,
- uint32_t s3, uint32_t s4, uint32_t s5)
-{
- RandomVariableBase::UseGlobalSeed (s0, s1, s2, s3, s4, s5);
-}
-void
-RandomVariable::SetRunNumber(uint32_t n)
-{
- RandomVariableBase::SetRunNumber (n);
-}
+
RandomVariableBase *
RandomVariable::Peek (void) const
{
return m_variable;
}
+
ATTRIBUTE_VALUE_IMPLEMENT (RandomVariable);
ATTRIBUTE_CHECKER_IMPLEMENT (RandomVariable);
@@ -335,15 +251,14 @@
* \return A value between low and high values specified by the constructor
*/
virtual double GetValue();
+
+ /**
+ * \return A value between low and high values specified by parameters
+ */
+ virtual double GetValue(double s, double l);
+
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param s Low end of the range
- * \param l High end of the range
- * \return A uniformly distributed random number between s and l
- */
- static double GetSingleValue(double s, double l);
private:
double m_min;
double m_max;
@@ -380,37 +295,46 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
return m_min + m_generator->RandU01() * (m_max - m_min);
}
+double UniformVariableImpl::GetValue(double s, double l)
+{
+ if(!RandomVariableBase::initialized)
+ {
+ RandomVariableBase::Initialize();
+ }
+ if(!m_generator)
+ {
+ m_generator = new RngStream();
+ m_generator->InitializeStream();
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
+ }
+ return s + m_generator->RandU01() * (l-s);
+}
+
RandomVariableBase* UniformVariableImpl::Copy() const
{
return new UniformVariableImpl(*this);
}
-double UniformVariableImpl::GetSingleValue(double s, double l)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- return s + m_static_generator->RandU01() * (l - s);;
-}
-
UniformVariable::UniformVariable()
: RandomVariable (UniformVariableImpl ())
{}
UniformVariable::UniformVariable(double s, double l)
: RandomVariable (UniformVariableImpl (s, l))
{}
-double
-UniformVariable::GetSingleValue(double s, double l)
+
+double UniformVariable::GetValue()
{
- return UniformVariableImpl::GetSingleValue (s, l);
+ return Peek()->GetValue();
+}
+
+double UniformVariable::GetValue(double s, double l)
+{
+ return ((UniformVariableImpl*)Peek())->GetValue(s,l);
}
@@ -623,13 +547,7 @@
*/
virtual double GetValue();
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param m The mean of the distribution from which the return value is drawn
- * \param b The upper bound value desired, beyond which values get clipped
- * \return A random number from an exponential distribution with mean m
- */
- static double GetSingleValue(double m, double b=0);
+
private:
double m_mean; // Mean value of RV
double m_bound; // Upper bound on value (if non-zero)
@@ -657,7 +575,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
double r = -m_mean*log(m_generator->RandU01());
if (m_bound != 0 && r > m_bound) return m_bound;
@@ -668,18 +586,6 @@
{
return new ExponentialVariableImpl(*this);
}
-double ExponentialVariableImpl::GetSingleValue(double m, double b/*=0*/)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- double r = -m*log(m_static_generator->RandU01());
- if (b != 0 && r > b) return b;
- return r;
-}
ExponentialVariable::ExponentialVariable()
: RandomVariable (ExponentialVariableImpl ())
@@ -690,11 +596,6 @@
ExponentialVariable::ExponentialVariable(double m, double b)
: RandomVariable (ExponentialVariableImpl (m, b))
{}
-double
-ExponentialVariable::GetSingleValue(double m, double b)
-{
- return ExponentialVariableImpl::GetSingleValue (m, b);
-}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -743,17 +644,7 @@
*/
virtual double GetValue();
virtual RandomVariableBase* Copy() const;
-public:
- /**
- * \param m The mean value of the distribution from which the return value
- * is drawn.
- * \param s The shape parameter of the distribution from which the return
- * value is drawn.
- * \param b The upper bound to which to restrict return values
- * \return A random number from a Pareto distribution with mean m and shape
- * parameter s.
- */
- static double GetSingleValue(double m, double s, double b=0);
+
private:
double m_mean; // Mean value of RV
double m_shape; // Shape parameter
@@ -786,7 +677,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
double scale = m_mean * ( m_shape - 1.0) / m_shape;
double r = (scale * ( 1.0 / pow(m_generator->RandU01(), 1.0 / m_shape)));
@@ -799,20 +690,6 @@
return new ParetoVariableImpl(*this);
}
-double ParetoVariableImpl::GetSingleValue(double m, double s, double b/*=0*/)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- double scale = m * ( s - 1.0) / s;
- double r = (scale * ( 1.0 / pow(m_static_generator->RandU01(), 1.0 / s)));
- if (b != 0 && r > b) return b;
- return r;
-}
-
ParetoVariable::ParetoVariable ()
: RandomVariable (ParetoVariableImpl ())
{}
@@ -825,11 +702,6 @@
ParetoVariable::ParetoVariable(double m, double s, double b)
: RandomVariable (ParetoVariableImpl (m, s, b))
{}
-double
-ParetoVariable::GetSingleValue(double m, double s, double b)
-{
- return ParetoVariableImpl::GetSingleValue (m, s, b);
-}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -879,14 +751,7 @@
*/
virtual double GetValue();
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param m Mean value for the distribution.
- * \param s Shape (alpha) parameter for the distribution.
- * \param b Upper limit on returned values
- * \return Random number from a distribution specified by m,s, and b
- */
- static double GetSingleValue(double m, double s, double b=0);
+
private:
double m_mean; // Mean value of RV
double m_alpha; // Shape parameter
@@ -914,7 +779,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
double exponent = 1.0 / m_alpha;
double r = m_mean * pow( -log(m_generator->RandU01()), exponent);
@@ -927,20 +792,6 @@
return new WeibullVariableImpl(*this);
}
-double WeibullVariableImpl::GetSingleValue(double m, double s, double b/*=0*/)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- double exponent = 1.0 / s;
- double r = m * pow( -log(m_static_generator->RandU01()), exponent);
- if (b != 0 && r > b) return b;
- return r;
-}
-
WeibullVariable::WeibullVariable()
: RandomVariable (WeibullVariableImpl ())
{}
@@ -953,11 +804,7 @@
WeibullVariable::WeibullVariable(double m, double s, double b)
: RandomVariable (WeibullVariableImpl (m, s, b))
{}
-double
-WeibullVariable::GetSingleValue(double m, double s, double b)
-{
- return WeibullVariableImpl::GetSingleValue (m, s, b);
-}
+
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// NormalVariableImpl methods
@@ -987,14 +834,7 @@
*/
virtual double GetValue();
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param m Mean value
- * \param v Variance
- * \param b Bound. The NormalVariableImpl is bounded within +-bound.
- * \return A random number from a distribution specified by m,v, and b.
- */
- static double GetSingleValue(double m, double v, double b = INFINITE_VALUE);
+
private:
double m_mean; // Mean value of RV
double m_variance; // Mean value of RV
@@ -1017,7 +857,7 @@
NormalVariableImpl::NormalVariableImpl(const NormalVariableImpl& c)
: RandomVariableBase(c), m_mean(c.m_mean), m_variance(c.m_variance),
- m_bound(c.m_bound), m_nextValid(false) { }
+ m_bound(c.m_bound) { }
double NormalVariableImpl::GetValue()
{
@@ -1029,7 +869,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
if (m_nextValid)
{ // use previously generated
@@ -1049,21 +889,11 @@
{ // Got good pair
double y = sqrt((-2 * log(w))/w);
m_next = m_mean + v2 * y * sqrt(m_variance);
- //if next is in bounds, it is valid
- m_nextValid = fabs(m_next-m_mean) <= m_bound;
+ if (fabs(m_next) > m_bound) m_next = m_bound * (m_next)/fabs(m_next);
+ m_nextValid = true;
double x1 = m_mean + v1 * y * sqrt(m_variance);
- //if x1 is in bounds, return it
- if (fabs(x1-m_mean) <= m_bound)
- {
- return x1;
- }
- //otherwise try and return m_next if it is valid
- else if (m_nextValid)
- {
- m_nextValid = false;
- return m_next;
- }
- //otherwise, just run this loop again
+ if (fabs(x1) > m_bound) x1 = m_bound * (x1)/fabs(x1);
+ return x1;
}
}
}
@@ -1073,71 +903,12 @@
return new NormalVariableImpl(*this);
}
-double NormalVariableImpl::GetSingleValue(double m, double v, double b)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- if (m_static_nextValid)
- { // use previously generated
- m_static_nextValid = false;
- return m_static_next;
- }
- while(1)
- { // See Simulation Modeling and Analysis p. 466 (Averill Law)
- // for algorithm; basically a Box-Muller transform:
- // http://en.wikipedia.org/wiki/Box-Muller_transform
- double u1 = m_static_generator->RandU01();
- double u2 = m_static_generator->RandU01();;
- double v1 = 2 * u1 - 1;
- double v2 = 2 * u2 - 1;
- double w = v1 * v1 + v2 * v2;
- if (w <= 1.0)
- { // Got good pair
- double y = sqrt((-2 * log(w))/w);
- m_static_next = m + v2 * y * sqrt(v);
- //if next is in bounds, it is valid
- m_static_nextValid = fabs(m_static_next-m) <= b;;
- double x1 = m + v1 * y * sqrt(v);
- //if x1 is in bounds, return it
- if (fabs(x1-m) <= b)
- {
- return x1;
- }
- //otherwise try and return m_next if it is valid
- else if (m_static_nextValid)
- {
- m_static_nextValid = false;
- return m_static_next;
- }
- //otherwise, just run this loop again
- }
- }
-}
-
NormalVariable::NormalVariable()
: RandomVariable (NormalVariableImpl ())
{}
-NormalVariable::NormalVariable(double m, double v)
- : RandomVariable (NormalVariableImpl (m, v))
-{}
NormalVariable::NormalVariable(double m, double v, double b)
: RandomVariable (NormalVariableImpl (m, v, b))
{}
-double
-NormalVariable::GetSingleValue(double m, double v)
-{
- return NormalVariableImpl::GetSingleValue (m, v);
-}
-double
-NormalVariable::GetSingleValue(double m, double v, double b)
-{
- return NormalVariableImpl::GetSingleValue (m, v, b);
-}
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -1208,7 +979,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
if (emp.size() == 0) return 0.0; // HuH? No empirical data
if (!validated) Validate(); // Insure in non-decreasing
@@ -1395,13 +1166,7 @@
*/
virtual double GetValue ();
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param mu mu parameter of the underlying normal distribution
- * \param sigma sigma parameter of the underlying normal distribution
- * \return A random number from the distribution specified by mu and sigma
- */
- static double GetSingleValue(double mu, double sigma);
+
private:
double m_mu;
double m_sigma;
@@ -1455,7 +1220,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
double u, v, r2, normal, z;
@@ -1478,42 +1243,9 @@
return z;
}
-double LogNormalVariableImpl::GetSingleValue (double mu, double sigma)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- double u, v, r2, normal, z;
- do
- {
- /* choose x,y in uniform square (-1,-1) to (+1,+1) */
- u = -1 + 2 * m_static_generator->RandU01 ();
- v = -1 + 2 * m_static_generator->RandU01 ();
-
- /* see if it is in the unit circle */
- r2 = u * u + v * v;
- }
- while (r2 > 1.0 || r2 == 0);
-
- normal = u * sqrt (-2.0 * log (r2) / r2);
-
- z = exp (sigma * normal + mu);
-
- return z;
-}
-
LogNormalVariable::LogNormalVariable (double mu, double sigma)
: RandomVariable (LogNormalVariableImpl (mu, sigma))
{}
-double
-LogNormalVariable::GetSingleValue(double mu, double sigma)
-{
- return LogNormalVariableImpl::GetSingleValue (mu, sigma);
-}
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -1542,14 +1274,7 @@
*/
virtual double GetValue();
virtual RandomVariableBase* Copy(void) const;
-public:
- /**
- * \param s Low end of the range
- * \param l High end of the range
- * \param mean mean of the distribution
- * \return A triangularly distributed random number between s and l
- */
- static double GetSingleValue(double s, double l, double mean);
+
private:
double m_min;
double m_max;
@@ -1576,7 +1301,7 @@
{
m_generator = new RngStream();
m_generator->InitializeStream();
- m_generator->ResetNthSubstream(RandomVariableBase::runNumber);
+ m_generator->ResetNthSubstream(SeedManager::GetRun());
}
double u = m_generator->RandU01();
if(u <= (m_mode - m_min) / (m_max - m_min) )
@@ -1590,33 +1315,12 @@
return new TriangularVariableImpl(*this);
}
-double TriangularVariableImpl::GetSingleValue(double s, double l, double mean)
-{
- if(!RandomVariableBase::m_static_generator)
- {
- RandomVariableBase::Initialize(); // sets the static package seed
- RandomVariableBase::m_static_generator = new RngStream();
- RandomVariableBase::m_static_generator->InitializeStream();
- }
- double mode = 3.0*mean-s-l;
- double u = m_static_generator->RandU01();
- if(u <= (mode - s) / (l - s) )
- return s + sqrt(u * (l - s) * (mode - s) );
- else
- return l - sqrt( (1-u) * (l - s) * (l - mode) );
-}
-
TriangularVariable::TriangularVariable()
: RandomVariable (TriangularVariableImpl ())
{}
TriangularVariable::TriangularVariable(double s, double l, double mean)
: RandomVariable (TriangularVariableImpl (s,l,mean))
{}
-double
-TriangularVariable::GetSingleValue(double s, double l, double mean)
-{
- return TriangularVariableImpl::GetSingleValue (s,l,mean);
-}
std::ostream &operator << (std::ostream &os, const RandomVariable &var)
@@ -1691,112 +1395,3 @@
}//namespace ns3
-
-#ifdef RUN_SELF_TESTS
-#include "test.h"
-#include <vector>
-
-namespace ns3 {
-
-
-class RandomVariableTest : public Test
-{
-public:
- RandomVariableTest () : Test ("RandomVariable") {}
- virtual bool RunTests (void)
- {
- bool result = true;
- const double desired_mean = 1.0;
- const double desired_stddev = 1.0;
- double tmp = log (1 + (desired_stddev/desired_mean)*(desired_stddev/desired_mean));
- double sigma = sqrt (tmp);
- double mu = log (desired_mean) - 0.5*tmp;
-
- // Test a custom lognormal instance
- {
- LogNormalVariable lognormal (mu, sigma);
- vector<double> samples;
- const int NSAMPLES = 10000;
- double sum = 0;
- for (int n = NSAMPLES; n; --n)
- {
- double value = lognormal.GetValue ();
- sum += value;
- samples.push_back (value);
- }
- double obtained_mean = sum / NSAMPLES;
- sum = 0;
- for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
- {
- double tmp = (*iter - obtained_mean);
- sum += tmp*tmp;
- }
- double obtained_stddev = sqrt (sum / (NSAMPLES - 1));
-
- if (not (obtained_mean/desired_mean > 0.90 and obtained_mean/desired_mean < 1.10))
- {
- result = false;
- Failure () << "Obtained lognormal mean value " << obtained_mean << ", expected " << desired_mean << std::endl;
- }
-
- if (not (obtained_stddev/desired_stddev > 0.90 and obtained_stddev/desired_stddev < 1.10))
- {
- result = false;
- Failure () << "Obtained lognormal stddev value " << obtained_stddev <<
- ", expected " << desired_stddev << std::endl;
- }
- }
-
- // Test GetSingleValue
- {
- vector<double> samples;
- const int NSAMPLES = 10000;
- double sum = 0;
- for (int n = NSAMPLES; n; --n)
- {
- double value = LogNormalVariable::GetSingleValue (mu, sigma);
- sum += value;
- samples.push_back (value);
- }
- double obtained_mean = sum / NSAMPLES;
- sum = 0;
- for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
- {
- double tmp = (*iter - obtained_mean);
- sum += tmp*tmp;
- }
- double obtained_stddev = sqrt (sum / (NSAMPLES - 1));
-
- if (not (obtained_mean/desired_mean > 0.90 and obtained_mean/desired_mean < 1.10))
- {
- result = false;
- Failure () << "Obtained LogNormalVariable::GetSingleValue mean value " << obtained_mean
- << ", expected " << desired_mean << std::endl;
- }
-
- if (not (obtained_stddev/desired_stddev > 0.90 and obtained_stddev/desired_stddev < 1.10))
- {
- result = false;
- Failure () << "Obtained LogNormalVariable::GetSingleValue stddev value " << obtained_stddev <<
- ", expected " << desired_stddev << std::endl;
- }
- }
-
- // Test attribute serialization
- {
- RandomVariableValue val;
- val.DeserializeFromString ("Uniform:0.1:0.2", MakeRandomVariableChecker ());
- RandomVariable rng = val.Get ();
- NS_TEST_ASSERT_EQUAL (val.SerializeToString (MakeRandomVariableChecker ()), "Uniform:0.1:0.2");
- }
-
- return result;
- }
-};
-
-
-static RandomVariableTest g_random_variable_tests;
-
-}//namespace ns3
-
-#endif /* RUN_SELF_TESTS */