A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
random-variable-stream-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009-12 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * This file is based on rng-test-suite.cc.
7 *
8 * Modified by Mitch Watrous <watrous@u.washington.edu>
9 *
10 */
11
12#include "ns3/boolean.h"
13#include "ns3/double.h"
14#include "ns3/integer.h"
15#include "ns3/log.h"
16#include "ns3/random-variable-stream.h"
17#include "ns3/rng-seed-manager.h"
18#include "ns3/shuffle.h"
19#include "ns3/string.h"
20#include "ns3/test.h"
21#include "ns3/uinteger.h"
22
23#include <cmath>
24#include <ctime>
25#include <fstream>
26#include <gsl/gsl_cdf.h>
27#include <gsl/gsl_histogram.h>
28#include <gsl/gsl_randist.h>
29#include <gsl/gsl_sf_zeta.h>
30
31using namespace ns3;
32
33NS_LOG_COMPONENT_DEFINE("RandomVariableStreamGenerators");
34
35namespace ns3
36{
37
38namespace test
39{
40
41namespace RandomVariable
42{
43
44/**
45 * \file
46 * \ingroup rng-tests
47 * Random number generator streams tests.
48 */
49
50/**
51 * \ingroup rng-tests
52 * Base class for RandomVariableStream test suites.
53 */
54class TestCaseBase : public TestCase
55{
56 public:
57 /** Number of bins for sampling the distributions. */
58 static const uint32_t N_BINS{50};
59 /** Number of samples to draw when populating the distributions. */
60 static const uint32_t N_MEASUREMENTS{1000000};
61 /** Number of retry attempts to pass a chi-square test. */
62 static const uint32_t N_RUNS{5};
63
64 /**
65 * Constructor
66 * \param [in] name The test case name.
67 */
68 TestCaseBase(std::string name)
69 : TestCase(name)
70 {
71 }
72
73 /**
74 * Configure a GSL histogram with uniform bins, with optional
75 * under/over-flow bins.
76 * \param [in,out] h The GSL histogram to configure.
77 * \param [in] start The minimum value of the lowest bin.
78 * \param [in] end The maximum value of the last bin.
79 * \param [in] underflow If \c true the lowest bin should contain the underflow,
80 * \param [in] overflow If \c true the highest bin should contain the overflow.
81 * \returns A vector of the bin edges, including the top of the highest bin.
82 * This vector has one more entry than the number of bins in the histogram.
83 */
84 std::vector<double> UniformHistogramBins(gsl_histogram* h,
85 double start,
86 double end,
87 bool underflow = true,
88 bool overflow = true) const
89 {
90 NS_LOG_FUNCTION(this << h << start << end);
91 std::size_t nBins = gsl_histogram_bins(h);
92 double increment = (end - start) / (nBins - 1.);
93 double d = start;
94
95 std::vector<double> range(nBins + 1);
96
97 for (auto& r : range)
98 {
99 r = d;
100 d += increment;
101 }
102 if (underflow)
103 {
104 range[0] = -std::numeric_limits<double>::max();
105 }
106 if (overflow)
107 {
108 range[nBins] = std::numeric_limits<double>::max();
109 }
110
111 gsl_histogram_set_ranges(h, range.data(), nBins + 1);
112 return range;
113 }
114
115 /**
116 * Compute the average of a random variable.
117 * \param [in] rng The random variable to sample.
118 * \returns The average of \c N_MEASUREMENTS samples.
119 */
121 {
122 NS_LOG_FUNCTION(this << rng);
123 double sum = 0.0;
124 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
125 {
126 double value = rng->GetValue();
127 sum += value;
128 }
129 double valueMean = sum / N_MEASUREMENTS;
130 return valueMean;
131 }
132
133 /**
134 * Compute the variance of a random variable.
135 * \param [in] rng The random variable to sample.
136 * \param [in] average The previously calculated average value.
137 * \returns The variance of \c N_MEASUREMENTS samples.
138 */
139 double Variance(Ptr<RandomVariableStream> rng, double average) const
140 {
141 NS_LOG_FUNCTION(this << rng);
142 auto sum = 0.0;
143 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
144 {
145 const auto value = rng->GetValue();
146 sum += std::pow(value - average, 2);
147 }
148 const auto valueVariance = sum / N_MEASUREMENTS;
149 return valueVariance;
150 }
151
152 /** A factory base class to create new instances of a random variable. */
154 {
155 public:
156 /**
157 * Create a new instance of a random variable stream
158 * \returns The new random variable stream instance.
159 */
161 };
162
163 /**
164 * Factory class to create new instances of a particular random variable stream.
165 *
166 * \tparam RNG The type of random variable generator to create.
167 */
168 template <typename RNG>
170 {
171 public:
172 /**
173 * Constructor.
174 * \param [in] anti Create antithetic streams if \c true.
175 */
176 RngGenerator(bool anti = false)
177 : m_anti(anti)
178 {
179 }
180
181 // Inherited
183 {
184 auto rng = CreateObject<RNG>();
185 rng->SetAttribute("Antithetic", BooleanValue(m_anti));
186 return rng;
187 }
188
189 private:
190 /** Whether to create antithetic random variable streams. */
191 bool m_anti;
192 };
193
194 /**
195 * Compute the chi squared value of a sampled distribution
196 * compared to the expected distribution.
197 *
198 * This function captures the actual computation of the chi square,
199 * given an expected distribution.
200 *
201 * The random variable is sampled \c N_MEASUREMENTS times, filling
202 * a histogram. The chi square value is formed by comparing to the
203 * expected distribution.
204 * \param [in,out] h The histogram, which defines the binning for sampling.
205 * \param [in] expected The expected distribution.
206 * \param [in] rng The random variable to sample.
207 * \returns The chi square value.
208 */
209 double ChiSquared(gsl_histogram* h,
210 const std::vector<double>& expected,
212 {
213 NS_LOG_FUNCTION(this << h << expected.size() << rng);
214 NS_ASSERT_MSG(gsl_histogram_bins(h) == expected.size(),
215 "Histogram and expected vector have different sizes.");
216
217 // Sample the rng into the histogram
218 for (std::size_t i = 0; i < N_MEASUREMENTS; ++i)
219 {
220 double value = rng->GetValue();
221 gsl_histogram_increment(h, value);
222 }
223
224 // Compute the chi square value
225 double chiSquared = 0;
226 std::size_t nBins = gsl_histogram_bins(h);
227 for (std::size_t i = 0; i < nBins; ++i)
228 {
229 double hbin = gsl_histogram_get(h, i);
230 double tmp = hbin - expected[i];
231 tmp *= tmp;
232 tmp /= expected[i];
233 chiSquared += tmp;
234 }
235
236 return chiSquared;
237 }
238
239 /**
240 * Compute the chi square value from a random variable.
241 *
242 * This function sets up the binning and expected distribution
243 * needed to actually compute the chi squared value, which
244 * should be done by a call to ChiSquared.
245 *
246 * This is the point of customization expected to be implemented
247 * in derived classes with the appropriate histogram binning and
248 * expected distribution. For example
249 *
250 * SomeRngTestCase::ChiSquaredTest (Ptr<RandomVariableStream> rng) const
251 * {
252 * gsl_histogram * h = gsl_histogram_alloc (N_BINS);
253 * auto range = UniformHistogramBins (h, -4., 4.);
254 * std::vector<double> expected (N_BINS);
255 * // Populated expected
256 * for (std::size_t i = 0; i < N_BINS; ++i)
257 * {
258 * expected[i] = ...;
259 * expected[i] *= N_MEASUREMENTS;
260 * }
261 * double chiSquared = ChiSquared (h, expected, rng);
262 * gsl_histogram_free (h);
263 * return chiSquared;
264 * }
265 *
266 * \param [in] rng The random number generator to test.
267 * \returns The chi squared value.
268 */
270 {
271 return 0;
272 }
273
274 /**
275 * Average the chi squared value over some number of runs,
276 * each run with a new instance of the random number generator.
277 * \param [in] generator The factory to create instances of the
278 * random number generator.
279 * \param [in] nRuns The number of runs to average over.
280 * \returns The average chi square over the number of runs.
281 */
282 double ChiSquaredsAverage(const RngGeneratorBase* generator, std::size_t nRuns) const
283 {
284 NS_LOG_FUNCTION(this << generator << nRuns);
285
286 double sum = 0.;
287 for (std::size_t i = 0; i < nRuns; ++i)
288 {
289 auto rng = generator->Create();
290 double result = ChiSquaredTest(rng);
291 sum += result;
292 }
293 sum /= (double)nRuns;
294 return sum;
295 }
296
297 /**
298 * Set the seed used for this test suite.
299 *
300 * This test suite is designed to be run with both deterministic and
301 * random seed and run number values. Deterministic values can be used
302 * for basic regression testing; random values can be used to more
303 * exhaustively test the generated streams, with the side effect of
304 * occasional test failures.
305 *
306 * By default, this test suite will use the default values of RngSeed = 1
307 * and RngRun = 1. Users can configure any other seed and run number
308 * in the usual way, but the special value of RngRun = 0 results in
309 * selecting a RngSeed value that corresponds to the seconds since epoch
310 * (\c time (0) from \c ctime). Note: this is not a recommended practice for
311 * seeding normal simulations, as described in the ns-3 manual, but
312 * allows the test to be exposed to a wider range of seeds.
313 *
314 * In either case, the values produced will be checked with a chi-squared
315 * test.
316 *
317 * For example, this command will cause this test suite to use the
318 * deterministic value of seed=3 and default run number=1 every time:
319 * NS_GLOBAL_VALUE="RngSeed=3" ./test.py -s random-variable-stream-generators
320 * or equivalently (to see log output):
321 * NS_LOG="RandomVariableStreamGenerators" NS_GLOBAL_VALUE="RngSeed=3" ./ns3 run "test-runner
322 * --suite=random-variable-stream-generators"
323 *
324 * Conversely, this command will cause this test suite to use a seed
325 * based on time-of-day, and run number=0:
326 * NS_GLOBAL_VALUE="RngRun=0" ./test.py -s random-variable-stream-generators
327 */
329 {
330 if (!m_seedSet)
331 {
332 uint32_t seed;
333 if (RngSeedManager::GetRun() == 0)
334 {
335 seed = static_cast<uint32_t>(time(nullptr));
336 m_seedSet = true;
338 "Special run number value of zero; seeding with time of day: " << seed);
339 }
340 else
341 {
343 m_seedSet = true;
344 NS_LOG_DEBUG("Using the values seed: " << seed
345 << " and run: " << RngSeedManager::GetRun());
346 }
348 }
349 }
350
351 private:
352 /** \c true if we've already set the seed the correctly. */
353 bool m_seedSet = false;
354
355}; // class TestCaseBase
356
357/**
358 * \ingroup rng-tests
359 * Test case for uniform distribution random variable stream generator.
360 */
362{
363 public:
364 // Constructor
366
367 // Inherited
368 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
369
370 private:
371 // Inherited
372 void DoRun() override;
373};
374
376 : TestCaseBase("Uniform Random Variable Stream Generator")
377{
378}
379
380double
382{
383 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
384
385 // Note that this assumes that the range for u is [0,1], which is
386 // the default range for this distribution.
387 gsl_histogram_set_ranges_uniform(h, 0., 1.);
388
389 std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
390
391 double chiSquared = ChiSquared(h, expected, rng);
392 gsl_histogram_free(h);
393 return chiSquared;
394}
395
396void
398{
399 NS_LOG_FUNCTION(this);
401
402 double confidence = 0.99;
403 double maxStatistic = gsl_cdf_chisq_Pinv(confidence, (N_BINS - 1));
404 NS_LOG_DEBUG("Chi square required at " << confidence << " confidence for " << N_BINS
405 << " bins is " << maxStatistic);
406
407 double result = maxStatistic;
408 // If chi-squared test fails, re-try it up to N_RUNS times
409 for (uint32_t i = 0; i < N_RUNS; ++i)
410 {
412 result = ChiSquaredTest(rng);
413 NS_LOG_DEBUG("Chi square result is " << result);
414 if (result < maxStatistic)
415 {
416 break;
417 }
418 }
419
420 NS_TEST_ASSERT_MSG_LT(result, maxStatistic, "Chi-squared statistic out of range");
421
422 double min = 0.0;
423 double max = 10.0;
424 double value;
425
426 // Create the RNG with the specified range.
428
429 x->SetAttribute("Min", DoubleValue(min));
430 x->SetAttribute("Max", DoubleValue(max));
431
432 // Test that values are always within the range:
433 //
434 // [min, max)
435 //
436 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
437 {
438 value = x->GetValue();
439 NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
440 NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
441 }
442
443 // Boundary checking on GetInteger; should be [min,max]; from bug 1964
444 static const uint32_t UNIFORM_INTEGER_MIN{0};
445 static const uint32_t UNIFORM_INTEGER_MAX{4294967295U};
446 // [0,0] should return 0
447 uint32_t intValue;
448 intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN);
449 NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MIN, "Uniform RV GetInteger boundary testing");
450 // [UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX] should return UNIFORM_INTEGER_MAX
451 intValue = x->GetInteger(UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX);
452 NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MAX, "Uniform RV GetInteger boundary testing");
453 // [0,1] should return mix of 0 or 1
454 intValue = 0;
455 for (int i = 0; i < 20; i++)
456 {
457 intValue += x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN + 1);
458 }
459 NS_TEST_ASSERT_MSG_GT(intValue, 0, "Uniform RV GetInteger boundary testing");
460 NS_TEST_ASSERT_MSG_LT(intValue, 20, "Uniform RV GetInteger boundary testing");
461 // [MAX-1,MAX] should return mix of MAX-1 or MAX
462 uint32_t count = 0;
463 for (int i = 0; i < 20; i++)
464 {
465 intValue = x->GetInteger(UNIFORM_INTEGER_MAX - 1, UNIFORM_INTEGER_MAX);
466 if (intValue == UNIFORM_INTEGER_MAX)
467 {
468 count++;
469 }
470 }
471 NS_TEST_ASSERT_MSG_GT(count, 0, "Uniform RV GetInteger boundary testing");
472 NS_TEST_ASSERT_MSG_LT(count, 20, "Uniform RV GetInteger boundary testing");
473 // multiple [0,UNIFORM_INTEGER_MAX] should return non-zero
474 intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
475 uint32_t intValue2 = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
476 NS_TEST_ASSERT_MSG_GT(intValue + intValue2, 0, "Uniform RV GetInteger boundary testing");
477}
478
479/**
480 * \ingroup rng-tests
481 * Test case for antithetic uniform distribution random variable stream generator
482 */
484{
485 public:
486 // Constructor
488
489 // Inherited
490 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
491
492 private:
493 // Inherited
494 void DoRun() override;
495};
496
498 : TestCaseBase("Antithetic Uniform Random Variable Stream Generator")
499{
500}
501
502double
504{
505 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
506
507 // Note that this assumes that the range for u is [0,1], which is
508 // the default range for this distribution.
509 gsl_histogram_set_ranges_uniform(h, 0., 1.);
510
511 std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
512
513 double chiSquared = ChiSquared(h, expected, rng);
514 gsl_histogram_free(h);
515 return chiSquared;
516}
517
518void
520{
521 NS_LOG_FUNCTION(this);
523
524 auto generator = RngGenerator<UniformRandomVariable>(true);
525 double sum = ChiSquaredsAverage(&generator, N_RUNS);
526 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
527 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
528
529 double min = 0.0;
530 double max = 10.0;
531 double value;
532
533 // Create the RNG with the specified range.
535
536 // Make this generate antithetic values.
537 x->SetAttribute("Antithetic", BooleanValue(true));
538
539 x->SetAttribute("Min", DoubleValue(min));
540 x->SetAttribute("Max", DoubleValue(max));
541
542 // Test that values are always within the range:
543 //
544 // [min, max)
545 //
546 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
547 {
548 value = x->GetValue();
549 NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
550 NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
551 }
552}
553
554/**
555 * \ingroup rng-tests
556 * Test case for constant random variable stream generator
557 */
559{
560 public:
561 // Constructor
563
564 private:
565 // Inherited
566 void DoRun() override;
567
568 /** Tolerance for testing rng values against expectation. */
569 static constexpr double TOLERANCE{1e-8};
570};
571
573 : TestCaseBase("Constant Random Variable Stream Generator")
574{
575}
576
577void
579{
580 NS_LOG_FUNCTION(this);
582
584
585 double constant;
586
587 // Test that the constant value can be changed using its attribute.
588 constant = 10.0;
589 c->SetAttribute("Constant", DoubleValue(constant));
590 NS_TEST_ASSERT_MSG_EQ_TOL(c->GetValue(), constant, TOLERANCE, "Constant value changed");
591 c->SetAttribute("Constant", DoubleValue(20.0));
592 NS_TEST_ASSERT_MSG_NE(c->GetValue(), constant, "Constant value not changed");
593
594 // Test that the constant value does not change.
595 constant = c->GetValue();
596 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
597 {
598 NS_TEST_ASSERT_MSG_EQ_TOL(c->GetValue(),
599 constant,
600 TOLERANCE,
601 "Constant value changed in loop");
602 }
603}
604
605/**
606 * \ingroup rng-tests
607 * Test case for sequential random variable stream generator
608 */
610{
611 public:
612 // Constructor
614
615 private:
616 // Inherited
617 void DoRun() override;
618
619 /** Tolerance for testing rng values against expectation. */
620 static constexpr double TOLERANCE{1e-8};
621};
622
624 : TestCaseBase("Sequential Random Variable Stream Generator")
625{
626}
627
628void
630{
631 NS_LOG_FUNCTION(this);
633
635
636 // The following four attributes should give the sequence
637 //
638 // 4, 4, 7, 7, 10, 10
639 //
640 s->SetAttribute("Min", DoubleValue(4));
641 s->SetAttribute("Max", DoubleValue(11));
642 s->SetAttribute("Increment", StringValue("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
643 s->SetAttribute("Consecutive", IntegerValue(2));
644
645 double value;
646
647 // Test that the sequencet is correct.
648 value = s->GetValue();
649 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 1 wrong.");
650 value = s->GetValue();
651 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 2 wrong.");
652 value = s->GetValue();
653 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 3 wrong.");
654 value = s->GetValue();
655 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 4 wrong.");
656 value = s->GetValue();
657 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 5 wrong.");
658 value = s->GetValue();
659 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 6 wrong.");
660}
661
662/**
663 * \ingroup rng-tests
664 * Test case for normal distribution random variable stream generator
665 */
667{
668 public:
669 // Constructor
671
672 // Inherited
673 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
674
675 private:
676 // Inherited
677 void DoRun() override;
678
679 /** Tolerance for testing rng values against expectation, in rms. */
680 static constexpr double TOLERANCE{5};
681};
682
684 : TestCaseBase("Normal Random Variable Stream Generator")
685{
686}
687
688double
690{
691 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
692 auto range = UniformHistogramBins(h, -4., 4.);
693
694 std::vector<double> expected(N_BINS);
695
696 // Note that this assumes that n has mean equal to zero and standard
697 // deviation equal to one, which are their default values for this
698 // distribution.
699 double sigma = 1.;
700
701 for (std::size_t i = 0; i < N_BINS; ++i)
702 {
703 expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
704 expected[i] *= N_MEASUREMENTS;
705 }
706
707 double chiSquared = ChiSquared(h, expected, rng);
708 gsl_histogram_free(h);
709 return chiSquared;
710}
711
712void
714{
715 NS_LOG_FUNCTION(this);
717
718 auto generator = RngGenerator<NormalRandomVariable>();
719 auto rng = generator.Create();
720
721 double sum = ChiSquaredsAverage(&generator, N_RUNS);
722 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
723 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
724
725 double mean = 5.0;
726 double variance = 2.0;
727
728 // Create the RNG with the specified range.
730 x->SetAttribute("Mean", DoubleValue(mean));
731 x->SetAttribute("Variance", DoubleValue(variance));
732
733 // Calculate the mean of these values.
734 double valueMean = Average(x);
735
736 // The expected value for the mean of the values returned by a
737 // normally distributed random variable is equal to mean.
738 double expectedMean = mean;
739 double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
740
741 // Test that values have approximately the right mean value.
743 expectedMean,
744 expectedRms * TOLERANCE,
745 "Wrong mean value.");
746}
747
748/**
749 * \ingroup rng-tests
750 * Test case for antithetic normal distribution random variable stream generator
751 */
753{
754 public:
755 // Constructor
757
758 // Inherited
759 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
760
761 private:
762 // Inherited
763 void DoRun() override;
764
765 /** Tolerance for testing rng values against expectation, in rms. */
766 static constexpr double TOLERANCE{5};
767};
768
770 : TestCaseBase("Antithetic Normal Random Variable Stream Generator")
771{
772}
773
774double
776{
777 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
778 auto range = UniformHistogramBins(h, -4, 4);
779
780 std::vector<double> expected(N_BINS);
781
782 // Note that this assumes that n has mean equal to zero and standard
783 // deviation equal to one, which are their default values for this
784 // distribution.
785 double sigma = 1.;
786
787 for (std::size_t i = 0; i < N_BINS; ++i)
788 {
789 expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
790 expected[i] *= N_MEASUREMENTS;
791 }
792
793 double chiSquared = ChiSquared(h, expected, rng);
794
795 gsl_histogram_free(h);
796 return chiSquared;
797}
798
799void
801{
802 NS_LOG_FUNCTION(this);
804
805 auto generator = RngGenerator<NormalRandomVariable>(true);
806 double sum = ChiSquaredsAverage(&generator, N_RUNS);
807 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
808 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
809
810 double mean = 5.0;
811 double variance = 2.0;
812
813 // Create the RNG with the specified range.
815 x->SetAttribute("Mean", DoubleValue(mean));
816 x->SetAttribute("Variance", DoubleValue(variance));
817
818 // Make this generate antithetic values.
819 x->SetAttribute("Antithetic", BooleanValue(true));
820
821 // Calculate the mean of these values.
822 double valueMean = Average(x);
823
824 // The expected value for the mean of the values returned by a
825 // normally distributed random variable is equal to mean.
826 double expectedMean = mean;
827 double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
828
829 // Test that values have approximately the right mean value.
831 expectedMean,
832 expectedRms * TOLERANCE,
833 "Wrong mean value.");
834}
835
836/**
837 * \ingroup rng-tests
838 * Test case for exponential distribution random variable stream generator
839 */
841{
842 public:
843 // Constructor
845
846 // Inherited
847 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
848
849 private:
850 // Inherited
851 void DoRun() override;
852
853 /** Tolerance for testing rng values against expectation, in rms. */
854 static constexpr double TOLERANCE{5};
855};
856
858 : TestCaseBase("Exponential Random Variable Stream Generator")
859{
860}
861
862double
864{
865 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
866 auto range = UniformHistogramBins(h, 0, 10, false);
867
868 std::vector<double> expected(N_BINS);
869
870 // Note that this assumes that e has mean equal to one, which is the
871 // default value for this distribution.
872 double mu = 1.;
873
874 for (std::size_t i = 0; i < N_BINS; ++i)
875 {
876 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
877 expected[i] *= N_MEASUREMENTS;
878 }
879
880 double chiSquared = ChiSquared(h, expected, rng);
881
882 gsl_histogram_free(h);
883 return chiSquared;
884}
885
886void
888{
889 NS_LOG_FUNCTION(this);
891
893 double sum = ChiSquaredsAverage(&generator, N_RUNS);
894 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
895 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
896
897 double mean = 3.14;
898 double bound = 0.0;
899
900 // Create the RNG with the specified range.
902 x->SetAttribute("Mean", DoubleValue(mean));
903 x->SetAttribute("Bound", DoubleValue(bound));
904
905 // Calculate the mean of these values.
906 double valueMean = Average(x);
907 double expectedMean = mean;
908 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
909
910 // Test that values have approximately the right mean value.
912 expectedMean,
913 expectedRms * TOLERANCE,
914 "Wrong mean value.");
915}
916
917/**
918 * \ingroup rng-tests
919 * Test case for antithetic exponential distribution random variable stream generator
920 */
922{
923 public:
924 // Constructor
926
927 // Inherited
928 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
929
930 private:
931 // Inherited
932 void DoRun() override;
933
934 /** Tolerance for testing rng values against expectation, in rms. */
935 static constexpr double TOLERANCE{5};
936};
937
939 : TestCaseBase("Antithetic Exponential Random Variable Stream Generator")
940{
941}
942
943double
945{
946 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
947 auto range = UniformHistogramBins(h, 0, 10, false);
948
949 std::vector<double> expected(N_BINS);
950
951 // Note that this assumes that e has mean equal to one, which is the
952 // default value for this distribution.
953 double mu = 1.;
954
955 for (std::size_t i = 0; i < N_BINS; ++i)
956 {
957 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
958 expected[i] *= N_MEASUREMENTS;
959 }
960
961 double chiSquared = ChiSquared(h, expected, rng);
962
963 gsl_histogram_free(h);
964 return chiSquared;
965}
966
967void
969{
970 NS_LOG_FUNCTION(this);
972
973 auto generator = RngGenerator<ExponentialRandomVariable>(true);
974 double sum = ChiSquaredsAverage(&generator, N_RUNS);
975 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
976 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
977
978 double mean = 3.14;
979 double bound = 0.0;
980
981 // Create the RNG with the specified range.
983 x->SetAttribute("Mean", DoubleValue(mean));
984 x->SetAttribute("Bound", DoubleValue(bound));
985
986 // Make this generate antithetic values.
987 x->SetAttribute("Antithetic", BooleanValue(true));
988
989 // Calculate the mean of these values.
990 double valueMean = Average(x);
991 double expectedMean = mean;
992 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
993
994 // Test that values have approximately the right mean value.
996 expectedMean,
997 expectedRms * TOLERANCE,
998 "Wrong mean value.");
999}
1000
1001/**
1002 * \ingroup rng-tests
1003 * Test case for Pareto distribution random variable stream generator
1004 */
1006{
1007 public:
1008 // Constructor
1010
1011 // Inherited
1012 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1013
1014 private:
1015 // Inherited
1016 void DoRun() override;
1017
1018 /**
1019 * Tolerance for testing rng values against expectation,
1020 * as a fraction of mean value.
1021 */
1022 static constexpr double TOLERANCE{1e-2};
1023};
1024
1026 : TestCaseBase("Pareto Random Variable Stream Generator")
1027{
1028}
1029
1030double
1032{
1033 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1034 auto range = UniformHistogramBins(h, 1, 10, false);
1035
1036 std::vector<double> expected(N_BINS);
1037
1038 double shape = 2.0;
1039 double scale = 1.0;
1040
1041 for (std::size_t i = 0; i < N_BINS; ++i)
1042 {
1043 expected[i] =
1044 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1045 expected[i] *= N_MEASUREMENTS;
1046 }
1047
1048 double chiSquared = ChiSquared(h, expected, rng);
1049
1050 gsl_histogram_free(h);
1051 return chiSquared;
1052}
1053
1054void
1056{
1057 NS_LOG_FUNCTION(this);
1059
1060 auto generator = RngGenerator<ParetoRandomVariable>();
1061 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1062 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1063 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1064
1065 double shape = 2.0;
1066 double scale = 1.0;
1067
1068 // Create the RNG with the specified range.
1070 x->SetAttribute("Shape", DoubleValue(shape));
1071 x->SetAttribute("Scale", DoubleValue(scale));
1072
1073 // Calculate the mean of these values.
1074 double valueMean = Average(x);
1075
1076 // The expected value for the mean is given by
1077 //
1078 // shape * scale
1079 // E[value] = --------------- ,
1080 // shape - 1
1081 //
1082 // where
1083 //
1084 // scale = mean * (shape - 1.0) / shape .
1085 double expectedMean = (shape * scale) / (shape - 1.0);
1086
1087 // Test that values have approximately the right mean value.
1088 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1089 expectedMean,
1090 expectedMean * TOLERANCE,
1091 "Wrong mean value.");
1092}
1093
1094/**
1095 * \ingroup rng-tests
1096 * Test case for antithetic Pareto distribution random variable stream generator
1097 */
1099{
1100 public:
1101 // Constructor
1103
1104 // Inherited
1105 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1106
1107 private:
1108 // Inherited
1109 void DoRun() override;
1110
1111 /**
1112 * Tolerance for testing rng values against expectation,
1113 * as a fraction of mean value.
1114 */
1115 static constexpr double TOLERANCE{1e-2};
1116};
1117
1119 : TestCaseBase("Antithetic Pareto Random Variable Stream Generator")
1120{
1121}
1122
1123double
1125{
1126 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1127 auto range = UniformHistogramBins(h, 1, 10, false);
1128
1129 std::vector<double> expected(N_BINS);
1130
1131 double shape = 2.0;
1132 double scale = 1.0;
1133
1134 for (std::size_t i = 0; i < N_BINS; ++i)
1135 {
1136 expected[i] =
1137 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1138 expected[i] *= N_MEASUREMENTS;
1139 }
1140
1141 double chiSquared = ChiSquared(h, expected, rng);
1142
1143 gsl_histogram_free(h);
1144 return chiSquared;
1145}
1146
1147void
1149{
1150 NS_LOG_FUNCTION(this);
1152
1153 auto generator = RngGenerator<ParetoRandomVariable>(true);
1154 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1155 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1156 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1157
1158 double shape = 2.0;
1159 double scale = 1.0;
1160
1161 // Create the RNG with the specified range.
1163 x->SetAttribute("Shape", DoubleValue(shape));
1164 x->SetAttribute("Scale", DoubleValue(scale));
1165
1166 // Make this generate antithetic values.
1167 x->SetAttribute("Antithetic", BooleanValue(true));
1168
1169 // Calculate the mean of these values.
1170 double valueMean = Average(x);
1171
1172 // The expected value for the mean is given by
1173 //
1174 // shape * scale
1175 // E[value] = --------------- ,
1176 // shape - 1
1177 //
1178 // where
1179 //
1180 // scale = mean * (shape - 1.0) / shape .
1181 //
1182 double expectedMean = (shape * scale) / (shape - 1.0);
1183
1184 // Test that values have approximately the right mean value.
1185 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1186 expectedMean,
1187 expectedMean * TOLERANCE,
1188 "Wrong mean value.");
1189}
1190
1191/**
1192 * \ingroup rng-tests
1193 * Test case for Weibull distribution random variable stream generator
1194 */
1196{
1197 public:
1198 // Constructor
1200
1201 // Inherited
1202 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1203
1204 private:
1205 // Inherited
1206 void DoRun() override;
1207
1208 /**
1209 * Tolerance for testing rng values against expectation,
1210 * as a fraction of mean value.
1211 */
1212 static constexpr double TOLERANCE{1e-2};
1213};
1214
1216 : TestCaseBase("Weibull Random Variable Stream Generator")
1217{
1218}
1219
1220double
1222{
1223 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1224 auto range = UniformHistogramBins(h, 1, 10, false);
1225
1226 std::vector<double> expected(N_BINS);
1227
1228 // Note that this assumes that p has shape equal to one and scale
1229 // equal to one, which are their default values for this
1230 // distribution.
1231 double a = 1.0;
1232 double b = 1.0;
1233
1234 for (std::size_t i = 0; i < N_BINS; ++i)
1235 {
1236 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1237 expected[i] *= N_MEASUREMENTS;
1238 NS_LOG_INFO("weibull: " << expected[i]);
1239 }
1240
1241 double chiSquared = ChiSquared(h, expected, rng);
1242
1243 gsl_histogram_free(h);
1244 return chiSquared;
1245}
1246
1247void
1249{
1250 NS_LOG_FUNCTION(this);
1252
1253 auto generator = RngGenerator<WeibullRandomVariable>();
1254 const auto sum = ChiSquaredsAverage(&generator, N_RUNS);
1255 const auto maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1256 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1257
1258 const auto scale = 5.0;
1259 const auto shape = 1.0;
1260
1261 // Create the RNG with the specified range.
1263 x->SetAttribute("Scale", DoubleValue(scale));
1264 x->SetAttribute("Shape", DoubleValue(shape));
1265
1266 // Calculate the mean of these values.
1267 const auto measuredMean = Average(x);
1268
1269 // The expected value for the mean of the values returned by a
1270 // Weibull distributed random variable is
1271 //
1272 // E[value] = scale * Gamma(1 + 1 / shape) ,
1273 //
1274 // where Gamma() is the Gamma function. Note that
1275 //
1276 // Gamma(n) = (n - 1)!
1277 //
1278 // if n is a positive integer.
1279 //
1280 // For this test,
1281 //
1282 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1283 // = Gamma(2)
1284 // = (2 - 1)!
1285 // = 1
1286 //
1287 // which means
1288 //
1289 // E[value] = scale .
1290 //
1291 const auto expectedMean = scale;
1292
1293 // Test calculated and expected mean values are identical.
1294 const auto valueMean = x->GetMean();
1295 NS_TEST_ASSERT_MSG_EQ(valueMean, expectedMean, "Wrong calculated mean value.");
1296
1297 // Test that values have approximately the right mean value.
1298 NS_TEST_ASSERT_MSG_EQ_TOL(measuredMean,
1299 expectedMean,
1300 expectedMean * TOLERANCE,
1301 "Wrong measured mean value.");
1302}
1303
1304/**
1305 * \ingroup rng-tests
1306 * Test case for antithetic Weibull distribution random variable stream generator
1307 */
1309{
1310 public:
1311 // Constructor
1313
1314 // Inherited
1315 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1316
1317 private:
1318 // Inherited
1319 void DoRun() override;
1320
1321 /**
1322 * Tolerance for testing rng values against expectation,
1323 * as a fraction of mean value.
1324 */
1325 static constexpr double TOLERANCE{1e-2};
1326};
1327
1329 : TestCaseBase("Antithetic Weibull Random Variable Stream Generator")
1330{
1331}
1332
1333double
1335{
1336 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1337 auto range = UniformHistogramBins(h, 1, 10, false);
1338
1339 std::vector<double> expected(N_BINS);
1340
1341 // Note that this assumes that p has shape equal to one and scale
1342 // equal to one, which are their default values for this
1343 // distribution.
1344 double a = 1.0;
1345 double b = 1.0;
1346
1347 for (std::size_t i = 0; i < N_BINS; ++i)
1348 {
1349 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1350 expected[i] *= N_MEASUREMENTS;
1351 }
1352
1353 double chiSquared = ChiSquared(h, expected, rng);
1354
1355 gsl_histogram_free(h);
1356 return chiSquared;
1357}
1358
1359void
1361{
1362 NS_LOG_FUNCTION(this);
1364
1365 auto generator = RngGenerator<WeibullRandomVariable>(true);
1366 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1367 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1368 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1369
1370 double scale = 5.0;
1371 double shape = 1.0;
1372
1373 // Create the RNG with the specified range.
1375 x->SetAttribute("Scale", DoubleValue(scale));
1376 x->SetAttribute("Shape", DoubleValue(shape));
1377
1378 // Make this generate antithetic values.
1379 x->SetAttribute("Antithetic", BooleanValue(true));
1380
1381 // Calculate the mean of these values.
1382 double valueMean = Average(x);
1383
1384 // The expected value for the mean of the values returned by a
1385 // Weibull distributed random variable is
1386 //
1387 // E[value] = scale * Gamma(1 + 1 / shape) ,
1388 //
1389 // where Gamma() is the Gamma function. Note that
1390 //
1391 // Gamma(n) = (n - 1)!
1392 //
1393 // if n is a positive integer.
1394 //
1395 // For this test,
1396 //
1397 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1398 // = Gamma(2)
1399 // = (2 - 1)!
1400 // = 1
1401 //
1402 // which means
1403 //
1404 // E[value] = scale .
1405 //
1406 double expectedMean = scale;
1407
1408 // Test that values have approximately the right mean value.
1409 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1410 expectedMean,
1411 expectedMean * TOLERANCE,
1412 "Wrong mean value.");
1413}
1414
1415/**
1416 * \ingroup rng-tests
1417 * Test case for log-normal distribution random variable stream generator
1418 */
1420{
1421 public:
1422 // Constructor
1424
1425 // Inherited
1426 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1427
1428 private:
1429 // Inherited
1430 void DoRun() override;
1431
1432 /**
1433 * Tolerance for testing rng values against expectation,
1434 * as a fraction of mean value.
1435 */
1436 static constexpr double TOLERANCE{3e-2};
1437};
1438
1440 : TestCaseBase("Log-Normal Random Variable Stream Generator")
1441{
1442}
1443
1444double
1446{
1447 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1448 auto range = UniformHistogramBins(h, 0, 10, false);
1449
1450 std::vector<double> expected(N_BINS);
1451
1452 // Note that this assumes that n has mu equal to zero and sigma
1453 // equal to one, which are their default values for this
1454 // distribution.
1455 double mu = 0.0;
1456 double sigma = 1.0;
1457
1458 for (std::size_t i = 0; i < N_BINS; ++i)
1459 {
1460 expected[i] =
1461 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1462 expected[i] *= N_MEASUREMENTS;
1463 }
1464
1465 double chiSquared = ChiSquared(h, expected, rng);
1466
1467 gsl_histogram_free(h);
1468 return chiSquared;
1469}
1470
1471void
1473{
1474 NS_LOG_FUNCTION(this);
1476
1477 auto generator = RngGenerator<LogNormalRandomVariable>();
1478 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1479 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1480
1481 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1482
1483 double mu = 5.0;
1484 double sigma = 2.0;
1485
1486 // Create the RNG with the specified range.
1488 x->SetAttribute("Mu", DoubleValue(mu));
1489 x->SetAttribute("Sigma", DoubleValue(sigma));
1490
1491 // Calculate the mean of these values.
1492 double valueMean = Average(x);
1493
1494 // The expected value for the mean of the values returned by a
1495 // log-normally distributed random variable is equal to
1496 //
1497 // 2
1498 // mu + sigma / 2
1499 // E[value] = e .
1500 //
1501 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1502
1503 // Test that values have approximately the right mean value.
1504 //
1505 /**
1506 * \todo This test fails sometimes if the required tolerance is less
1507 * than 3%, which may be because there is a bug in the
1508 * implementation or that the mean of this distribution is more
1509 * sensitive to its parameters than the others are.
1510 */
1511 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1512 expectedMean,
1513 expectedMean * TOLERANCE,
1514 "Wrong mean value.");
1515}
1516
1517/**
1518 * \ingroup rng-tests
1519 * Test case for antithetic log-normal distribution random variable stream generator
1520 */
1522{
1523 public:
1524 // Constructor
1526
1527 // Inherited
1528 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1529
1530 private:
1531 // Inherited
1532 void DoRun() override;
1533
1534 /**
1535 * Tolerance for testing rng values against expectation,
1536 * as a fraction of mean value.
1537 */
1538 static constexpr double TOLERANCE{3e-2};
1539};
1540
1542 : TestCaseBase("Antithetic Log-Normal Random Variable Stream Generator")
1543{
1544}
1545
1546double
1548{
1549 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1550 auto range = UniformHistogramBins(h, 0, 10, false);
1551
1552 std::vector<double> expected(N_BINS);
1553
1554 // Note that this assumes that n has mu equal to zero and sigma
1555 // equal to one, which are their default values for this
1556 // distribution.
1557 double mu = 0.0;
1558 double sigma = 1.0;
1559
1560 for (std::size_t i = 0; i < N_BINS; ++i)
1561 {
1562 expected[i] =
1563 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1564 expected[i] *= N_MEASUREMENTS;
1565 }
1566
1567 double chiSquared = ChiSquared(h, expected, rng);
1568
1569 gsl_histogram_free(h);
1570 return chiSquared;
1571}
1572
1573void
1575{
1576 NS_LOG_FUNCTION(this);
1578
1579 auto generator = RngGenerator<LogNormalRandomVariable>(true);
1580 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1581 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1582 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1583
1584 double mu = 5.0;
1585 double sigma = 2.0;
1586
1587 // Create the RNG with the specified range.
1589 x->SetAttribute("Mu", DoubleValue(mu));
1590 x->SetAttribute("Sigma", DoubleValue(sigma));
1591
1592 // Make this generate antithetic values.
1593 x->SetAttribute("Antithetic", BooleanValue(true));
1594
1595 // Calculate the mean of these values.
1596 double valueMean = Average(x);
1597
1598 // The expected value for the mean of the values returned by a
1599 // log-normally distributed random variable is equal to
1600 //
1601 // 2
1602 // mu + sigma / 2
1603 // E[value] = e .
1604 //
1605 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1606
1607 // Test that values have approximately the right mean value.
1608 //
1609 /**
1610 * \todo This test fails sometimes if the required tolerance is less
1611 * than 3%, which may be because there is a bug in the
1612 * implementation or that the mean of this distribution is more
1613 * sensitive to its parameters than the others are.
1614 */
1615 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1616 expectedMean,
1617 expectedMean * TOLERANCE,
1618 "Wrong mean value.");
1619}
1620
1621/**
1622 * \ingroup rng-tests
1623 * Test case for gamma distribution random variable stream generator
1624 */
1626{
1627 public:
1628 // Constructor
1629 GammaTestCase();
1630
1631 // Inherited
1632 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1633
1634 private:
1635 // Inherited
1636 void DoRun() override;
1637
1638 /**
1639 * Tolerance for testing rng values against expectation,
1640 * as a fraction of mean value.
1641 */
1642 static constexpr double TOLERANCE{1e-2};
1643};
1644
1646 : TestCaseBase("Gamma Random Variable Stream Generator")
1647{
1648}
1649
1650double
1652{
1653 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1654 auto range = UniformHistogramBins(h, 0, 10, false);
1655
1656 std::vector<double> expected(N_BINS);
1657
1658 // Note that this assumes that n has alpha equal to one and beta
1659 // equal to one, which are their default values for this
1660 // distribution.
1661 double alpha = 1.0;
1662 double beta = 1.0;
1663
1664 for (std::size_t i = 0; i < N_BINS; ++i)
1665 {
1666 expected[i] =
1667 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1668 expected[i] *= N_MEASUREMENTS;
1669 }
1670
1671 double chiSquared = ChiSquared(h, expected, rng);
1672
1673 gsl_histogram_free(h);
1674 return chiSquared;
1675}
1676
1677void
1679{
1680 NS_LOG_FUNCTION(this);
1682
1683 auto generator = RngGenerator<GammaRandomVariable>();
1684 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1685 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1686 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1687
1688 double alpha = 5.0;
1689 double beta = 2.0;
1690
1691 // Create the RNG with the specified range.
1693 x->SetAttribute("Alpha", DoubleValue(alpha));
1694 x->SetAttribute("Beta", DoubleValue(beta));
1695
1696 // Calculate the mean of these values.
1697 double valueMean = Average(x);
1698
1699 // The expected value for the mean of the values returned by a
1700 // gammaly distributed random variable is equal to
1701 //
1702 // E[value] = alpha * beta .
1703 //
1704 double expectedMean = alpha * beta;
1705
1706 // Test that values have approximately the right mean value.
1707 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1708 expectedMean,
1709 expectedMean * TOLERANCE,
1710 "Wrong mean value.");
1711}
1712
1713/**
1714 * \ingroup rng-tests
1715 * Test case for antithetic gamma distribution random variable stream generator
1716 */
1718{
1719 public:
1720 // Constructor
1722
1723 // Inherited
1724 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1725
1726 private:
1727 // Inherited
1728 void DoRun() override;
1729
1730 /**
1731 * Tolerance for testing rng values against expectation,
1732 * as a fraction of mean value.
1733 */
1734 static constexpr double TOLERANCE{1e-2};
1735};
1736
1738 : TestCaseBase("Antithetic Gamma Random Variable Stream Generator")
1739{
1740}
1741
1742double
1744{
1745 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1746 auto range = UniformHistogramBins(h, 0, 10, false);
1747
1748 std::vector<double> expected(N_BINS);
1749
1750 // Note that this assumes that n has alpha equal to one and beta
1751 // equal to one, which are their default values for this
1752 // distribution.
1753 double alpha = 1.0;
1754 double beta = 1.0;
1755
1756 for (std::size_t i = 0; i < N_BINS; ++i)
1757 {
1758 expected[i] =
1759 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1760 expected[i] *= N_MEASUREMENTS;
1761 }
1762
1763 double chiSquared = ChiSquared(h, expected, rng);
1764
1765 gsl_histogram_free(h);
1766 return chiSquared;
1767}
1768
1769void
1771{
1772 NS_LOG_FUNCTION(this);
1774
1775 auto generator = RngGenerator<GammaRandomVariable>(true);
1776 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1777 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1778 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1779
1780 double alpha = 5.0;
1781 double beta = 2.0;
1782
1783 // Create the RNG with the specified range.
1785
1786 // Make this generate antithetic values.
1787 x->SetAttribute("Antithetic", BooleanValue(true));
1788
1789 x->SetAttribute("Alpha", DoubleValue(alpha));
1790 x->SetAttribute("Beta", DoubleValue(beta));
1791
1792 // Calculate the mean of these values.
1793 double valueMean = Average(x);
1794
1795 // The expected value for the mean of the values returned by a
1796 // gammaly distributed random variable is equal to
1797 //
1798 // E[value] = alpha * beta .
1799 //
1800 double expectedMean = alpha * beta;
1801
1802 // Test that values have approximately the right mean value.
1803 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1804 expectedMean,
1805 expectedMean * TOLERANCE,
1806 "Wrong mean value.");
1807}
1808
1809/**
1810 * \ingroup rng-tests
1811 * Test case for Erlang distribution random variable stream generator
1812 */
1814{
1815 public:
1816 // Constructor
1818
1819 // Inherited
1820 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1821
1822 private:
1823 // Inherited
1824 void DoRun() override;
1825
1826 /**
1827 * Tolerance for testing rng values against expectation,
1828 * as a fraction of mean value.
1829 */
1830 static constexpr double TOLERANCE{1e-2};
1831};
1832
1834 : TestCaseBase("Erlang Random Variable Stream Generator")
1835{
1836}
1837
1838double
1840{
1841 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1842 auto range = UniformHistogramBins(h, 0, 10, false);
1843
1844 std::vector<double> expected(N_BINS);
1845
1846 // Note that this assumes that n has k equal to one and lambda
1847 // equal to one, which are their default values for this
1848 // distribution.
1849 uint32_t k = 1;
1850 double lambda = 1.0;
1851
1852 // Note that Erlang distribution is equal to the gamma distribution
1853 // when k is an integer, which is why the gamma distribution's cdf
1854 // function can be used here.
1855 for (std::size_t i = 0; i < N_BINS; ++i)
1856 {
1857 expected[i] =
1858 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1859 expected[i] *= N_MEASUREMENTS;
1860 }
1861
1862 double chiSquared = ChiSquared(h, expected, rng);
1863
1864 gsl_histogram_free(h);
1865 return chiSquared;
1866}
1867
1868void
1870{
1871 NS_LOG_FUNCTION(this);
1873
1874 auto generator = RngGenerator<ErlangRandomVariable>();
1875 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1876 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1877 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1878
1879 uint32_t k = 5;
1880 double lambda = 2.0;
1881
1882 // Create the RNG with the specified range.
1884 x->SetAttribute("K", IntegerValue(k));
1885 x->SetAttribute("Lambda", DoubleValue(lambda));
1886
1887 // Calculate the mean of these values.
1888 double valueMean = Average(x);
1889
1890 // The expected value for the mean of the values returned by a
1891 // Erlangly distributed random variable is equal to
1892 //
1893 // E[value] = k * lambda .
1894 //
1895 double expectedMean = k * lambda;
1896
1897 // Test that values have approximately the right mean value.
1898 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1899 expectedMean,
1900 expectedMean * TOLERANCE,
1901 "Wrong mean value.");
1902}
1903
1904/**
1905 * \ingroup rng-tests
1906 * Test case for antithetic Erlang distribution random variable stream generator
1907 */
1909{
1910 public:
1911 // Constructor
1913
1914 // Inherited
1915 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1916
1917 private:
1918 // Inherited
1919 void DoRun() override;
1920
1921 /**
1922 * Tolerance for testing rng values against expectation,
1923 * as a fraction of mean value.
1924 */
1925 static constexpr double TOLERANCE{1e-2};
1926};
1927
1929 : TestCaseBase("Antithetic Erlang Random Variable Stream Generator")
1930{
1931}
1932
1933double
1935{
1936 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1937 auto range = UniformHistogramBins(h, 0, 10, false);
1938
1939 std::vector<double> expected(N_BINS);
1940
1941 // Note that this assumes that n has k equal to one and lambda
1942 // equal to one, which are their default values for this
1943 // distribution.
1944 uint32_t k = 1;
1945 double lambda = 1.0;
1946
1947 // Note that Erlang distribution is equal to the gamma distribution
1948 // when k is an integer, which is why the gamma distribution's cdf
1949 // function can be used here.
1950 for (std::size_t i = 0; i < N_BINS; ++i)
1951 {
1952 expected[i] =
1953 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1954 expected[i] *= N_MEASUREMENTS;
1955 }
1956
1957 double chiSquared = ChiSquared(h, expected, rng);
1958
1959 gsl_histogram_free(h);
1960 return chiSquared;
1961}
1962
1963void
1965{
1966 NS_LOG_FUNCTION(this);
1968
1969 auto generator = RngGenerator<ErlangRandomVariable>(true);
1970 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1971 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1972 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1973
1974 uint32_t k = 5;
1975 double lambda = 2.0;
1976
1977 // Create the RNG with the specified range.
1979
1980 // Make this generate antithetic values.
1981 x->SetAttribute("Antithetic", BooleanValue(true));
1982
1983 x->SetAttribute("K", IntegerValue(k));
1984 x->SetAttribute("Lambda", DoubleValue(lambda));
1985
1986 // Calculate the mean of these values.
1987 double valueMean = Average(x);
1988
1989 // The expected value for the mean of the values returned by a
1990 // Erlangly distributed random variable is equal to
1991 //
1992 // E[value] = k * lambda .
1993 //
1994 double expectedMean = k * lambda;
1995
1996 // Test that values have approximately the right mean value.
1997 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1998 expectedMean,
1999 expectedMean * TOLERANCE,
2000 "Wrong mean value.");
2001}
2002
2003/**
2004 * \ingroup rng-tests
2005 * Test case for Zipf distribution random variable stream generator
2006 */
2008{
2009 public:
2010 // Constructor
2011 ZipfTestCase();
2012
2013 private:
2014 // Inherited
2015 void DoRun() override;
2016
2017 /**
2018 * Tolerance for testing rng values against expectation,
2019 * as a fraction of mean value.
2020 */
2021 static constexpr double TOLERANCE{1e-2};
2022};
2023
2025 : TestCaseBase("Zipf Random Variable Stream Generator")
2026{
2027}
2028
2029void
2031{
2032 NS_LOG_FUNCTION(this);
2034
2035 uint32_t n = 1;
2036 double alpha = 2.0;
2037
2038 // Create the RNG with the specified range.
2040 x->SetAttribute("N", IntegerValue(n));
2041 x->SetAttribute("Alpha", DoubleValue(alpha));
2042
2043 // Calculate the mean of these values.
2044 double valueMean = Average(x);
2045
2046 // The expected value for the mean of the values returned by a
2047 // Zipfly distributed random variable is equal to
2048 //
2049 // H
2050 // N, alpha - 1
2051 // E[value] = ---------------
2052 // H
2053 // N, alpha
2054 //
2055 // where
2056 //
2057 // N
2058 // ---
2059 // \ -alpha
2060 // H = / m .
2061 // N, alpha ---
2062 // m=1
2063 //
2064 // For this test,
2065 //
2066 // -(alpha - 1)
2067 // 1
2068 // E[value] = ---------------
2069 // -alpha
2070 // 1
2071 //
2072 // = 1 .
2073 //
2074 double expectedMean = 1.0;
2075
2076 // Test that values have approximately the right mean value.
2077 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2078 expectedMean,
2079 expectedMean * TOLERANCE,
2080 "Wrong mean value.");
2081}
2082
2083/**
2084 * \ingroup rng-tests
2085 * Test case for antithetic Zipf distribution random variable stream generator
2086 */
2088{
2089 public:
2090 // Constructor
2092
2093 private:
2094 // Inherited
2095 void DoRun() override;
2096
2097 /**
2098 * Tolerance for testing rng values against expectation,
2099 * as a fraction of mean value.
2100 */
2101 static constexpr double TOLERANCE{1e-2};
2102};
2103
2105 : TestCaseBase("Antithetic Zipf Random Variable Stream Generator")
2106{
2107}
2108
2109void
2111{
2112 NS_LOG_FUNCTION(this);
2114
2115 uint32_t n = 1;
2116 double alpha = 2.0;
2117
2118 // Create the RNG with the specified range.
2120 x->SetAttribute("N", IntegerValue(n));
2121 x->SetAttribute("Alpha", DoubleValue(alpha));
2122
2123 // Make this generate antithetic values.
2124 x->SetAttribute("Antithetic", BooleanValue(true));
2125
2126 // Calculate the mean of these values.
2127 double valueMean = Average(x);
2128
2129 // The expected value for the mean of the values returned by a
2130 // Zipfly distributed random variable is equal to
2131 //
2132 // H
2133 // N, alpha - 1
2134 // E[value] = ---------------
2135 // H
2136 // N, alpha
2137 //
2138 // where
2139 //
2140 // N
2141 // ---
2142 // \ -alpha
2143 // H = / m .
2144 // N, alpha ---
2145 // m=1
2146 //
2147 // For this test,
2148 //
2149 // -(alpha - 1)
2150 // 1
2151 // E[value] = ---------------
2152 // -alpha
2153 // 1
2154 //
2155 // = 1 .
2156 //
2157 double expectedMean = 1.0;
2158
2159 // Test that values have approximately the right mean value.
2160 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2161 expectedMean,
2162 expectedMean * TOLERANCE,
2163 "Wrong mean value.");
2164}
2165
2166/**
2167 * \ingroup rng-tests
2168 * Test case for Zeta distribution random variable stream generator
2169 */
2171{
2172 public:
2173 // Constructor
2174 ZetaTestCase();
2175
2176 private:
2177 // Inherited
2178 void DoRun() override;
2179
2180 /**
2181 * Tolerance for testing rng values against expectation,
2182 * as a fraction of mean value.
2183 */
2184 static constexpr double TOLERANCE{1e-2};
2185};
2186
2188 : TestCaseBase("Zeta Random Variable Stream Generator")
2189{
2190}
2191
2192void
2194{
2195 NS_LOG_FUNCTION(this);
2197
2198 double alpha = 5.0;
2199
2200 // Create the RNG with the specified range.
2202 x->SetAttribute("Alpha", DoubleValue(alpha));
2203
2204 // Calculate the mean of these values.
2205 double valueMean = Average(x);
2206
2207 // The expected value for the mean of the values returned by a
2208 // zetaly distributed random variable is equal to
2209 //
2210 // zeta(alpha - 1)
2211 // E[value] = --------------- for alpha > 2 ,
2212 // zeta(alpha)
2213 //
2214 // where zeta(alpha) is the Riemann zeta function.
2215 //
2216 // There are no simple analytic forms for the Riemann zeta function,
2217 // which is why the gsl library is used in this test to calculate
2218 // the known mean of the values.
2219 double expectedMean =
2220 gsl_sf_zeta_int(static_cast<int>(alpha - 1)) / gsl_sf_zeta_int(static_cast<int>(alpha));
2221
2222 // Test that values have approximately the right mean value.
2223 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2224 expectedMean,
2225 expectedMean * TOLERANCE,
2226 "Wrong mean value.");
2227}
2228
2229/**
2230 * \ingroup rng-tests
2231 * Test case for antithetic Zeta distribution random variable stream generator
2232 */
2234{
2235 public:
2236 // Constructor
2238
2239 private:
2240 // Inherited
2241 void DoRun() override;
2242
2243 /**
2244 * Tolerance for testing rng values against expectation,
2245 * as a fraction of mean value.
2246 */
2247 static constexpr double TOLERANCE{1e-2};
2248};
2249
2251 : TestCaseBase("Antithetic Zeta Random Variable Stream Generator")
2252{
2253}
2254
2255void
2257{
2258 NS_LOG_FUNCTION(this);
2260
2261 double alpha = 5.0;
2262
2263 // Create the RNG with the specified range.
2265 x->SetAttribute("Alpha", DoubleValue(alpha));
2266
2267 // Make this generate antithetic values.
2268 x->SetAttribute("Antithetic", BooleanValue(true));
2269
2270 // Calculate the mean of these values.
2271 double valueMean = Average(x);
2272
2273 // The expected value for the mean of the values returned by a
2274 // zetaly distributed random variable is equal to
2275 //
2276 // zeta(alpha - 1)
2277 // E[value] = --------------- for alpha > 2 ,
2278 // zeta(alpha)
2279 //
2280 // where zeta(alpha) is the Riemann zeta function.
2281 //
2282 // There are no simple analytic forms for the Riemann zeta function,
2283 // which is why the gsl library is used in this test to calculate
2284 // the known mean of the values.
2285 double expectedMean =
2286 gsl_sf_zeta_int(static_cast<int>(alpha) - 1) / gsl_sf_zeta_int(static_cast<int>(alpha));
2287
2288 // Test that values have approximately the right mean value.
2289 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2290 expectedMean,
2291 expectedMean * TOLERANCE,
2292 "Wrong mean value.");
2293}
2294
2295/**
2296 * \ingroup rng-tests
2297 * Test case for deterministic random variable stream generator
2298 */
2300{
2301 public:
2302 // Constructor
2304
2305 private:
2306 // Inherited
2307 void DoRun() override;
2308
2309 /** Tolerance for testing rng values against expectation. */
2310 static constexpr double TOLERANCE{1e-8};
2311};
2312
2314 : TestCaseBase("Deterministic Random Variable Stream Generator")
2315{
2316}
2317
2318void
2320{
2321 NS_LOG_FUNCTION(this);
2323
2325
2326 // The following array should give the sequence
2327 //
2328 // 4, 4, 7, 7, 10, 10 .
2329 //
2330 double array1[] = {4, 4, 7, 7, 10, 10};
2331 std::size_t count1 = 6;
2332 s->SetValueArray(array1, count1);
2333
2334 double value;
2335
2336 // Test that the first sequence is correct.
2337 value = s->GetValue();
2338 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2339 value = s->GetValue();
2340 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2341 value = s->GetValue();
2342 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2343 value = s->GetValue();
2344 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2345 value = s->GetValue();
2346 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2347 value = s->GetValue();
2348 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2349
2350 // The following array should give the sequence
2351 //
2352 // 1000, 2000, 7, 7 .
2353 //
2354 double array2[] = {1000, 2000, 3000, 4000};
2355 std::size_t count2 = 4;
2356 s->SetValueArray(array2, count2);
2357
2358 // Test that the second sequence is correct.
2359 value = s->GetValue();
2360 NS_TEST_ASSERT_MSG_EQ_TOL(value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2361 value = s->GetValue();
2362 NS_TEST_ASSERT_MSG_EQ_TOL(value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2363 value = s->GetValue();
2364 NS_TEST_ASSERT_MSG_EQ_TOL(value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2365 value = s->GetValue();
2366 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2367 value = s->GetValue();
2368}
2369
2370/**
2371 * \ingroup rng-tests
2372 * Test case for empirical distribution random variable stream generator
2373 */
2375{
2376 public:
2377 // Constructor
2379
2380 private:
2381 // Inherited
2382 void DoRun() override;
2383
2384 /**
2385 * Tolerance for testing rng values against expectation,
2386 * as a fraction of mean value.
2387 */
2388 static constexpr double TOLERANCE{1e-2};
2389};
2390
2392 : TestCaseBase("Empirical Random Variable Stream Generator")
2393{
2394}
2395
2396void
2398{
2399 NS_LOG_FUNCTION(this);
2401
2402 // Create the RNG with a uniform distribution between 0 and 10.
2404 x->SetInterpolate(false);
2405 x->CDF(0.0, 0.0);
2406 x->CDF(5.0, 0.25);
2407 x->CDF(10.0, 1.0);
2408
2409 // Check that only the correct values are returned
2410 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2411 {
2412 double value = x->GetValue();
2413 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2414 true,
2415 "Incorrect value returned, expected only 5 or 10.");
2416 }
2417
2418 // Calculate the mean of the sampled values.
2419 double valueMean = Average(x);
2420
2421 // The expected distribution with sampled values is
2422 // Value Probability
2423 // 5 25%
2424 // 10 75%
2425 //
2426 // The expected mean is
2427 //
2428 // E[value] = 5 * 25% + 10 * 75% = 8.75
2429 //
2430 // Test that values have approximately the right mean value.
2431 double expectedMean = 8.75;
2432 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2433 expectedMean,
2434 expectedMean * TOLERANCE,
2435 "Wrong mean value.");
2436
2437 // Calculate the mean of the interpolated values.
2438 x->SetInterpolate(true);
2439 valueMean = Average(x);
2440
2441 // The expected distribution (with interpolation) is
2442 // Bin Probability
2443 // [0, 5) 25%
2444 // [5, 10) 75%
2445 //
2446 // Each bin is uniformly sampled, so the average of the samples in the
2447 // bin is the center of the bin.
2448 //
2449 // The expected mean is
2450 //
2451 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2452 //
2453 expectedMean = 6.25;
2454
2455 // Test that values have approximately the right mean value.
2456 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2457 expectedMean,
2458 expectedMean * TOLERANCE,
2459 "Wrong mean value.");
2460
2461 // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2463 y->SetInterpolate(false);
2464 y->CDF(-1.0, 0.0);
2465 y->CDF(0.0, 0.5);
2466 y->CDF(1.0, 1.0);
2467 NS_TEST_ASSERT_MSG_LT(y->GetValue(), 2, "Empirical variable with negative domain");
2468}
2469
2470/**
2471 * \ingroup rng-tests
2472 * Test case for antithetic empirical distribution random variable stream generator
2473 */
2475{
2476 public:
2477 // Constructor
2479
2480 private:
2481 // Inherited
2482 void DoRun() override;
2483
2484 /**
2485 * Tolerance for testing rng values against expectation,
2486 * as a fraction of mean value.
2487 */
2488 static constexpr double TOLERANCE{1e-2};
2489};
2490
2492 : TestCaseBase("EmpiricalAntithetic Random Variable Stream Generator")
2493{
2494}
2495
2496void
2498{
2499 NS_LOG_FUNCTION(this);
2501
2502 // Create the RNG with a uniform distribution between 0 and 10.
2504 x->SetInterpolate(false);
2505 x->CDF(0.0, 0.0);
2506 x->CDF(5.0, 0.25);
2507 x->CDF(10.0, 1.0);
2508
2509 // Make this generate antithetic values.
2510 x->SetAttribute("Antithetic", BooleanValue(true));
2511
2512 // Check that only the correct values are returned
2513 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2514 {
2515 double value = x->GetValue();
2516 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2517 true,
2518 "Incorrect value returned, expected only 5 or 10.");
2519 }
2520
2521 // Calculate the mean of these values.
2522 double valueMean = Average(x);
2523 // Expected
2524 // E[value] = 5 * 25% + 10 * 75% = 8.75
2525 double expectedMean = 8.75;
2526 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2527 expectedMean,
2528 expectedMean * TOLERANCE,
2529 "Wrong mean value.");
2530
2531 // Check interpolated sampling
2532 x->SetInterpolate(true);
2533 valueMean = Average(x);
2534
2535 // The expected value for the mean of the values returned by this
2536 // empirical distribution with interpolation is
2537 //
2538 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2539 //
2540 expectedMean = 6.25;
2541
2542 // Test that values have approximately the right mean value.
2543 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2544 expectedMean,
2545 expectedMean * TOLERANCE,
2546 "Wrong mean value.");
2547}
2548
2549/**
2550 * \ingroup rng-tests
2551 * Test case for caching of Normal RV parameters (see issue #302)
2552 */
2554{
2555 public:
2556 // Constructor
2558
2559 private:
2560 // Inherited
2561 void DoRun() override;
2562};
2563
2565 : TestCaseBase("NormalRandomVariable caching of parameters")
2566{
2567}
2568
2569void
2571{
2572 NS_LOG_FUNCTION(this);
2574
2576 double v1 = n->GetValue(-10, 1, 10); // Mean -10, variance 1, bounded to [-20,0]
2577 double v2 = n->GetValue(10, 1, 10); // Mean 10, variance 1, bounded to [0,20]
2578
2579 NS_TEST_ASSERT_MSG_LT(v1, 0, "Incorrect value returned, expected < 0");
2580 NS_TEST_ASSERT_MSG_GT(v2, 0, "Incorrect value returned, expected > 0");
2581}
2582
2583/**
2584 * \ingroup rng-tests
2585 * Test case for bernoulli distribution random variable stream generator
2586 */
2588{
2589 public:
2590 // Constructor
2592
2593 // Inherited
2594 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2595
2596 private:
2597 // Inherited
2598 void DoRun() override;
2599
2600 /** Tolerance for testing rng values against expectation, in rms. */
2601 static constexpr double TOLERANCE{5};
2602};
2603
2605 : TestCaseBase("Bernoulli Random Variable Stream Generator")
2606{
2607}
2608
2609double
2611{
2612 gsl_histogram* h = gsl_histogram_alloc(2);
2613 auto range = UniformHistogramBins(h, 0, 1);
2614
2615 double p = 0.5;
2616 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2617
2618 double chiSquared = ChiSquared(h, expected, rng);
2619
2620 gsl_histogram_free(h);
2621 return chiSquared;
2622}
2623
2624void
2626{
2627 NS_LOG_FUNCTION(this);
2629
2630 auto generator = RngGenerator<BernoulliRandomVariable>();
2631 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2632 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2633 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2634
2635 double probability = 0.5;
2636
2637 // Create the RNG with the specified range.
2639 x->SetAttribute("Probability", DoubleValue(probability));
2640
2641 // Calculate the mean of these values.
2642 double mean = probability;
2643 double valueMean = Average(x);
2644 double expectedMean = mean;
2645 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2646
2647 // Test that values have approximately the right mean value.
2648 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2649 expectedMean,
2650 expectedRms * TOLERANCE,
2651 "Wrong mean value.");
2652}
2653
2654/**
2655 * \ingroup rng-tests
2656 * Test case for antithetic bernoulli distribution random variable stream generator
2657 */
2659{
2660 public:
2661 // Constructor
2663
2664 // Inherited
2665 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2666
2667 private:
2668 // Inherited
2669 void DoRun() override;
2670
2671 /** Tolerance for testing rng values against expectation, in rms. */
2672 static constexpr double TOLERANCE{5};
2673};
2674
2676 : TestCaseBase("Antithetic Bernoulli Random Variable Stream Generator")
2677{
2678}
2679
2680double
2682{
2683 gsl_histogram* h = gsl_histogram_alloc(2);
2684 auto range = UniformHistogramBins(h, 0, 1);
2685
2686 double p = 0.5;
2687 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2688
2689 double chiSquared = ChiSquared(h, expected, rng);
2690
2691 gsl_histogram_free(h);
2692 return chiSquared;
2693}
2694
2695void
2697{
2698 NS_LOG_FUNCTION(this);
2700
2701 auto generator = RngGenerator<BernoulliRandomVariable>(true);
2702 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2703 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2704 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2705
2706 double probability = 0.5;
2707
2708 // Create the RNG with the specified range.
2710 x->SetAttribute("Probability", DoubleValue(probability));
2711
2712 // Make this generate antithetic values.
2713 x->SetAttribute("Antithetic", BooleanValue(true));
2714
2715 // Calculate the mean of these values.
2716 double mean = probability;
2717 double valueMean = Average(x);
2718 double expectedMean = mean;
2719 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2720
2721 // Test that values have approximately the right mean value.
2722 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2723 expectedMean,
2724 expectedRms * TOLERANCE,
2725 "Wrong mean value.");
2726}
2727
2728/**
2729 * \ingroup rng-tests
2730 * Test case for binomial distribution random variable stream generator
2731 */
2733{
2734 public:
2735 // Constructor
2737
2738 // Inherited
2739 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2740
2741 private:
2742 // Inherited
2743 void DoRun() override;
2744
2745 /** Tolerance for testing rng values against expectation, in rms. */
2746 static constexpr double TOLERANCE{5};
2747};
2748
2750 : TestCaseBase("Binomial Random Variable Stream Generator")
2751{
2752}
2753
2754double
2756{
2757 uint32_t trials = 10;
2758 double probability = 0.5;
2759
2760 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2761 auto range = UniformHistogramBins(h, 0, trials);
2762
2763 std::vector<double> expected(trials + 1);
2764 for (std::size_t i = 0; i < trials + 1; ++i)
2765 {
2766 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2767 }
2768
2769 double chiSquared = ChiSquared(h, expected, rng);
2770
2771 gsl_histogram_free(h);
2772 return chiSquared;
2773}
2774
2775void
2777{
2778 NS_LOG_FUNCTION(this);
2780
2781 uint32_t trials = 10;
2782 double probability = 0.5;
2783
2784 auto generator = RngGenerator<BinomialRandomVariable>();
2785 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2786 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2787 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2788
2789 // Create the RNG with the specified range.
2791 x->SetAttribute("Trials", IntegerValue(trials));
2792 x->SetAttribute("Probability", DoubleValue(probability));
2793
2794 // Calculate the mean of these values.
2795 double mean = trials * probability;
2796 double valueMean = Average(x);
2797 double expectedMean = mean;
2798 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2799
2800 // Test that values have approximately the right mean value.
2801 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2802 expectedMean,
2803 expectedRms * TOLERANCE,
2804 "Wrong mean value.");
2805}
2806
2807/**
2808 * \ingroup rng-tests
2809 * Test case for antithetic binomial distribution random variable stream generator
2810 */
2812{
2813 public:
2814 // Constructor
2816
2817 // Inherited
2818 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2819
2820 private:
2821 // Inherited
2822 void DoRun() override;
2823
2824 /** Tolerance for testing rng values against expectation, in rms. */
2825 static constexpr double TOLERANCE{5};
2826};
2827
2829 : TestCaseBase("Antithetic Binomial Random Variable Stream Generator")
2830{
2831}
2832
2833double
2835{
2836 uint32_t trials = 10;
2837 double probability = 0.5;
2838
2839 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2840 auto range = UniformHistogramBins(h, 0, trials);
2841
2842 std::vector<double> expected(trials + 1);
2843 for (std::size_t i = 0; i < trials + 1; ++i)
2844 {
2845 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2846 }
2847
2848 double chiSquared = ChiSquared(h, expected, rng);
2849
2850 gsl_histogram_free(h);
2851 return chiSquared;
2852}
2853
2854void
2856{
2857 NS_LOG_FUNCTION(this);
2859
2860 uint32_t trials = 10;
2861 double probability = 0.5;
2862
2863 auto generator = RngGenerator<BinomialRandomVariable>(true);
2864 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2865 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2866 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2867
2868 // Create the RNG with the specified range.
2870 x->SetAttribute("Trials", IntegerValue(trials));
2871 x->SetAttribute("Probability", DoubleValue(probability));
2872
2873 // Make this generate antithetic values.
2874 x->SetAttribute("Antithetic", BooleanValue(true));
2875
2876 // Calculate the mean of these values.
2877 double mean = trials * probability;
2878 double valueMean = Average(x);
2879 double expectedMean = mean;
2880 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2881
2882 // Test that values have approximately the right mean value.
2883 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2884 expectedMean,
2885 expectedRms * TOLERANCE,
2886 "Wrong mean value.");
2887}
2888
2889/**
2890 * \ingroup rng-test
2891 * \ingroup tests
2892 *
2893 * \brief Test the Shuffle function
2894 *
2895 * Check that the Shuffle function actually shuffles the elements and does so in a portable way.
2896 */
2898{
2899 public:
2901
2902 private:
2903 void DoRun() override;
2904};
2905
2907 : TestCase("Check correct operation of the Shuffle function")
2908{
2909}
2910
2911void
2913{
2916
2918 rv->SetStream(1);
2919
2920 // test empty vector
2921 std::vector<uint8_t> vec{};
2922
2923 Shuffle(vec.begin(), vec.end(), rv);
2924
2925 NS_TEST_EXPECT_MSG_EQ(vec.empty(), true, "Expected an empty vector");
2926
2927 // test vector with one value
2928 vec.push_back(3);
2929
2930 Shuffle(vec.begin(), vec.end(), rv);
2931
2932 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{3}), true, "Expected vector {3}");
2933
2934 // test vector with two values
2935 vec.push_back(1);
2936
2937 Shuffle(vec.begin(), vec.end(), rv);
2938
2939 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{1, 3}), true, "Expected vector {1, 3}");
2940
2941 // test vector with multiple values
2942 vec.push_back(7);
2943 vec.push_back(2);
2944 vec.push_back(4);
2945 vec.push_back(9);
2946
2947 Shuffle(vec.begin(), vec.end(), rv);
2948
2949 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{4, 1, 9, 3, 2, 7}),
2950 true,
2951 "Expected vector {4, 1, 9, 3, 2, 7}");
2952}
2953
2954/**
2955 * \ingroup rng-tests
2956 * Test case for laplacian distribution random variable stream generator
2957 */
2959{
2960 public:
2962
2963 private:
2964 void DoRun() override;
2965
2966 /**
2967 * Tolerance for testing rng values against expectation,
2968 * as a fraction of mean value.
2969 */
2970 static constexpr double TOLERANCE{1e-2};
2971};
2972
2974 : TestCaseBase("Laplacian Random Variable Stream Generator")
2975{
2976}
2977
2978void
2980{
2981 NS_LOG_FUNCTION(this);
2983
2984 double mu = -5.0;
2985 double scale = 4.0;
2986 double bound = 20.0;
2987
2988 // Create unbounded RNG with the specified range.
2990 x1->SetAttribute("Location", DoubleValue(mu));
2991 x1->SetAttribute("Scale", DoubleValue(scale));
2992
2993 // Calculate the mean of these values.
2994 auto valueMean = Average(x1);
2995
2996 // Calculate the variance of these values.
2997 auto valueVariance = Variance(x1, valueMean);
2998
2999 // Test that values have approximately the right mean value.
3000 const auto expectedMean = mu;
3001 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3002
3003 // Test that values have approximately the right variance value.
3004 const auto expectedVariance = LaplacianRandomVariable::GetVariance(scale);
3005 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3006 expectedVariance,
3007 TOLERANCE * expectedVariance,
3008 "Wrong variance value.");
3009
3010 // Create bounded RNG with the specified range.
3012 x2->SetAttribute("Location", DoubleValue(mu));
3013 x2->SetAttribute("Scale", DoubleValue(scale));
3014 x2->SetAttribute("Bound", DoubleValue(bound));
3015
3016 // Calculate the mean of these values.
3017 valueMean = Average(x2);
3018
3019 // Test that values have approximately the right mean value.
3020 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3021
3022 // Check that only the correct values are returned
3023 const auto lowerBound = mu - bound;
3024 const auto upperBound = mu + bound;
3025 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
3026 {
3027 const auto value = x2->GetValue();
3028 NS_TEST_EXPECT_MSG_EQ((value >= lowerBound) || (value <= upperBound),
3029 true,
3030 "Value not in expected boundaries.");
3031 }
3032}
3033
3034/**
3035 * \ingroup rng-tests
3036 * Test case for largest extreme value distribution random variable stream generator
3037 */
3039{
3040 public:
3042
3043 private:
3044 void DoRun() override;
3045
3046 /**
3047 * Tolerance for testing rng values against expectation,
3048 * as a fraction of mean value.
3049 */
3050 static constexpr double TOLERANCE{1e-2};
3051};
3052
3054 : TestCaseBase("Largest Extreme Value Random Variable Stream Generator")
3055{
3056}
3057
3058void
3060{
3061 NS_LOG_FUNCTION(this);
3063
3064 double mu = 2.0;
3065 double scale = 1.0;
3066
3067 // Create RNG with the specified range.
3069 x->SetAttribute("Location", DoubleValue(mu));
3070 x->SetAttribute("Scale", DoubleValue(scale));
3071
3072 // Calculate the mean of these values.
3073 auto valueMean = Average(x);
3074
3075 // Calculate the variance of these values.
3076 auto valueVariance = Variance(x, valueMean);
3077
3078 // Test that values have approximately the right mean value.
3079 const auto expectedMean = LargestExtremeValueRandomVariable::GetMean(mu, scale);
3080 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3081
3082 // Test that values have approximately the right variance value.
3083 const auto expectedVariance = LargestExtremeValueRandomVariable::GetVariance(scale);
3084 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3085 expectedVariance,
3086 TOLERANCE * expectedVariance,
3087 "Wrong variance value.");
3088}
3089
3090/**
3091 * \ingroup rng-tests
3092 * RandomVariableStream test suite, covering all random number variable
3093 * stream generator types.
3094 */
3096{
3097 public:
3098 // Constructor
3100};
3101
3103 : TestSuite("random-variable-stream-generators", Type::UNIT)
3104{
3118 /// \todo This test is currently disabled because it fails sometimes.
3119 /// A possible reason for the failure is that the antithetic code is
3120 /// not implemented properly for this log-normal case.
3121 /*
3122 AddTestCase (new LogNormalAntitheticTestCase);
3123 */
3125 /// \todo This test is currently disabled because it fails sometimes.
3126 /// A possible reason for the failure is that the antithetic code is
3127 /// not implemented properly for this gamma case.
3128 /*
3129 AddTestCase (new GammaAntitheticTestCase);
3130 */
3140 /// Issue #302: NormalRandomVariable produces stale values
3149}
3150
3151static RandomVariableSuite randomVariableSuite; //!< Static variable for test initialization
3152
3153} // namespace RandomVariable
3154
3155} // namespace test
3156
3157} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Hold a signed integer type.
Definition integer.h:34
double GetVariance() const
Returns the variance value for the laplacian distribution returned by this RNG stream.
double GetMean() const
Returns the mean value for the Largest Extreme Value distribution returned by this RNG stream.
double GetVariance() const
Returns the variance value for the Largest Extreme Value distribution returned by this RNG stream.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static uint64_t GetRun()
Get the current run number.
static uint32_t GetSeed()
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Test case for antithetic bernoulli distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for bernoulli distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
void DoRun() override
Implementation to actually run this TestCase.
Test case for antithetic binomial distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
Test case for binomial distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for constant random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation.
void DoRun() override
Implementation to actually run this TestCase.
Test case for deterministic random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation.
Test case for antithetic empirical distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for empirical distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for antithetic Erlang distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for Erlang distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for antithetic exponential distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for exponential distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for antithetic gamma distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for gamma distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for laplacian distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for largest extreme value distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for antithetic log-normal distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for log-normal distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for antithetic normal distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for caching of Normal RV parameters (see issue #302)
void DoRun() override
Implementation to actually run this TestCase.
Test case for normal distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, in rms.
Test case for antithetic Pareto distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for Pareto distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
RandomVariableStream test suite, covering all random number variable stream generator types.
Test case for sequential random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation.
void DoRun() override
Implementation to actually run this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
A factory base class to create new instances of a random variable.
virtual Ptr< RandomVariableStream > Create() const =0
Create a new instance of a random variable stream.
Factory class to create new instances of a particular random variable stream.
Ptr< RandomVariableStream > Create() const override
Create a new instance of a random variable stream.
bool m_anti
Whether to create antithetic random variable streams.
Base class for RandomVariableStream test suites.
double ChiSquared(gsl_histogram *h, const std::vector< double > &expected, Ptr< RandomVariableStream > rng) const
Compute the chi squared value of a sampled distribution compared to the expected distribution.
static const uint32_t N_MEASUREMENTS
Number of samples to draw when populating the distributions.
void SetTestSuiteSeed()
Set the seed used for this test suite.
double ChiSquaredsAverage(const RngGeneratorBase *generator, std::size_t nRuns) const
Average the chi squared value over some number of runs, each run with a new instance of the random nu...
std::vector< double > UniformHistogramBins(gsl_histogram *h, double start, double end, bool underflow=true, bool overflow=true) const
Configure a GSL histogram with uniform bins, with optional under/over-flow bins.
virtual double ChiSquaredTest(Ptr< RandomVariableStream > rng) const
Compute the chi square value from a random variable.
static const uint32_t N_BINS
Number of bins for sampling the distributions.
double Variance(Ptr< RandomVariableStream > rng, double average) const
Compute the variance of a random variable.
bool m_seedSet
true if we've already set the seed the correctly.
static const uint32_t N_RUNS
Number of retry attempts to pass a chi-square test.
double Average(Ptr< RandomVariableStream > rng) const
Compute the average of a random variable.
Test case for antithetic uniform distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for uniform distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
Test case for antithetic Weibull distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for Weibull distribution random variable stream generator.
double ChiSquaredTest(Ptr< RandomVariableStream > rng) const override
Compute the chi square value from a random variable.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
Test case for antithetic Zeta distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for Zeta distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for antithetic Zipf distribution random variable stream generator.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
Test case for Zipf distribution random variable stream generator.
static constexpr double TOLERANCE
Tolerance for testing rng values against expectation, as a fraction of mean value.
void DoRun() override
Implementation to actually run this TestCase.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
Definition test.h:699
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:554
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition test.h:864
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition test.h:327
static RandomVariableSuite randomVariableSuite
Static variable for test initialization.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void Shuffle(RND_ACCESS_ITER first, RND_ACCESS_ITER last, Ptr< UniformRandomVariable > rv)
Shuffle the elements in the range first to last.
Definition shuffle.h:48
-ns3 Test suite for the ns3 wrapper script