core: refactor EmpricialRandomVariable and provide example

This commit is contained in:
Peter D. Barnes, Jr
2020-04-02 10:21:03 -07:00
committed by Peter Barnes
parent 6ec2093986
commit b7deb42a65
5 changed files with 510 additions and 146 deletions

View File

@@ -0,0 +1,215 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2020 Lawrence Livermore National Laboratory
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
*/
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/command-line.h"
#include "ns3/random-variable-stream.h"
#include "ns3/histogram.h"
#include "ns3/ptr.h"
#include <iomanip>
#include <iostream>
#include <map>
/**
* \file
* \ingroup core-examples
* \ingroup randomvariable
* Example program illustrating use of ns3::EmpiricalRandomVariable
*
* This example illustrates
*
* * Creating an EmpiricalRandomVariable instance.
* * Switching the mode.
* * Using the sampling mode
* * Switching modes
* * Using the interpolating mode
*
* Consult the ns-3 manual for more information about the use of the
* random number generator
*/
using namespace ns3;
void
RunSingleSample (std::string mode, Ptr<EmpiricalRandomVariable> erv)
{
std::cout << "------------------------------" << std::endl;
std::cout << "Sampling " << mode << std::endl;
std::cout << std::endl;
std::cout << "Binned sample" << std::endl;
double value = erv->GetValue ();
std::cout << "Binned sample: " << value << std::endl;
std::cout << std::endl;
std::cout << "Interpolated sample" << std::endl;
erv->SetInterpolate (true);
value = erv->GetValue ();
std::cout << "Interpolated sample:" << value << std::endl;
erv->SetInterpolate (false);
}
void
PrintStatsLine (const double value, const long count, const long n)
{
std::cout << std::fixed << std::setprecision (3)
<< std::setw (10) << std::right << value
<< std::setw (10) << std::right << count
<< std::setw (10) << std::right
<< count / static_cast<double> (n) * 100.0
<< std::endl;
}
void
PrintSummary (long sum, long n, double weighted, double expected)
{
std::cout << std::endl;
std::cout << " --------" << std::endl;
std::cout << " Total "
<< std::setprecision (3) << std::fixed
<< std::setw (10) << std::right
<< sum / static_cast<double> (n) * 100.0
<< std::endl;
std::cout << " Average "
<< std::setprecision (3) << std::fixed
<< std::setw (6) << std::right << weighted / n
<< std::endl;
std::cout << " Expected "
<< std::setprecision (3) << std::fixed
<< std::setw (6) << std::right << expected
<< std::endl
<< std::endl;
}
void
RunBothModes (std::string mode, Ptr<EmpiricalRandomVariable> erv, long n)
{
std::cout << std::endl;
std::cout << "Sampling " << mode << std::endl;
std::map <double, int> counts;
counts[0] = 0;
for (long i = 0; i < n; ++i)
{
++counts[erv->GetValue ()];
}
long sum = 0;
double weighted = 0;
std::cout << std::endl;
std::cout << " Value Counts %" << std::endl;
std::cout << "---------- -------- --------" << std::endl;
for (auto c : counts)
{
long count = c.second;
double value = c.first;
sum += count;
weighted += value * count;
PrintStatsLine (value, count, n);
}
PrintSummary (sum, n, weighted, 8.75);
std::cout << "Interpolating " << mode << std::endl;
erv->SetInterpolate (true);
Histogram h (0.5);
for (long i = 0; i < n; ++i)
{
h.AddValue (erv->GetValue ());
// This could also be expressed as
// h.AddValue (erv->Interpolate ());
}
erv->SetInterpolate (false);
sum = 0;
weighted = 0;
std::cout << std::endl;
std::cout << " Bin Start Counts %" << std::endl;
std::cout << "---------- -------- --------" << std::endl;
for (uint32_t i = 0; i < h.GetNBins (); ++i)
{
long count = h.GetBinCount (i);
double start = h.GetBinStart (i);
double value = start + h.GetBinWidth (i) / 2.;
sum += count;
weighted += count * value;
PrintStatsLine (start, count, n);
}
PrintSummary (sum, n, weighted, 6.25);
}
int main (int argc, char *argv[])
{
long n = 1000000;
bool disableAnti = false;
bool single = false;
CommandLine cmd;
cmd.AddValue ("count", "how many draws to make from the rng", n);
cmd.AddValue ("antithetic", "disable antithetic sampling", disableAnti);
cmd.AddValue ("single", "sample a single time", single);
cmd.Parse (argc, argv);
std::cout << std::endl;
std::cout << cmd.GetName () << std::endl;
if (!single)
{
std::cout << "Sample count: " << n << std::endl;
}
else
{
std::cout << "Sampling a single time" << std::endl;
}
if (disableAnti)
{
std::cout << "Antithetic sampling disabled" << std::endl;
}
// Create the ERV in sampling mode
Ptr<EmpiricalRandomVariable> erv = CreateObject<EmpiricalRandomVariable> ();
erv->SetInterpolate (false);
erv->CDF ( 0.0, 0.0);
erv->CDF ( 5.0, 0.25);
erv->CDF (10.0, 1.0);
if (single)
{
RunSingleSample ("normal", erv);
if (!disableAnti)
{
std::cout << std::endl;
std::cout << "Antithetic" << std::endl;
erv->SetAntithetic (true);
RunSingleSample ("antithetic", erv);
erv->SetAntithetic (false);
}
std::cout << std::endl;
return 0;
}
RunBothModes ("normal", erv, n);
if (!disableAnti)
{
erv->SetAntithetic (true);
RunBothModes ("antithetic", erv, n);
erv->SetAntithetic (false);
}
return 0;
}

View File

@@ -44,6 +44,9 @@ def build(bld):
['core'])
obj.source = 'sample-show-progress.cc'
obj = bld.create_ns3_program('empirical-random-variable-example', ['core', 'flow-monitor'])
obj.source = 'empirical-random-variable-example.cc'
if bld.env['ENABLE_THREADING'] and bld.env["ENABLE_REAL_TIME"]:
obj = bld.create_ns3_program('main-test-sync', ['network'])
obj.source = 'main-test-sync.cc'

View File

@@ -1518,12 +1518,13 @@ DeterministicRandomVariable::GetInteger (void)
NS_OBJECT_ENSURE_REGISTERED (EmpiricalRandomVariable);
// ValueCDF methods
EmpiricalRandomVariable::ValueCDF::ValueCDF ()
EmpiricalRandomVariable::ValueCDF::ValueCDF (void)
: value (0.0),
cdf (0.0)
{
NS_LOG_FUNCTION (this);
}
EmpiricalRandomVariable::ValueCDF::ValueCDF (double v, double c)
: value (v),
cdf (c)
@@ -1531,11 +1532,12 @@ EmpiricalRandomVariable::ValueCDF::ValueCDF (double v, double c)
NS_LOG_FUNCTION (this << v << c);
NS_ASSERT (c >= 0.0 && c <= 1.0);
}
EmpiricalRandomVariable::ValueCDF::ValueCDF (const ValueCDF& c)
: value (c.value),
cdf (c.cdf)
bool
operator < (EmpiricalRandomVariable::ValueCDF a,
EmpiricalRandomVariable::ValueCDF b)
{
NS_LOG_FUNCTION (this << &c);
return a.cdf < b.cdf;
}
TypeId
@@ -1545,18 +1547,39 @@ EmpiricalRandomVariable::GetTypeId (void)
.SetParent<RandomVariableStream>()
.SetGroupName ("Core")
.AddConstructor<EmpiricalRandomVariable> ()
.AddAttribute ("Interpolate",
"Treat the CDF as a smooth distribution and interpolate, "
"default is to treat the CDF as a histogram and sample.",
BooleanValue (false),
MakeBooleanAccessor (&EmpiricalRandomVariable::m_interpolate),
MakeBooleanChecker ())
;
return tid;
}
EmpiricalRandomVariable::EmpiricalRandomVariable ()
:
m_validated (false)
EmpiricalRandomVariable::EmpiricalRandomVariable (void)
: m_validated (false)
{
NS_LOG_FUNCTION (this);
}
double
EmpiricalRandomVariable::GetValue (void)
bool
EmpiricalRandomVariable::SetInterpolate (bool interpolate)
{
NS_LOG_FUNCTION (this << interpolate);
bool prev = m_interpolate;
m_interpolate = interpolate;
return prev;
}
uint32_t
EmpiricalRandomVariable::GetInteger (void)
{
NS_LOG_FUNCTION (this);
return static_cast<uint32_t> (GetValue ());
}
bool
EmpiricalRandomVariable::PreSample (double & value)
{
NS_LOG_FUNCTION (this);
@@ -1564,29 +1587,61 @@ EmpiricalRandomVariable::GetValue (void)
{
Validate ();
}
// Get a uniform random variable in [0,1].
// Get a uniform random variable in [0, 1].
double r = Peek ()->RandU01 ();
if (IsAntithetic ())
{
r = (1 - r);
}
value = r;
bool valid = false;
// check extrema
if (r <= m_emp.front ().cdf)
{
return m_emp.front ().value; // Less than first
value = m_emp.front ().value; // Less than first
valid = true;
}
if (r >= m_emp.back ().cdf)
else if (r >= m_emp.back ().cdf)
{
return m_emp.back ().value; // Greater than last
value = m_emp.back ().value; // Greater than last
valid = true;
}
return valid;
}
double
EmpiricalRandomVariable::GetValue (void)
{
NS_LOG_FUNCTION (this);
double value;
if (PreSample (value))
{
return value;
}
// Binary search
auto bound = std::upper_bound (m_emp.begin (), m_emp.end (), r,
[] (double p, ValueCDF &it)
{
return p < it.cdf;
});
// value now has the (unused) URNG selector
if (m_interpolate)
{
value = DoInterpolate (value);
}
else
{
value = DoSampleCDF (value);
}
return value;
}
double
EmpiricalRandomVariable::DoSampleCDF (double r)
{
NS_LOG_FUNCTION (this << r);
ValueCDF selector (0, r);
auto bound = std::upper_bound (m_emp.begin (), m_emp.end (), selector);
return bound->value;
}
@@ -1595,52 +1650,55 @@ EmpiricalRandomVariable::Interpolate (void)
{
NS_LOG_FUNCTION (this);
if (!m_validated)
double value;
if (PreSample (value))
{
Validate ();
}
// Get a uniform random variable in [0, 1].
double r = Peek ()->RandU01 ();
if (IsAntithetic ())
{
r = (1 - r);
return value;
}
if (r <= m_emp.front ().cdf)
{
return m_emp.front ().value; // Less than first
}
if (r >= m_emp.back ().cdf)
{
return m_emp.back ().value; // Greater than last
}
// Binary search
auto bound = std::upper_bound (m_emp.begin (), m_emp.end (), r,
[] (double p, ValueCDF &it)
{
return p < it.cdf;
});
auto next = std::next(bound, 1);
return DoInterpolate (bound->cdf, next->cdf, bound->value, next->value, r);
// value now has the (unused) URNG selector
value = DoInterpolate (value);
return value;
}
uint32_t
EmpiricalRandomVariable::GetInteger (void)
double
EmpiricalRandomVariable::DoInterpolate (double r)
{
NS_LOG_FUNCTION (this);
return (uint32_t)GetValue ();
NS_LOG_FUNCTION (this << r);
// Return a value from the empirical distribution
// This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
// search
ValueCDF selector (0, r);
auto upper = std::upper_bound (m_emp.begin (), m_emp.end (), selector);
auto lower = std::prev (upper, 1);
if (upper == m_emp.begin ())
{
lower = upper;
}
// Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
double c1 = lower->cdf;
double c2 = upper->cdf;
double v1 = lower->value;
double v2 = upper->value;
double value = (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
return value;
}
void EmpiricalRandomVariable::CDF (double v, double c)
{ // Add a new empirical datapoint to the empirical cdf
void
EmpiricalRandomVariable::CDF (double v, double c)
{
// Add a new empirical datapoint to the empirical cdf
// NOTE. These MUST be inserted in non-decreasing order
NS_LOG_FUNCTION (this << v << c);
m_emp.push_back (ValueCDF (v, c));
}
void EmpiricalRandomVariable::Validate ()
void
EmpiricalRandomVariable::Validate (void)
{
NS_LOG_FUNCTION (this);
if (m_emp.empty ())
@@ -1648,9 +1706,8 @@ void EmpiricalRandomVariable::Validate ()
NS_FATAL_ERROR ("CDF is not initialized");
}
ValueCDF prior = m_emp[0];
for (std::vector<ValueCDF>::size_type i = 0; i < m_emp.size (); ++i)
for (auto current : m_emp)
{
ValueCDF& current = m_emp[i];
if (current.value < prior.value || current.cdf < prior.cdf)
{ // Error
std::cerr << "Empirical Dist error,"
@@ -1669,11 +1726,4 @@ void EmpiricalRandomVariable::Validate ()
m_validated = true;
}
double EmpiricalRandomVariable::DoInterpolate (double c1, double c2,
double v1, double v2, double r)
{ // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
NS_LOG_FUNCTION (this << c1 << c2 << v1 << v2 << r);
return (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
}
} // namespace ns3

View File

@@ -2403,34 +2403,70 @@ private:
/**
* \ingroup randomvariable
* \brief The Random Number Generator (RNG) that has a specified empirical distribution.
* \brief The Random Number Generator (RNG) that has a specified
* empirical distribution.
*
* Defines a random variable that has a specified, empirical
* distribution. The distribution is specified by a
* series of calls to the CDF member function, specifying a
* series of calls to the CDF() member function, specifying a
* value and the probability that the function value is less than
* the specified value. When values are requested,
* the specified value. When random values are requested,
* a uniform random variable is used to select a probability,
* and the return value is interpreted linearly between the
* two appropriate points in the CDF. The method is known
* and the return value is chosen from the largest input value with CDF
* less than the random value. The method is known
* as inverse transform sampling:
* (http://en.wikipedia.org/wiki/Inverse_transform_sampling).
*
* Here is an example of how to use this class:
* \code
* // Create the RNG with a uniform distribution between 0 and 10.
* Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
* x->CDF ( 0.0, 0.0);
* x->CDF ( 5.0, 0.5);
* x->CDF (10.0, 1.0);
* This generator has two modes: *sampling* and *interpolating*.
* In *sampling* mode this random variable generator
* treats the CDF as an exact histogram and returns
* one of the histogram inputs exactly. This is appropriate
* when the configured CDF represents the exact probability
* distribution, for a categorical variable, for example.
*
* // The expected value for the mean of the values returned by this
* // empirical distribution is the midpoint of the distribution
* //
* // E[value] = 5 .
* //
* double value = x->GetValue ();
* \endcode
* In *interpolating* mode this random variable generator linearly
* interpolates between the CDF values defining the histogram bins.
* This is appropriate when the configured CDF is an approximation
* to a continuous underlying probability distribution.
*
* For historical reasons the default is interpolating.
* To switch modes use the \c Interpolate Attribute, or call SetInterpolate().
* You can change modes at any time.
*
* If you find yourself switching frequently it could be simpler to
* set the mode to sampling, then use the GetValue() function for
* sampled values, and Interpolate() function for interpolated values.
*
* Here is an example of how to use this class:
*
* // Create the RNG with a non-uniform distribution between 0 and 10.
* // in sampling mode.
* Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
* x->SetInterpolate (false);
* x->CDF ( 0.0, 0.0);
* x->CDF ( 5.0, 0.25);
* x->CDF (10.0, 1.0);
*
* double value = x->GetValue ();
*
* The expected values and probabilities returned by GetValue are
*
* Value | Probability
* ----: | ----------:
* 0.0 | 0
* 5.0 | 25%
* 10.0 | 75%
*
* The only two values ever returned are 5 and 10, with unequal probability.
*
* If instead you want linear interpolation between the points of the CDF
* use the Interpolate() function:
*
* double interp = x->Interpolate ();
*
* This will return continuous values on the range [0,1).
*
* See empirical-random-variable-example.cc for an example.
*/
class EmpiricalRandomVariable : public RandomVariableStream
{
@@ -2443,14 +2479,16 @@ public:
/**
* \brief Creates an empirical RNG that has a specified, empirical
* distribution.
* distribution, and configured for interpolating mode.
*/
EmpiricalRandomVariable ();
EmpiricalRandomVariable (void);
/**
* \brief Specifies a point in the empirical distribution
* \note These *MUST* be inserted in ascending order of \p c
*
* \param [in] v The function value for this point
* \param [in] c Probability that the function is less than or equal to v
* \param [in] c Probability that the function is less than or equal to \p v
*/
void CDF (double v, double c); // Value, prob <= Value
@@ -2460,6 +2498,7 @@ public:
*
* Note that this does not interpolate the CDF, but treats it as a
* stepwise continuous function.
*
* Also note that antithetic values are being generated if m_isAntithetic
* is equal to true. If \f$u\f$ is a uniform variable over [0,1]
* and \f$x\f$ is a value that would be returned normally, then
@@ -2485,39 +2524,44 @@ public:
virtual uint32_t GetInteger (void);
/**
* \brief Returns the next value in the empirical distribution using linear interpolation.
* \return The floating point next value in the empirical distribution using linear interpolation.
* \brief Returns the next value in the empirical distribution using
* linear interpolation.
* \return The floating point next value in the empirical distribution
* using linear interpolation.
*/
virtual double Interpolate (void);
/**
* \brief Switch the mode between sampling the CDF and interpolating.
* The default mode is sampling.
* \param [in] interpolate If \c true set to interpolation, otherwise sampling.
* \returns The previous interpolate flag value.
*/
bool SetInterpolate (bool interpolate);
private:
/** Helper to hold one point of the CDF. */
/** \brief Helper to hold one point of the CDF. */
class ValueCDF
{
public:
/** Constructor. */
ValueCDF ();
/** \brief Constructor. */
ValueCDF (void);
/**
* Construct from values.
* \brief Construct from values.
*
* \param [in] v The argument value.
* \param [in] c The CDF at the argument value \pname{v}
*/
ValueCDF (double v, double c);
/**
* Copy constructor.
*
* \param [in] c The other ValueCDF.
*/
ValueCDF (const ValueCDF& c);
/** The argument value. */
double value;
/** The CDF at \pname{value} */
double cdf;
};
}; // class ValueCDF
/**
* Check that the CDF is valid.
* \brief Check that the CDF is valid.
*
* A valid CDF has
*
@@ -2526,25 +2570,54 @@ private:
*
* It is a fatal error to fail validation.
*/
virtual void Validate ();
void Validate (void);
/**
* \brief Do the initial rng draw and check against the extrema.
*
* If the extrema apply, \c value will have the extremal value
* and the return will be \c true.
*
* If the extrema do not apply \c value will have the URNG value
* and the return will be \c false.
*
* \param [out] value The extremal value, or the URNG.
* \returns \c true if \p value is the extremal result,
* or \c false if \p value is the URNG value.
*/
bool PreSample (double & value);
/**
* Linear interpolation between two points on the CDF to estimate
* \brief Sample the CDF as a histogram (without interpolation).
* \param [in] r The CDF value at which to sample the CDF.
* \return The bin value corresponding to \c r.
*/
double DoSampleCDF (double r);
/**
* \brief Linear interpolation between two points on the CDF to estimate
* the value at \p r.
*
* \param [in] c1 The first argument value.
* \param [in] c2 The second argument value.
* \param [in] v1 The first CDF value.
* \param [in] v2 The second CDF value.
* \param [in] r The argument value to interpolate to.
* \returns The interpolated CDF at \pname{r}
*/
virtual double DoInterpolate (double c1, double c2,
double v1, double v2, double r);
double DoInterpolate (double r);
/**
* \brief Comparison operator, for use by std::upper_bound
* \param a [in] the first value
* \param b [in] the second value
* \returns \c true if \c a.cdf < \c b.cdf
*/
friend
bool operator < (ValueCDF a, ValueCDF b);
/** \c true once the CDF has been validated. */
bool m_validated;
/** The vector of CDF points. */
std::vector<ValueCDF> m_emp;
/**
* If \c true GetValue will interpolate,
* otherwise treat CDF as normal histogram.
*/
bool m_interpolate;
}; // class EmpiricalRandomVariable

View File

@@ -2741,26 +2741,39 @@ RandomVariableStreamEmpiricalTestCase::DoRun (void)
// Create the RNG with a uniform distribution between 0 and 10.
Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
x->SetInterpolate (false);
x->CDF ( 0.0, 0.0);
x->CDF ( 5.0, 0.5);
x->CDF ( 5.0, 0.25);
x->CDF (10.0, 1.0);
// Calculate the mean of these values.
double sum = 0.0;
double value;
// Check that only the correct values are returned
for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
{
value = x->GetValue ();
double value = x->GetValue ();
NS_TEST_EXPECT_MSG_EQ ( (value == 5) || (value == 10), true,
"Incorrect value returned, expected only 5 or 10.");
}
// Calculate the mean of the interpolated values.
double sum = 0.0;
for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
{
double value = x->Interpolate ();
sum += value;
}
double valueMean = sum / N_MEASUREMENTS;
// The expected distribution (with interpolation) is
// Domain Probability
// [0, 5) 25%
// [5, 10) 75%
//
// The expected value for the mean of the values returned by this
// empirical distribution is the midpoint of the distribution
// empirical distribution is
//
// E[value] = 5 .
// E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
//
double expectedMean = 5.0;
double expectedMean = 6.25;
// Test that values have approximately the right mean value.
double TOLERANCE = expectedMean * 1e-2;
@@ -2768,6 +2781,7 @@ RandomVariableStreamEmpiricalTestCase::DoRun (void)
// Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
Ptr<EmpiricalRandomVariable> y = CreateObject<EmpiricalRandomVariable> ();
y->SetInterpolate (false);
y->CDF (-1.0, 0.0);
y->CDF (0.0, 0.5);
y->CDF (1.0, 1.0);
@@ -2803,29 +2817,38 @@ RandomVariableStreamEmpiricalAntitheticTestCase::DoRun (void)
// Create the RNG with a uniform distribution between 0 and 10.
Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
x->SetInterpolate (false);
x->CDF ( 0.0, 0.0);
x->CDF ( 5.0, 0.5);
x->CDF ( 5.0, 0.25);
x->CDF (10.0, 1.0);
// Make this generate antithetic values.
x->SetAttribute ("Antithetic", BooleanValue (true));
// Check that only the correct values are returned
for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
{
double value = x->GetValue ();
NS_TEST_EXPECT_MSG_EQ ( (value == 5) || (value == 10), true,
"Incorrect value returned, expected only 5 or 10.");
}
// Calculate the mean of these values.
double sum = 0.0;
double value;
for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
{
value = x->GetValue ();
value = x->Interpolate ();
sum += value;
}
double valueMean = sum / N_MEASUREMENTS;
// The expected value for the mean of the values returned by this
// empirical distribution is the midpoint of the distribution
// empirical distribution is
//
// E[value] = 5 .
// E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
//
double expectedMean = 5.0;
double expectedMean = 6.25;
// Test that values have approximately the right mean value.
double TOLERANCE = expectedMean * 1e-2;
@@ -2841,41 +2864,41 @@ public:
RandomVariableStreamTestSuite::RandomVariableStreamTestSuite ()
: TestSuite ("random-variable-stream-generators", UNIT)
{
AddTestCase (new RandomVariableStreamUniformTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamUniformAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamConstantTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamSequentialTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamNormalTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamNormalAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamExponentialTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamExponentialAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamParetoTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamParetoAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamWeibullTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamWeibullAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamLogNormalTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamUniformTestCase);
AddTestCase (new RandomVariableStreamUniformAntitheticTestCase);
AddTestCase (new RandomVariableStreamConstantTestCase);
AddTestCase (new RandomVariableStreamSequentialTestCase);
AddTestCase (new RandomVariableStreamNormalTestCase);
AddTestCase (new RandomVariableStreamNormalAntitheticTestCase);
AddTestCase (new RandomVariableStreamExponentialTestCase);
AddTestCase (new RandomVariableStreamExponentialAntitheticTestCase);
AddTestCase (new RandomVariableStreamParetoTestCase);
AddTestCase (new RandomVariableStreamParetoAntitheticTestCase);
AddTestCase (new RandomVariableStreamWeibullTestCase);
AddTestCase (new RandomVariableStreamWeibullAntitheticTestCase);
AddTestCase (new RandomVariableStreamLogNormalTestCase);
/// \todo This test is currently disabled because it fails sometimes.
/// A possible reason for the failure is that the antithetic code is
/// not implemented properly for this log-normal case.
/*
AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase);
*/
AddTestCase (new RandomVariableStreamGammaTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamGammaTestCase);
/// \todo This test is currently disabled because it fails sometimes.
/// A possible reason for the failure is that the antithetic code is
/// not implemented properly for this gamma case.
/*
AddTestCase (new RandomVariableStreamGammaAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamGammaAntitheticTestCase);
*/
AddTestCase (new RandomVariableStreamErlangTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamErlangAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamZipfTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamZipfAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamZetaTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamZetaAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamDeterministicTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamEmpiricalTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamEmpiricalAntitheticTestCase, TestCase::QUICK);
AddTestCase (new RandomVariableStreamErlangTestCase);
AddTestCase (new RandomVariableStreamErlangAntitheticTestCase);
AddTestCase (new RandomVariableStreamZipfTestCase);
AddTestCase (new RandomVariableStreamZipfAntitheticTestCase);
AddTestCase (new RandomVariableStreamZetaTestCase);
AddTestCase (new RandomVariableStreamZetaAntitheticTestCase);
AddTestCase (new RandomVariableStreamDeterministicTestCase);
AddTestCase (new RandomVariableStreamEmpiricalTestCase);
AddTestCase (new RandomVariableStreamEmpiricalAntitheticTestCase);
}
static RandomVariableStreamTestSuite randomVariableStreamTestSuite;