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 // end of class TestCaseBase
356};
357
358/**
359 * @ingroup rng-tests
360 * Test case for uniform distribution random variable stream generator.
361 */
363{
364 public:
365 // Constructor
367
368 // Inherited
369 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
370
371 private:
372 // Inherited
373 void DoRun() override;
374};
375
377 : TestCaseBase("Uniform Random Variable Stream Generator")
378{
379}
380
381double
383{
384 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
385
386 // Note that this assumes that the range for u is [0,1], which is
387 // the default range for this distribution.
388 gsl_histogram_set_ranges_uniform(h, 0., 1.);
389
390 std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
391
392 double chiSquared = ChiSquared(h, expected, rng);
393 gsl_histogram_free(h);
394 return chiSquared;
395}
396
397void
399{
400 NS_LOG_FUNCTION(this);
402
403 double confidence = 0.99;
404 double maxStatistic = gsl_cdf_chisq_Pinv(confidence, (N_BINS - 1));
405 NS_LOG_DEBUG("Chi square required at " << confidence << " confidence for " << N_BINS
406 << " bins is " << maxStatistic);
407
408 double result = maxStatistic;
409 // If chi-squared test fails, re-try it up to N_RUNS times
410 for (uint32_t i = 0; i < N_RUNS; ++i)
411 {
413 result = ChiSquaredTest(rng);
414 NS_LOG_DEBUG("Chi square result is " << result);
415 if (result < maxStatistic)
416 {
417 break;
418 }
419 }
420
421 NS_TEST_ASSERT_MSG_LT(result, maxStatistic, "Chi-squared statistic out of range");
422
423 double min = 0.0;
424 double max = 10.0;
425 double value;
426
427 // Create the RNG with the specified range.
429
430 x->SetAttribute("Min", DoubleValue(min));
431 x->SetAttribute("Max", DoubleValue(max));
432
433 // Test that values are always within the range:
434 //
435 // [min, max)
436 //
437 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
438 {
439 value = x->GetValue();
440 NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
441 NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
442 }
443
444 // Boundary checking on GetInteger; should be [min,max]; from bug 1964
445 static const uint32_t UNIFORM_INTEGER_MIN{0};
446 static const uint32_t UNIFORM_INTEGER_MAX{4294967295U};
447 // [0,0] should return 0
448 uint32_t intValue;
449 intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN);
450 NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MIN, "Uniform RV GetInteger boundary testing");
451 // [UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX] should return UNIFORM_INTEGER_MAX
452 intValue = x->GetInteger(UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX);
453 NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MAX, "Uniform RV GetInteger boundary testing");
454 // [0,1] should return mix of 0 or 1
455 intValue = 0;
456 for (int i = 0; i < 20; i++)
457 {
458 intValue += x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN + 1);
459 }
460 NS_TEST_ASSERT_MSG_GT(intValue, 0, "Uniform RV GetInteger boundary testing");
461 NS_TEST_ASSERT_MSG_LT(intValue, 20, "Uniform RV GetInteger boundary testing");
462 // [MAX-1,MAX] should return mix of MAX-1 or MAX
463 uint32_t count = 0;
464 for (int i = 0; i < 20; i++)
465 {
466 intValue = x->GetInteger(UNIFORM_INTEGER_MAX - 1, UNIFORM_INTEGER_MAX);
467 if (intValue == UNIFORM_INTEGER_MAX)
468 {
469 count++;
470 }
471 }
472 NS_TEST_ASSERT_MSG_GT(count, 0, "Uniform RV GetInteger boundary testing");
473 NS_TEST_ASSERT_MSG_LT(count, 20, "Uniform RV GetInteger boundary testing");
474 // multiple [0,UNIFORM_INTEGER_MAX] should return non-zero
475 intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
476 uint32_t intValue2 = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
477 NS_TEST_ASSERT_MSG_GT(intValue + intValue2, 0, "Uniform RV GetInteger boundary testing");
478}
479
480/**
481 * @ingroup rng-tests
482 * Test case for antithetic uniform distribution random variable stream generator
483 */
485{
486 public:
487 // Constructor
489
490 // Inherited
491 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
492
493 private:
494 // Inherited
495 void DoRun() override;
496};
497
499 : TestCaseBase("Antithetic Uniform Random Variable Stream Generator")
500{
501}
502
503double
505{
506 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
507
508 // Note that this assumes that the range for u is [0,1], which is
509 // the default range for this distribution.
510 gsl_histogram_set_ranges_uniform(h, 0., 1.);
511
512 std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
513
514 double chiSquared = ChiSquared(h, expected, rng);
515 gsl_histogram_free(h);
516 return chiSquared;
517}
518
519void
521{
522 NS_LOG_FUNCTION(this);
524
525 auto generator = RngGenerator<UniformRandomVariable>(true);
526 double sum = ChiSquaredsAverage(&generator, N_RUNS);
527 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
528 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
529
530 double min = 0.0;
531 double max = 10.0;
532 double value;
533
534 // Create the RNG with the specified range.
536
537 // Make this generate antithetic values.
538 x->SetAttribute("Antithetic", BooleanValue(true));
539
540 x->SetAttribute("Min", DoubleValue(min));
541 x->SetAttribute("Max", DoubleValue(max));
542
543 // Test that values are always within the range:
544 //
545 // [min, max)
546 //
547 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
548 {
549 value = x->GetValue();
550 NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
551 NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
552 }
553}
554
555/**
556 * @ingroup rng-tests
557 * Test case for constant random variable stream generator
558 */
560{
561 public:
562 // Constructor
564
565 private:
566 // Inherited
567 void DoRun() override;
568
569 /** Tolerance for testing rng values against expectation. */
570 static constexpr double TOLERANCE{1e-8};
571};
572
574 : TestCaseBase("Constant Random Variable Stream Generator")
575{
576}
577
578void
580{
581 NS_LOG_FUNCTION(this);
583
585
586 double constant;
587
588 // Test that the constant value can be changed using its attribute.
589 constant = 10.0;
590 c->SetAttribute("Constant", DoubleValue(constant));
591 NS_TEST_ASSERT_MSG_EQ_TOL(c->GetValue(), constant, TOLERANCE, "Constant value changed");
592 c->SetAttribute("Constant", DoubleValue(20.0));
593 NS_TEST_ASSERT_MSG_NE(c->GetValue(), constant, "Constant value not changed");
594
595 // Test that the constant value does not change.
596 constant = c->GetValue();
597 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
598 {
599 NS_TEST_ASSERT_MSG_EQ_TOL(c->GetValue(),
600 constant,
601 TOLERANCE,
602 "Constant value changed in loop");
603 }
604}
605
606/**
607 * @ingroup rng-tests
608 * Test case for sequential random variable stream generator
609 */
611{
612 public:
613 // Constructor
615
616 private:
617 // Inherited
618 void DoRun() override;
619
620 /** Tolerance for testing rng values against expectation. */
621 static constexpr double TOLERANCE{1e-8};
622};
623
625 : TestCaseBase("Sequential Random Variable Stream Generator")
626{
627}
628
629void
631{
632 NS_LOG_FUNCTION(this);
634
636
637 // The following four attributes should give the sequence
638 //
639 // 4, 4, 7, 7, 10, 10
640 //
641 s->SetAttribute("Min", DoubleValue(4));
642 s->SetAttribute("Max", DoubleValue(11));
643 s->SetAttribute("Increment", StringValue("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
644 s->SetAttribute("Consecutive", IntegerValue(2));
645
646 double value;
647
648 // Test that the sequencet is correct.
649 value = s->GetValue();
650 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 1 wrong.");
651 value = s->GetValue();
652 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 2 wrong.");
653 value = s->GetValue();
654 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 3 wrong.");
655 value = s->GetValue();
656 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 4 wrong.");
657 value = s->GetValue();
658 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 5 wrong.");
659 value = s->GetValue();
660 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 6 wrong.");
661}
662
663/**
664 * @ingroup rng-tests
665 * Test case for normal distribution random variable stream generator
666 */
668{
669 public:
670 // Constructor
672
673 // Inherited
674 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
675
676 private:
677 // Inherited
678 void DoRun() override;
679
680 /** Tolerance for testing rng values against expectation, in rms. */
681 static constexpr double TOLERANCE{5};
682};
683
685 : TestCaseBase("Normal Random Variable Stream Generator")
686{
687}
688
689double
691{
692 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
693 auto range = UniformHistogramBins(h, -4., 4.);
694
695 std::vector<double> expected(N_BINS);
696
697 // Note that this assumes that n has mean equal to zero and standard
698 // deviation equal to one, which are their default values for this
699 // distribution.
700 double sigma = 1.;
701
702 for (std::size_t i = 0; i < N_BINS; ++i)
703 {
704 expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
705 expected[i] *= N_MEASUREMENTS;
706 }
707
708 double chiSquared = ChiSquared(h, expected, rng);
709 gsl_histogram_free(h);
710 return chiSquared;
711}
712
713void
715{
716 NS_LOG_FUNCTION(this);
718
719 auto generator = RngGenerator<NormalRandomVariable>();
720 auto rng = generator.Create();
721
722 double sum = ChiSquaredsAverage(&generator, N_RUNS);
723 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
724 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
725
726 double mean = 5.0;
727 double variance = 2.0;
728
729 // Create the RNG with the specified range.
731 x->SetAttribute("Mean", DoubleValue(mean));
732 x->SetAttribute("Variance", DoubleValue(variance));
733
734 // Calculate the mean of these values.
735 double valueMean = Average(x);
736
737 // The expected value for the mean of the values returned by a
738 // normally distributed random variable is equal to mean.
739 double expectedMean = mean;
740 double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
741
742 // Test that values have approximately the right mean value.
744 expectedMean,
745 expectedRms * TOLERANCE,
746 "Wrong mean value.");
747}
748
749/**
750 * @ingroup rng-tests
751 * Test case for antithetic normal distribution random variable stream generator
752 */
754{
755 public:
756 // Constructor
758
759 // Inherited
760 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
761
762 private:
763 // Inherited
764 void DoRun() override;
765
766 /** Tolerance for testing rng values against expectation, in rms. */
767 static constexpr double TOLERANCE{5};
768};
769
771 : TestCaseBase("Antithetic Normal Random Variable Stream Generator")
772{
773}
774
775double
777{
778 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
779 auto range = UniformHistogramBins(h, -4, 4);
780
781 std::vector<double> expected(N_BINS);
782
783 // Note that this assumes that n has mean equal to zero and standard
784 // deviation equal to one, which are their default values for this
785 // distribution.
786 double sigma = 1.;
787
788 for (std::size_t i = 0; i < N_BINS; ++i)
789 {
790 expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
791 expected[i] *= N_MEASUREMENTS;
792 }
793
794 double chiSquared = ChiSquared(h, expected, rng);
795
796 gsl_histogram_free(h);
797 return chiSquared;
798}
799
800void
802{
803 NS_LOG_FUNCTION(this);
805
806 auto generator = RngGenerator<NormalRandomVariable>(true);
807 double sum = ChiSquaredsAverage(&generator, N_RUNS);
808 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
809 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
810
811 double mean = 5.0;
812 double variance = 2.0;
813
814 // Create the RNG with the specified range.
816 x->SetAttribute("Mean", DoubleValue(mean));
817 x->SetAttribute("Variance", DoubleValue(variance));
818
819 // Make this generate antithetic values.
820 x->SetAttribute("Antithetic", BooleanValue(true));
821
822 // Calculate the mean of these values.
823 double valueMean = Average(x);
824
825 // The expected value for the mean of the values returned by a
826 // normally distributed random variable is equal to mean.
827 double expectedMean = mean;
828 double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
829
830 // Test that values have approximately the right mean value.
832 expectedMean,
833 expectedRms * TOLERANCE,
834 "Wrong mean value.");
835}
836
837/**
838 * @ingroup rng-tests
839 * Test case for exponential distribution random variable stream generator
840 */
842{
843 public:
844 // Constructor
846
847 // Inherited
848 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
849
850 private:
851 // Inherited
852 void DoRun() override;
853
854 /** Tolerance for testing rng values against expectation, in rms. */
855 static constexpr double TOLERANCE{5};
856};
857
859 : TestCaseBase("Exponential Random Variable Stream Generator")
860{
861}
862
863double
865{
866 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
867 auto range = UniformHistogramBins(h, 0, 10, false);
868
869 std::vector<double> expected(N_BINS);
870
871 // Note that this assumes that e has mean equal to one, which is the
872 // default value for this distribution.
873 double mu = 1.;
874
875 for (std::size_t i = 0; i < N_BINS; ++i)
876 {
877 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
878 expected[i] *= N_MEASUREMENTS;
879 }
880
881 double chiSquared = ChiSquared(h, expected, rng);
882
883 gsl_histogram_free(h);
884 return chiSquared;
885}
886
887void
889{
890 NS_LOG_FUNCTION(this);
892
894 double sum = ChiSquaredsAverage(&generator, N_RUNS);
895 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
896 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
897
898 double mean = 3.14;
899 double bound = 0.0;
900
901 // Create the RNG with the specified range.
903 x->SetAttribute("Mean", DoubleValue(mean));
904 x->SetAttribute("Bound", DoubleValue(bound));
905
906 // Calculate the mean of these values.
907 double valueMean = Average(x);
908 double expectedMean = mean;
909 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
910
911 // Test that values have approximately the right mean value.
913 expectedMean,
914 expectedRms * TOLERANCE,
915 "Wrong mean value.");
916}
917
918/**
919 * @ingroup rng-tests
920 * Test case for antithetic exponential distribution random variable stream generator
921 */
923{
924 public:
925 // Constructor
927
928 // Inherited
929 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
930
931 private:
932 // Inherited
933 void DoRun() override;
934
935 /** Tolerance for testing rng values against expectation, in rms. */
936 static constexpr double TOLERANCE{5};
937};
938
940 : TestCaseBase("Antithetic Exponential Random Variable Stream Generator")
941{
942}
943
944double
946{
947 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
948 auto range = UniformHistogramBins(h, 0, 10, false);
949
950 std::vector<double> expected(N_BINS);
951
952 // Note that this assumes that e has mean equal to one, which is the
953 // default value for this distribution.
954 double mu = 1.;
955
956 for (std::size_t i = 0; i < N_BINS; ++i)
957 {
958 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
959 expected[i] *= N_MEASUREMENTS;
960 }
961
962 double chiSquared = ChiSquared(h, expected, rng);
963
964 gsl_histogram_free(h);
965 return chiSquared;
966}
967
968void
970{
971 NS_LOG_FUNCTION(this);
973
974 auto generator = RngGenerator<ExponentialRandomVariable>(true);
975 double sum = ChiSquaredsAverage(&generator, N_RUNS);
976 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
977 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
978
979 double mean = 3.14;
980 double bound = 0.0;
981
982 // Create the RNG with the specified range.
984 x->SetAttribute("Mean", DoubleValue(mean));
985 x->SetAttribute("Bound", DoubleValue(bound));
986
987 // Make this generate antithetic values.
988 x->SetAttribute("Antithetic", BooleanValue(true));
989
990 // Calculate the mean of these values.
991 double valueMean = Average(x);
992 double expectedMean = mean;
993 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
994
995 // Test that values have approximately the right mean value.
997 expectedMean,
998 expectedRms * TOLERANCE,
999 "Wrong mean value.");
1000}
1001
1002/**
1003 * @ingroup rng-tests
1004 * Test case for Pareto distribution random variable stream generator
1005 */
1007{
1008 public:
1009 // Constructor
1011
1012 // Inherited
1013 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1014
1015 private:
1016 // Inherited
1017 void DoRun() override;
1018
1019 /**
1020 * Tolerance for testing rng values against expectation,
1021 * as a fraction of mean value.
1022 */
1023 static constexpr double TOLERANCE{1e-2};
1024};
1025
1027 : TestCaseBase("Pareto Random Variable Stream Generator")
1028{
1029}
1030
1031double
1033{
1034 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1035 auto range = UniformHistogramBins(h, 1, 10, false);
1036
1037 std::vector<double> expected(N_BINS);
1038
1039 double shape = 2.0;
1040 double scale = 1.0;
1041
1042 for (std::size_t i = 0; i < N_BINS; ++i)
1043 {
1044 expected[i] =
1045 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1046 expected[i] *= N_MEASUREMENTS;
1047 }
1048
1049 double chiSquared = ChiSquared(h, expected, rng);
1050
1051 gsl_histogram_free(h);
1052 return chiSquared;
1053}
1054
1055void
1057{
1058 NS_LOG_FUNCTION(this);
1060
1061 auto generator = RngGenerator<ParetoRandomVariable>();
1062 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1063 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1064 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1065
1066 double shape = 2.0;
1067 double scale = 1.0;
1068
1069 // Create the RNG with the specified range.
1071 x->SetAttribute("Shape", DoubleValue(shape));
1072 x->SetAttribute("Scale", DoubleValue(scale));
1073
1074 // Calculate the mean of these values.
1075 double valueMean = Average(x);
1076
1077 // The expected value for the mean is given by
1078 //
1079 // shape * scale
1080 // E[value] = --------------- ,
1081 // shape - 1
1082 //
1083 // where
1084 //
1085 // scale = mean * (shape - 1.0) / shape .
1086 double expectedMean = (shape * scale) / (shape - 1.0);
1087
1088 // Test that values have approximately the right mean value.
1089 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1090 expectedMean,
1091 expectedMean * TOLERANCE,
1092 "Wrong mean value.");
1093}
1094
1095/**
1096 * @ingroup rng-tests
1097 * Test case for antithetic Pareto distribution random variable stream generator
1098 */
1100{
1101 public:
1102 // Constructor
1104
1105 // Inherited
1106 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1107
1108 private:
1109 // Inherited
1110 void DoRun() override;
1111
1112 /**
1113 * Tolerance for testing rng values against expectation,
1114 * as a fraction of mean value.
1115 */
1116 static constexpr double TOLERANCE{1e-2};
1117};
1118
1120 : TestCaseBase("Antithetic Pareto Random Variable Stream Generator")
1121{
1122}
1123
1124double
1126{
1127 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1128 auto range = UniformHistogramBins(h, 1, 10, false);
1129
1130 std::vector<double> expected(N_BINS);
1131
1132 double shape = 2.0;
1133 double scale = 1.0;
1134
1135 for (std::size_t i = 0; i < N_BINS; ++i)
1136 {
1137 expected[i] =
1138 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1139 expected[i] *= N_MEASUREMENTS;
1140 }
1141
1142 double chiSquared = ChiSquared(h, expected, rng);
1143
1144 gsl_histogram_free(h);
1145 return chiSquared;
1146}
1147
1148void
1150{
1151 NS_LOG_FUNCTION(this);
1153
1154 auto generator = RngGenerator<ParetoRandomVariable>(true);
1155 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1156 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1157 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1158
1159 double shape = 2.0;
1160 double scale = 1.0;
1161
1162 // Create the RNG with the specified range.
1164 x->SetAttribute("Shape", DoubleValue(shape));
1165 x->SetAttribute("Scale", DoubleValue(scale));
1166
1167 // Make this generate antithetic values.
1168 x->SetAttribute("Antithetic", BooleanValue(true));
1169
1170 // Calculate the mean of these values.
1171 double valueMean = Average(x);
1172
1173 // The expected value for the mean is given by
1174 //
1175 // shape * scale
1176 // E[value] = --------------- ,
1177 // shape - 1
1178 //
1179 // where
1180 //
1181 // scale = mean * (shape - 1.0) / shape .
1182 //
1183 double expectedMean = (shape * scale) / (shape - 1.0);
1184
1185 // Test that values have approximately the right mean value.
1186 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1187 expectedMean,
1188 expectedMean * TOLERANCE,
1189 "Wrong mean value.");
1190}
1191
1192/**
1193 * @ingroup rng-tests
1194 * Test case for Weibull distribution random variable stream generator
1195 */
1197{
1198 public:
1199 // Constructor
1201
1202 // Inherited
1203 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1204
1205 private:
1206 // Inherited
1207 void DoRun() override;
1208
1209 /**
1210 * Tolerance for testing rng values against expectation,
1211 * as a fraction of mean value.
1212 */
1213 static constexpr double TOLERANCE{1e-2};
1214};
1215
1217 : TestCaseBase("Weibull Random Variable Stream Generator")
1218{
1219}
1220
1221double
1223{
1224 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1225 auto range = UniformHistogramBins(h, 1, 10, false);
1226
1227 std::vector<double> expected(N_BINS);
1228
1229 // Note that this assumes that p has shape equal to one and scale
1230 // equal to one, which are their default values for this
1231 // distribution.
1232 double a = 1.0;
1233 double b = 1.0;
1234
1235 for (std::size_t i = 0; i < N_BINS; ++i)
1236 {
1237 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1238 expected[i] *= N_MEASUREMENTS;
1239 NS_LOG_INFO("weibull: " << expected[i]);
1240 }
1241
1242 double chiSquared = ChiSquared(h, expected, rng);
1243
1244 gsl_histogram_free(h);
1245 return chiSquared;
1246}
1247
1248void
1250{
1251 NS_LOG_FUNCTION(this);
1253
1254 auto generator = RngGenerator<WeibullRandomVariable>();
1255 const auto sum = ChiSquaredsAverage(&generator, N_RUNS);
1256 const auto maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1257 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1258
1259 const auto scale = 5.0;
1260 const auto shape = 1.0;
1261
1262 // Create the RNG with the specified range.
1264 x->SetAttribute("Scale", DoubleValue(scale));
1265 x->SetAttribute("Shape", DoubleValue(shape));
1266
1267 // Calculate the mean of these values.
1268 const auto measuredMean = Average(x);
1269
1270 // The expected value for the mean of the values returned by a
1271 // Weibull distributed random variable is
1272 //
1273 // E[value] = scale * Gamma(1 + 1 / shape) ,
1274 //
1275 // where Gamma() is the Gamma function. Note that
1276 //
1277 // Gamma(n) = (n - 1)!
1278 //
1279 // if n is a positive integer.
1280 //
1281 // For this test,
1282 //
1283 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1284 // = Gamma(2)
1285 // = (2 - 1)!
1286 // = 1
1287 //
1288 // which means
1289 //
1290 // E[value] = scale .
1291 //
1292 const auto expectedMean = scale;
1293
1294 // Test calculated and expected mean values are identical.
1295 const auto valueMean = x->GetMean();
1296 NS_TEST_ASSERT_MSG_EQ(valueMean, expectedMean, "Wrong calculated mean value.");
1297
1298 // Test that values have approximately the right mean value.
1299 NS_TEST_ASSERT_MSG_EQ_TOL(measuredMean,
1300 expectedMean,
1301 expectedMean * TOLERANCE,
1302 "Wrong measured mean value.");
1303}
1304
1305/**
1306 * @ingroup rng-tests
1307 * Test case for antithetic Weibull distribution random variable stream generator
1308 */
1310{
1311 public:
1312 // Constructor
1314
1315 // Inherited
1316 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1317
1318 private:
1319 // Inherited
1320 void DoRun() override;
1321
1322 /**
1323 * Tolerance for testing rng values against expectation,
1324 * as a fraction of mean value.
1325 */
1326 static constexpr double TOLERANCE{1e-2};
1327};
1328
1330 : TestCaseBase("Antithetic Weibull Random Variable Stream Generator")
1331{
1332}
1333
1334double
1336{
1337 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1338 auto range = UniformHistogramBins(h, 1, 10, false);
1339
1340 std::vector<double> expected(N_BINS);
1341
1342 // Note that this assumes that p has shape equal to one and scale
1343 // equal to one, which are their default values for this
1344 // distribution.
1345 double a = 1.0;
1346 double b = 1.0;
1347
1348 for (std::size_t i = 0; i < N_BINS; ++i)
1349 {
1350 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1351 expected[i] *= N_MEASUREMENTS;
1352 }
1353
1354 double chiSquared = ChiSquared(h, expected, rng);
1355
1356 gsl_histogram_free(h);
1357 return chiSquared;
1358}
1359
1360void
1362{
1363 NS_LOG_FUNCTION(this);
1365
1366 auto generator = RngGenerator<WeibullRandomVariable>(true);
1367 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1368 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1369 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1370
1371 double scale = 5.0;
1372 double shape = 1.0;
1373
1374 // Create the RNG with the specified range.
1376 x->SetAttribute("Scale", DoubleValue(scale));
1377 x->SetAttribute("Shape", DoubleValue(shape));
1378
1379 // Make this generate antithetic values.
1380 x->SetAttribute("Antithetic", BooleanValue(true));
1381
1382 // Calculate the mean of these values.
1383 double valueMean = Average(x);
1384
1385 // The expected value for the mean of the values returned by a
1386 // Weibull distributed random variable is
1387 //
1388 // E[value] = scale * Gamma(1 + 1 / shape) ,
1389 //
1390 // where Gamma() is the Gamma function. Note that
1391 //
1392 // Gamma(n) = (n - 1)!
1393 //
1394 // if n is a positive integer.
1395 //
1396 // For this test,
1397 //
1398 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1399 // = Gamma(2)
1400 // = (2 - 1)!
1401 // = 1
1402 //
1403 // which means
1404 //
1405 // E[value] = scale .
1406 //
1407 double expectedMean = scale;
1408
1409 // Test that values have approximately the right mean value.
1410 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1411 expectedMean,
1412 expectedMean * TOLERANCE,
1413 "Wrong mean value.");
1414}
1415
1416/**
1417 * @ingroup rng-tests
1418 * Test case for log-normal distribution random variable stream generator
1419 */
1421{
1422 public:
1423 // Constructor
1425
1426 // Inherited
1427 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1428
1429 private:
1430 // Inherited
1431 void DoRun() override;
1432
1433 /**
1434 * Tolerance for testing rng values against expectation,
1435 * as a fraction of mean value.
1436 */
1437 static constexpr double TOLERANCE{3e-2};
1438};
1439
1441 : TestCaseBase("Log-Normal Random Variable Stream Generator")
1442{
1443}
1444
1445double
1447{
1448 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1449 auto range = UniformHistogramBins(h, 0, 10, false);
1450
1451 std::vector<double> expected(N_BINS);
1452
1453 // Note that this assumes that n has mu equal to zero and sigma
1454 // equal to one, which are their default values for this
1455 // distribution.
1456 double mu = 0.0;
1457 double sigma = 1.0;
1458
1459 for (std::size_t i = 0; i < N_BINS; ++i)
1460 {
1461 expected[i] =
1462 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1463 expected[i] *= N_MEASUREMENTS;
1464 }
1465
1466 double chiSquared = ChiSquared(h, expected, rng);
1467
1468 gsl_histogram_free(h);
1469 return chiSquared;
1470}
1471
1472void
1474{
1475 NS_LOG_FUNCTION(this);
1477
1478 auto generator = RngGenerator<LogNormalRandomVariable>();
1479 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1480 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1481
1482 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1483
1484 double mu = 5.0;
1485 double sigma = 2.0;
1486
1487 // Create the RNG with the specified range.
1489 x->SetAttribute("Mu", DoubleValue(mu));
1490 x->SetAttribute("Sigma", DoubleValue(sigma));
1491
1492 // Calculate the mean of these values.
1493 double valueMean = Average(x);
1494
1495 // The expected value for the mean of the values returned by a
1496 // log-normally distributed random variable is equal to
1497 //
1498 // 2
1499 // mu + sigma / 2
1500 // E[value] = e .
1501 //
1502 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1503
1504 // Test that values have approximately the right mean value.
1505 //
1506 /**
1507 * @todo This test fails sometimes if the required tolerance is less
1508 * than 3%, which may be because there is a bug in the
1509 * implementation or that the mean of this distribution is more
1510 * sensitive to its parameters than the others are.
1511 */
1512 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1513 expectedMean,
1514 expectedMean * TOLERANCE,
1515 "Wrong mean value.");
1516}
1517
1518/**
1519 * @ingroup rng-tests
1520 * Test case for antithetic log-normal distribution random variable stream generator
1521 */
1523{
1524 public:
1525 // Constructor
1527
1528 // Inherited
1529 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1530
1531 private:
1532 // Inherited
1533 void DoRun() override;
1534
1535 /**
1536 * Tolerance for testing rng values against expectation,
1537 * as a fraction of mean value.
1538 */
1539 static constexpr double TOLERANCE{3e-2};
1540};
1541
1543 : TestCaseBase("Antithetic Log-Normal Random Variable Stream Generator")
1544{
1545}
1546
1547double
1549{
1550 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1551 auto range = UniformHistogramBins(h, 0, 10, false);
1552
1553 std::vector<double> expected(N_BINS);
1554
1555 // Note that this assumes that n has mu equal to zero and sigma
1556 // equal to one, which are their default values for this
1557 // distribution.
1558 double mu = 0.0;
1559 double sigma = 1.0;
1560
1561 for (std::size_t i = 0; i < N_BINS; ++i)
1562 {
1563 expected[i] =
1564 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1565 expected[i] *= N_MEASUREMENTS;
1566 }
1567
1568 double chiSquared = ChiSquared(h, expected, rng);
1569
1570 gsl_histogram_free(h);
1571 return chiSquared;
1572}
1573
1574void
1576{
1577 NS_LOG_FUNCTION(this);
1579
1580 auto generator = RngGenerator<LogNormalRandomVariable>(true);
1581 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1582 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1583 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1584
1585 double mu = 5.0;
1586 double sigma = 2.0;
1587
1588 // Create the RNG with the specified range.
1590 x->SetAttribute("Mu", DoubleValue(mu));
1591 x->SetAttribute("Sigma", DoubleValue(sigma));
1592
1593 // Make this generate antithetic values.
1594 x->SetAttribute("Antithetic", BooleanValue(true));
1595
1596 // Calculate the mean of these values.
1597 double valueMean = Average(x);
1598
1599 // The expected value for the mean of the values returned by a
1600 // log-normally distributed random variable is equal to
1601 //
1602 // 2
1603 // mu + sigma / 2
1604 // E[value] = e .
1605 //
1606 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1607
1608 // Test that values have approximately the right mean value.
1609 //
1610 /**
1611 * @todo This test fails sometimes if the required tolerance is less
1612 * than 3%, which may be because there is a bug in the
1613 * implementation or that the mean of this distribution is more
1614 * sensitive to its parameters than the others are.
1615 */
1616 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1617 expectedMean,
1618 expectedMean * TOLERANCE,
1619 "Wrong mean value.");
1620}
1621
1622/**
1623 * @ingroup rng-tests
1624 * Test case for gamma distribution random variable stream generator
1625 */
1627{
1628 public:
1629 // Constructor
1630 GammaTestCase();
1631
1632 // Inherited
1633 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1634
1635 private:
1636 // Inherited
1637 void DoRun() override;
1638
1639 /**
1640 * Tolerance for testing rng values against expectation,
1641 * as a fraction of mean value.
1642 */
1643 static constexpr double TOLERANCE{1e-2};
1644};
1645
1647 : TestCaseBase("Gamma Random Variable Stream Generator")
1648{
1649}
1650
1651double
1653{
1654 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1655 auto range = UniformHistogramBins(h, 0, 10, false);
1656
1657 std::vector<double> expected(N_BINS);
1658
1659 // Note that this assumes that n has alpha equal to one and beta
1660 // equal to one, which are their default values for this
1661 // distribution.
1662 double alpha = 1.0;
1663 double beta = 1.0;
1664
1665 for (std::size_t i = 0; i < N_BINS; ++i)
1666 {
1667 expected[i] =
1668 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1669 expected[i] *= N_MEASUREMENTS;
1670 }
1671
1672 double chiSquared = ChiSquared(h, expected, rng);
1673
1674 gsl_histogram_free(h);
1675 return chiSquared;
1676}
1677
1678void
1680{
1681 NS_LOG_FUNCTION(this);
1683
1684 auto generator = RngGenerator<GammaRandomVariable>();
1685 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1686 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1687 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1688
1689 double alpha = 5.0;
1690 double beta = 2.0;
1691
1692 // Create the RNG with the specified range.
1694 x->SetAttribute("Alpha", DoubleValue(alpha));
1695 x->SetAttribute("Beta", DoubleValue(beta));
1696
1697 // Calculate the mean of these values.
1698 double valueMean = Average(x);
1699
1700 // The expected value for the mean of the values returned by a
1701 // gammaly distributed random variable is equal to
1702 //
1703 // E[value] = alpha * beta .
1704 //
1705 double expectedMean = alpha * beta;
1706
1707 // Test that values have approximately the right mean value.
1708 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1709 expectedMean,
1710 expectedMean * TOLERANCE,
1711 "Wrong mean value.");
1712}
1713
1714/**
1715 * @ingroup rng-tests
1716 * Test case for antithetic gamma distribution random variable stream generator
1717 */
1719{
1720 public:
1721 // Constructor
1723
1724 // Inherited
1725 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1726
1727 private:
1728 // Inherited
1729 void DoRun() override;
1730
1731 /**
1732 * Tolerance for testing rng values against expectation,
1733 * as a fraction of mean value.
1734 */
1735 static constexpr double TOLERANCE{1e-2};
1736};
1737
1739 : TestCaseBase("Antithetic Gamma Random Variable Stream Generator")
1740{
1741}
1742
1743double
1745{
1746 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1747 auto range = UniformHistogramBins(h, 0, 10, false);
1748
1749 std::vector<double> expected(N_BINS);
1750
1751 // Note that this assumes that n has alpha equal to one and beta
1752 // equal to one, which are their default values for this
1753 // distribution.
1754 double alpha = 1.0;
1755 double beta = 1.0;
1756
1757 for (std::size_t i = 0; i < N_BINS; ++i)
1758 {
1759 expected[i] =
1760 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1761 expected[i] *= N_MEASUREMENTS;
1762 }
1763
1764 double chiSquared = ChiSquared(h, expected, rng);
1765
1766 gsl_histogram_free(h);
1767 return chiSquared;
1768}
1769
1770void
1772{
1773 NS_LOG_FUNCTION(this);
1775
1776 auto generator = RngGenerator<GammaRandomVariable>(true);
1777 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1778 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1779 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1780
1781 double alpha = 5.0;
1782 double beta = 2.0;
1783
1784 // Create the RNG with the specified range.
1786
1787 // Make this generate antithetic values.
1788 x->SetAttribute("Antithetic", BooleanValue(true));
1789
1790 x->SetAttribute("Alpha", DoubleValue(alpha));
1791 x->SetAttribute("Beta", DoubleValue(beta));
1792
1793 // Calculate the mean of these values.
1794 double valueMean = Average(x);
1795
1796 // The expected value for the mean of the values returned by a
1797 // gammaly distributed random variable is equal to
1798 //
1799 // E[value] = alpha * beta .
1800 //
1801 double expectedMean = alpha * beta;
1802
1803 // Test that values have approximately the right mean value.
1804 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1805 expectedMean,
1806 expectedMean * TOLERANCE,
1807 "Wrong mean value.");
1808}
1809
1810/**
1811 * @ingroup rng-tests
1812 * Test case for Erlang distribution random variable stream generator
1813 */
1815{
1816 public:
1817 // Constructor
1819
1820 // Inherited
1821 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1822
1823 private:
1824 // Inherited
1825 void DoRun() override;
1826
1827 /**
1828 * Tolerance for testing rng values against expectation,
1829 * as a fraction of mean value.
1830 */
1831 static constexpr double TOLERANCE{1e-2};
1832};
1833
1835 : TestCaseBase("Erlang Random Variable Stream Generator")
1836{
1837}
1838
1839double
1841{
1842 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1843 auto range = UniformHistogramBins(h, 0, 10, false);
1844
1845 std::vector<double> expected(N_BINS);
1846
1847 // Note that this assumes that n has k equal to one and lambda
1848 // equal to one, which are their default values for this
1849 // distribution.
1850 uint32_t k = 1;
1851 double lambda = 1.0;
1852
1853 // Note that Erlang distribution is equal to the gamma distribution
1854 // when k is an integer, which is why the gamma distribution's cdf
1855 // function can be used here.
1856 for (std::size_t i = 0; i < N_BINS; ++i)
1857 {
1858 expected[i] =
1859 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1860 expected[i] *= N_MEASUREMENTS;
1861 }
1862
1863 double chiSquared = ChiSquared(h, expected, rng);
1864
1865 gsl_histogram_free(h);
1866 return chiSquared;
1867}
1868
1869void
1871{
1872 NS_LOG_FUNCTION(this);
1874
1875 auto generator = RngGenerator<ErlangRandomVariable>();
1876 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1877 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1878 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1879
1880 uint32_t k = 5;
1881 double lambda = 2.0;
1882
1883 // Create the RNG with the specified range.
1885 x->SetAttribute("K", IntegerValue(k));
1886 x->SetAttribute("Lambda", DoubleValue(lambda));
1887
1888 // Calculate the mean of these values.
1889 double valueMean = Average(x);
1890
1891 // The expected value for the mean of the values returned by a
1892 // Erlangly distributed random variable is equal to
1893 //
1894 // E[value] = k * lambda .
1895 //
1896 double expectedMean = k * lambda;
1897
1898 // Test that values have approximately the right mean value.
1899 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1900 expectedMean,
1901 expectedMean * TOLERANCE,
1902 "Wrong mean value.");
1903}
1904
1905/**
1906 * @ingroup rng-tests
1907 * Test case for antithetic Erlang distribution random variable stream generator
1908 */
1910{
1911 public:
1912 // Constructor
1914
1915 // Inherited
1916 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1917
1918 private:
1919 // Inherited
1920 void DoRun() override;
1921
1922 /**
1923 * Tolerance for testing rng values against expectation,
1924 * as a fraction of mean value.
1925 */
1926 static constexpr double TOLERANCE{1e-2};
1927};
1928
1930 : TestCaseBase("Antithetic Erlang Random Variable Stream Generator")
1931{
1932}
1933
1934double
1936{
1937 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1938 auto range = UniformHistogramBins(h, 0, 10, false);
1939
1940 std::vector<double> expected(N_BINS);
1941
1942 // Note that this assumes that n has k equal to one and lambda
1943 // equal to one, which are their default values for this
1944 // distribution.
1945 uint32_t k = 1;
1946 double lambda = 1.0;
1947
1948 // Note that Erlang distribution is equal to the gamma distribution
1949 // when k is an integer, which is why the gamma distribution's cdf
1950 // function can be used here.
1951 for (std::size_t i = 0; i < N_BINS; ++i)
1952 {
1953 expected[i] =
1954 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1955 expected[i] *= N_MEASUREMENTS;
1956 }
1957
1958 double chiSquared = ChiSquared(h, expected, rng);
1959
1960 gsl_histogram_free(h);
1961 return chiSquared;
1962}
1963
1964void
1966{
1967 NS_LOG_FUNCTION(this);
1969
1970 auto generator = RngGenerator<ErlangRandomVariable>(true);
1971 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1972 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1973 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1974
1975 uint32_t k = 5;
1976 double lambda = 2.0;
1977
1978 // Create the RNG with the specified range.
1980
1981 // Make this generate antithetic values.
1982 x->SetAttribute("Antithetic", BooleanValue(true));
1983
1984 x->SetAttribute("K", IntegerValue(k));
1985 x->SetAttribute("Lambda", DoubleValue(lambda));
1986
1987 // Calculate the mean of these values.
1988 double valueMean = Average(x);
1989
1990 // The expected value for the mean of the values returned by a
1991 // Erlangly distributed random variable is equal to
1992 //
1993 // E[value] = k * lambda .
1994 //
1995 double expectedMean = k * lambda;
1996
1997 // Test that values have approximately the right mean value.
1998 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1999 expectedMean,
2000 expectedMean * TOLERANCE,
2001 "Wrong mean value.");
2002}
2003
2004/**
2005 * @ingroup rng-tests
2006 * Test case for Zipf distribution random variable stream generator
2007 */
2009{
2010 public:
2011 // Constructor
2012 ZipfTestCase();
2013
2014 private:
2015 // Inherited
2016 void DoRun() override;
2017
2018 /**
2019 * Tolerance for testing rng values against expectation,
2020 * as a fraction of mean value.
2021 */
2022 static constexpr double TOLERANCE{1e-2};
2023};
2024
2026 : TestCaseBase("Zipf Random Variable Stream Generator")
2027{
2028}
2029
2030void
2032{
2033 NS_LOG_FUNCTION(this);
2035
2036 uint32_t n = 1;
2037 double alpha = 2.0;
2038
2039 // Create the RNG with the specified range.
2041 x->SetAttribute("N", IntegerValue(n));
2042 x->SetAttribute("Alpha", DoubleValue(alpha));
2043
2044 // Calculate the mean of these values.
2045 double valueMean = Average(x);
2046
2047 // The expected value for the mean of the values returned by a
2048 // Zipfly distributed random variable is equal to
2049 //
2050 // H
2051 // N, alpha - 1
2052 // E[value] = ---------------
2053 // H
2054 // N, alpha
2055 //
2056 // where
2057 //
2058 // N
2059 // ---
2060 // \ -alpha
2061 // H = / m .
2062 // N, alpha ---
2063 // m=1
2064 //
2065 // For this test,
2066 //
2067 // -(alpha - 1)
2068 // 1
2069 // E[value] = ---------------
2070 // -alpha
2071 // 1
2072 //
2073 // = 1 .
2074 //
2075 double expectedMean = 1.0;
2076
2077 // Test that values have approximately the right mean value.
2078 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2079 expectedMean,
2080 expectedMean * TOLERANCE,
2081 "Wrong mean value.");
2082}
2083
2084/**
2085 * @ingroup rng-tests
2086 * Test case for antithetic Zipf distribution random variable stream generator
2087 */
2089{
2090 public:
2091 // Constructor
2093
2094 private:
2095 // Inherited
2096 void DoRun() override;
2097
2098 /**
2099 * Tolerance for testing rng values against expectation,
2100 * as a fraction of mean value.
2101 */
2102 static constexpr double TOLERANCE{1e-2};
2103};
2104
2106 : TestCaseBase("Antithetic Zipf Random Variable Stream Generator")
2107{
2108}
2109
2110void
2112{
2113 NS_LOG_FUNCTION(this);
2115
2116 uint32_t n = 1;
2117 double alpha = 2.0;
2118
2119 // Create the RNG with the specified range.
2121 x->SetAttribute("N", IntegerValue(n));
2122 x->SetAttribute("Alpha", DoubleValue(alpha));
2123
2124 // Make this generate antithetic values.
2125 x->SetAttribute("Antithetic", BooleanValue(true));
2126
2127 // Calculate the mean of these values.
2128 double valueMean = Average(x);
2129
2130 // The expected value for the mean of the values returned by a
2131 // Zipfly distributed random variable is equal to
2132 //
2133 // H
2134 // N, alpha - 1
2135 // E[value] = ---------------
2136 // H
2137 // N, alpha
2138 //
2139 // where
2140 //
2141 // N
2142 // ---
2143 // \ -alpha
2144 // H = / m .
2145 // N, alpha ---
2146 // m=1
2147 //
2148 // For this test,
2149 //
2150 // -(alpha - 1)
2151 // 1
2152 // E[value] = ---------------
2153 // -alpha
2154 // 1
2155 //
2156 // = 1 .
2157 //
2158 double expectedMean = 1.0;
2159
2160 // Test that values have approximately the right mean value.
2161 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2162 expectedMean,
2163 expectedMean * TOLERANCE,
2164 "Wrong mean value.");
2165}
2166
2167/**
2168 * @ingroup rng-tests
2169 * Test case for Zeta distribution random variable stream generator
2170 */
2172{
2173 public:
2174 // Constructor
2175 ZetaTestCase();
2176
2177 private:
2178 // Inherited
2179 void DoRun() override;
2180
2181 /**
2182 * Tolerance for testing rng values against expectation,
2183 * as a fraction of mean value.
2184 */
2185 static constexpr double TOLERANCE{1e-2};
2186};
2187
2189 : TestCaseBase("Zeta Random Variable Stream Generator")
2190{
2191}
2192
2193void
2195{
2196 NS_LOG_FUNCTION(this);
2198
2199 double alpha = 5.0;
2200
2201 // Create the RNG with the specified range.
2203 x->SetAttribute("Alpha", DoubleValue(alpha));
2204
2205 // Calculate the mean of these values.
2206 double valueMean = Average(x);
2207
2208 // The expected value for the mean of the values returned by a
2209 // zetaly distributed random variable is equal to
2210 //
2211 // zeta(alpha - 1)
2212 // E[value] = --------------- for alpha > 2 ,
2213 // zeta(alpha)
2214 //
2215 // where zeta(alpha) is the Riemann zeta function.
2216 //
2217 // There are no simple analytic forms for the Riemann zeta function,
2218 // which is why the gsl library is used in this test to calculate
2219 // the known mean of the values.
2220 double expectedMean =
2221 gsl_sf_zeta_int(static_cast<int>(alpha - 1)) / gsl_sf_zeta_int(static_cast<int>(alpha));
2222
2223 // Test that values have approximately the right mean value.
2224 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2225 expectedMean,
2226 expectedMean * TOLERANCE,
2227 "Wrong mean value.");
2228}
2229
2230/**
2231 * @ingroup rng-tests
2232 * Test case for antithetic Zeta distribution random variable stream generator
2233 */
2235{
2236 public:
2237 // Constructor
2239
2240 private:
2241 // Inherited
2242 void DoRun() override;
2243
2244 /**
2245 * Tolerance for testing rng values against expectation,
2246 * as a fraction of mean value.
2247 */
2248 static constexpr double TOLERANCE{1e-2};
2249};
2250
2252 : TestCaseBase("Antithetic Zeta Random Variable Stream Generator")
2253{
2254}
2255
2256void
2258{
2259 NS_LOG_FUNCTION(this);
2261
2262 double alpha = 5.0;
2263
2264 // Create the RNG with the specified range.
2266 x->SetAttribute("Alpha", DoubleValue(alpha));
2267
2268 // Make this generate antithetic values.
2269 x->SetAttribute("Antithetic", BooleanValue(true));
2270
2271 // Calculate the mean of these values.
2272 double valueMean = Average(x);
2273
2274 // The expected value for the mean of the values returned by a
2275 // zetaly distributed random variable is equal to
2276 //
2277 // zeta(alpha - 1)
2278 // E[value] = --------------- for alpha > 2 ,
2279 // zeta(alpha)
2280 //
2281 // where zeta(alpha) is the Riemann zeta function.
2282 //
2283 // There are no simple analytic forms for the Riemann zeta function,
2284 // which is why the gsl library is used in this test to calculate
2285 // the known mean of the values.
2286 double expectedMean =
2287 gsl_sf_zeta_int(static_cast<int>(alpha) - 1) / gsl_sf_zeta_int(static_cast<int>(alpha));
2288
2289 // Test that values have approximately the right mean value.
2290 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2291 expectedMean,
2292 expectedMean * TOLERANCE,
2293 "Wrong mean value.");
2294}
2295
2296/**
2297 * @ingroup rng-tests
2298 * Test case for deterministic random variable stream generator
2299 */
2301{
2302 public:
2303 // Constructor
2305
2306 private:
2307 // Inherited
2308 void DoRun() override;
2309
2310 /** Tolerance for testing rng values against expectation. */
2311 static constexpr double TOLERANCE{1e-8};
2312};
2313
2315 : TestCaseBase("Deterministic Random Variable Stream Generator")
2316{
2317}
2318
2319void
2321{
2322 NS_LOG_FUNCTION(this);
2324
2326
2327 // The following array should give the sequence
2328 //
2329 // 4, 4, 7, 7, 10, 10 .
2330 //
2331 double array1[] = {4, 4, 7, 7, 10, 10};
2332 std::size_t count1 = 6;
2333 s->SetValueArray(array1, count1);
2334
2335 double value;
2336
2337 // Test that the first sequence is correct.
2338 value = s->GetValue();
2339 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2340 value = s->GetValue();
2341 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2342 value = s->GetValue();
2343 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2344 value = s->GetValue();
2345 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2346 value = s->GetValue();
2347 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2348 value = s->GetValue();
2349 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2350
2351 // The following array should give the sequence
2352 //
2353 // 1000, 2000, 7, 7 .
2354 //
2355 double array2[] = {1000, 2000, 3000, 4000};
2356 std::size_t count2 = 4;
2357 s->SetValueArray(array2, count2);
2358
2359 // Test that the second sequence is correct.
2360 value = s->GetValue();
2361 NS_TEST_ASSERT_MSG_EQ_TOL(value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2362 value = s->GetValue();
2363 NS_TEST_ASSERT_MSG_EQ_TOL(value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2364 value = s->GetValue();
2365 NS_TEST_ASSERT_MSG_EQ_TOL(value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2366 value = s->GetValue();
2367 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2368 value = s->GetValue();
2369}
2370
2371/**
2372 * @ingroup rng-tests
2373 * Test case for empirical distribution random variable stream generator
2374 */
2376{
2377 public:
2378 // Constructor
2380
2381 private:
2382 // Inherited
2383 void DoRun() override;
2384
2385 /**
2386 * Tolerance for testing rng values against expectation,
2387 * as a fraction of mean value.
2388 */
2389 static constexpr double TOLERANCE{1e-2};
2390};
2391
2393 : TestCaseBase("Empirical Random Variable Stream Generator")
2394{
2395}
2396
2397void
2399{
2400 NS_LOG_FUNCTION(this);
2402
2403 // Create the RNG with a uniform distribution between 0 and 10.
2405 x->SetInterpolate(false);
2406 x->CDF(0.0, 0.0);
2407 x->CDF(5.0, 0.25);
2408 x->CDF(10.0, 1.0);
2409
2410 // Check that only the correct values are returned
2411 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2412 {
2413 double value = x->GetValue();
2414 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2415 true,
2416 "Incorrect value returned, expected only 5 or 10.");
2417 }
2418
2419 // Calculate the mean of the sampled values.
2420 double valueMean = Average(x);
2421
2422 // The expected distribution with sampled values is
2423 // Value Probability
2424 // 5 25%
2425 // 10 75%
2426 //
2427 // The expected mean is
2428 //
2429 // E[value] = 5 * 25% + 10 * 75% = 8.75
2430 //
2431 // Test that values have approximately the right mean value.
2432 double expectedMean = 8.75;
2433 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2434 expectedMean,
2435 expectedMean * TOLERANCE,
2436 "Wrong mean value.");
2437
2438 // Calculate the mean of the interpolated values.
2439 x->SetInterpolate(true);
2440 valueMean = Average(x);
2441
2442 // The expected distribution (with interpolation) is
2443 // Bin Probability
2444 // [0, 5) 25%
2445 // [5, 10) 75%
2446 //
2447 // Each bin is uniformly sampled, so the average of the samples in the
2448 // bin is the center of the bin.
2449 //
2450 // The expected mean is
2451 //
2452 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2453 //
2454 expectedMean = 6.25;
2455
2456 // Test that values have approximately the right mean value.
2457 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2458 expectedMean,
2459 expectedMean * TOLERANCE,
2460 "Wrong mean value.");
2461
2462 // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2464 y->SetInterpolate(false);
2465 y->CDF(-1.0, 0.0);
2466 y->CDF(0.0, 0.5);
2467 y->CDF(1.0, 1.0);
2468 NS_TEST_ASSERT_MSG_LT(y->GetValue(), 2, "Empirical variable with negative domain");
2469}
2470
2471/**
2472 * @ingroup rng-tests
2473 * Test case for antithetic empirical distribution random variable stream generator
2474 */
2476{
2477 public:
2478 // Constructor
2480
2481 private:
2482 // Inherited
2483 void DoRun() override;
2484
2485 /**
2486 * Tolerance for testing rng values against expectation,
2487 * as a fraction of mean value.
2488 */
2489 static constexpr double TOLERANCE{1e-2};
2490};
2491
2493 : TestCaseBase("EmpiricalAntithetic Random Variable Stream Generator")
2494{
2495}
2496
2497void
2499{
2500 NS_LOG_FUNCTION(this);
2502
2503 // Create the RNG with a uniform distribution between 0 and 10.
2505 x->SetInterpolate(false);
2506 x->CDF(0.0, 0.0);
2507 x->CDF(5.0, 0.25);
2508 x->CDF(10.0, 1.0);
2509
2510 // Make this generate antithetic values.
2511 x->SetAttribute("Antithetic", BooleanValue(true));
2512
2513 // Check that only the correct values are returned
2514 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2515 {
2516 double value = x->GetValue();
2517 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2518 true,
2519 "Incorrect value returned, expected only 5 or 10.");
2520 }
2521
2522 // Calculate the mean of these values.
2523 double valueMean = Average(x);
2524 // Expected
2525 // E[value] = 5 * 25% + 10 * 75% = 8.75
2526 double expectedMean = 8.75;
2527 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2528 expectedMean,
2529 expectedMean * TOLERANCE,
2530 "Wrong mean value.");
2531
2532 // Check interpolated sampling
2533 x->SetInterpolate(true);
2534 valueMean = Average(x);
2535
2536 // The expected value for the mean of the values returned by this
2537 // empirical distribution with interpolation is
2538 //
2539 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2540 //
2541 expectedMean = 6.25;
2542
2543 // Test that values have approximately the right mean value.
2544 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2545 expectedMean,
2546 expectedMean * TOLERANCE,
2547 "Wrong mean value.");
2548}
2549
2550/**
2551 * @ingroup rng-tests
2552 * Test case for caching of Normal RV parameters (see issue #302)
2553 */
2555{
2556 public:
2557 // Constructor
2559
2560 private:
2561 // Inherited
2562 void DoRun() override;
2563};
2564
2566 : TestCaseBase("NormalRandomVariable caching of parameters")
2567{
2568}
2569
2570void
2572{
2573 NS_LOG_FUNCTION(this);
2575
2577 double v1 = n->GetValue(-10, 1, 10); // Mean -10, variance 1, bounded to [-20,0]
2578 double v2 = n->GetValue(10, 1, 10); // Mean 10, variance 1, bounded to [0,20]
2579
2580 NS_TEST_ASSERT_MSG_LT(v1, 0, "Incorrect value returned, expected < 0");
2581 NS_TEST_ASSERT_MSG_GT(v2, 0, "Incorrect value returned, expected > 0");
2582}
2583
2584/**
2585 * @ingroup rng-tests
2586 * Test case for bernoulli distribution random variable stream generator
2587 */
2589{
2590 public:
2591 // Constructor
2593
2594 // Inherited
2595 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2596
2597 private:
2598 // Inherited
2599 void DoRun() override;
2600
2601 /** Tolerance for testing rng values against expectation, in rms. */
2602 static constexpr double TOLERANCE{5};
2603};
2604
2606 : TestCaseBase("Bernoulli Random Variable Stream Generator")
2607{
2608}
2609
2610double
2612{
2613 gsl_histogram* h = gsl_histogram_alloc(2);
2614 auto range = UniformHistogramBins(h, 0, 1);
2615
2616 double p = 0.5;
2617 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2618
2619 double chiSquared = ChiSquared(h, expected, rng);
2620
2621 gsl_histogram_free(h);
2622 return chiSquared;
2623}
2624
2625void
2627{
2628 NS_LOG_FUNCTION(this);
2630
2631 auto generator = RngGenerator<BernoulliRandomVariable>();
2632 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2633 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2634 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2635
2636 double probability = 0.5;
2637
2638 // Create the RNG with the specified range.
2640 x->SetAttribute("Probability", DoubleValue(probability));
2641
2642 // Calculate the mean of these values.
2643 double mean = probability;
2644 double valueMean = Average(x);
2645 double expectedMean = mean;
2646 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2647
2648 // Test that values have approximately the right mean value.
2649 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2650 expectedMean,
2651 expectedRms * TOLERANCE,
2652 "Wrong mean value.");
2653}
2654
2655/**
2656 * @ingroup rng-tests
2657 * Test case for antithetic bernoulli distribution random variable stream generator
2658 */
2660{
2661 public:
2662 // Constructor
2664
2665 // Inherited
2666 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2667
2668 private:
2669 // Inherited
2670 void DoRun() override;
2671
2672 /** Tolerance for testing rng values against expectation, in rms. */
2673 static constexpr double TOLERANCE{5};
2674};
2675
2677 : TestCaseBase("Antithetic Bernoulli Random Variable Stream Generator")
2678{
2679}
2680
2681double
2683{
2684 gsl_histogram* h = gsl_histogram_alloc(2);
2685 auto range = UniformHistogramBins(h, 0, 1);
2686
2687 double p = 0.5;
2688 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2689
2690 double chiSquared = ChiSquared(h, expected, rng);
2691
2692 gsl_histogram_free(h);
2693 return chiSquared;
2694}
2695
2696void
2698{
2699 NS_LOG_FUNCTION(this);
2701
2702 auto generator = RngGenerator<BernoulliRandomVariable>(true);
2703 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2704 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2705 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2706
2707 double probability = 0.5;
2708
2709 // Create the RNG with the specified range.
2711 x->SetAttribute("Probability", DoubleValue(probability));
2712
2713 // Make this generate antithetic values.
2714 x->SetAttribute("Antithetic", BooleanValue(true));
2715
2716 // Calculate the mean of these values.
2717 double mean = probability;
2718 double valueMean = Average(x);
2719 double expectedMean = mean;
2720 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2721
2722 // Test that values have approximately the right mean value.
2723 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2724 expectedMean,
2725 expectedRms * TOLERANCE,
2726 "Wrong mean value.");
2727}
2728
2729/**
2730 * @ingroup rng-tests
2731 * Test case for binomial distribution random variable stream generator
2732 */
2734{
2735 public:
2736 // Constructor
2738
2739 // Inherited
2740 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2741
2742 private:
2743 // Inherited
2744 void DoRun() override;
2745
2746 /** Tolerance for testing rng values against expectation, in rms. */
2747 static constexpr double TOLERANCE{5};
2748};
2749
2751 : TestCaseBase("Binomial Random Variable Stream Generator")
2752{
2753}
2754
2755double
2757{
2758 uint32_t trials = 10;
2759 double probability = 0.5;
2760
2761 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2762 auto range = UniformHistogramBins(h, 0, trials);
2763
2764 std::vector<double> expected(trials + 1);
2765 for (std::size_t i = 0; i < trials + 1; ++i)
2766 {
2767 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2768 }
2769
2770 double chiSquared = ChiSquared(h, expected, rng);
2771
2772 gsl_histogram_free(h);
2773 return chiSquared;
2774}
2775
2776void
2778{
2779 NS_LOG_FUNCTION(this);
2781
2782 uint32_t trials = 10;
2783 double probability = 0.5;
2784
2785 auto generator = RngGenerator<BinomialRandomVariable>();
2786 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2787 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2788 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2789
2790 // Create the RNG with the specified range.
2792 x->SetAttribute("Trials", IntegerValue(trials));
2793 x->SetAttribute("Probability", DoubleValue(probability));
2794
2795 // Calculate the mean of these values.
2796 double mean = trials * probability;
2797 double valueMean = Average(x);
2798 double expectedMean = mean;
2799 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2800
2801 // Test that values have approximately the right mean value.
2802 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2803 expectedMean,
2804 expectedRms * TOLERANCE,
2805 "Wrong mean value.");
2806}
2807
2808/**
2809 * @ingroup rng-tests
2810 * Test case for antithetic binomial distribution random variable stream generator
2811 */
2813{
2814 public:
2815 // Constructor
2817
2818 // Inherited
2819 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2820
2821 private:
2822 // Inherited
2823 void DoRun() override;
2824
2825 /** Tolerance for testing rng values against expectation, in rms. */
2826 static constexpr double TOLERANCE{5};
2827};
2828
2830 : TestCaseBase("Antithetic Binomial Random Variable Stream Generator")
2831{
2832}
2833
2834double
2836{
2837 uint32_t trials = 10;
2838 double probability = 0.5;
2839
2840 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2841 auto range = UniformHistogramBins(h, 0, trials);
2842
2843 std::vector<double> expected(trials + 1);
2844 for (std::size_t i = 0; i < trials + 1; ++i)
2845 {
2846 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2847 }
2848
2849 double chiSquared = ChiSquared(h, expected, rng);
2850
2851 gsl_histogram_free(h);
2852 return chiSquared;
2853}
2854
2855void
2857{
2858 NS_LOG_FUNCTION(this);
2860
2861 uint32_t trials = 10;
2862 double probability = 0.5;
2863
2864 auto generator = RngGenerator<BinomialRandomVariable>(true);
2865 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2866 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2867 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2868
2869 // Create the RNG with the specified range.
2871 x->SetAttribute("Trials", IntegerValue(trials));
2872 x->SetAttribute("Probability", DoubleValue(probability));
2873
2874 // Make this generate antithetic values.
2875 x->SetAttribute("Antithetic", BooleanValue(true));
2876
2877 // Calculate the mean of these values.
2878 double mean = trials * probability;
2879 double valueMean = Average(x);
2880 double expectedMean = mean;
2881 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2882
2883 // Test that values have approximately the right mean value.
2884 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2885 expectedMean,
2886 expectedRms * TOLERANCE,
2887 "Wrong mean value.");
2888}
2889
2890/**
2891 * @ingroup rng-test
2892 * @ingroup tests
2893 *
2894 * @brief Test the Shuffle function
2895 *
2896 * Check that the Shuffle function actually shuffles the elements and does so in a portable way.
2897 */
2899{
2900 public:
2902
2903 private:
2904 void DoRun() override;
2905};
2906
2908 : TestCase("Check correct operation of the Shuffle function")
2909{
2910}
2911
2912void
2914{
2917
2919 rv->SetStream(1);
2920
2921 // test empty vector
2922 std::vector<uint8_t> vec{};
2923
2924 Shuffle(vec.begin(), vec.end(), rv);
2925
2926 NS_TEST_EXPECT_MSG_EQ(vec.empty(), true, "Expected an empty vector");
2927
2928 // test vector with one value
2929 vec.push_back(3);
2930
2931 Shuffle(vec.begin(), vec.end(), rv);
2932
2933 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{3}), true, "Expected vector {3}");
2934
2935 // test vector with two values
2936 vec.push_back(1);
2937
2938 Shuffle(vec.begin(), vec.end(), rv);
2939
2940 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{1, 3}), true, "Expected vector {1, 3}");
2941
2942 // test vector with multiple values
2943 vec.push_back(7);
2944 vec.push_back(2);
2945 vec.push_back(4);
2946 vec.push_back(9);
2947
2948 Shuffle(vec.begin(), vec.end(), rv);
2949
2950 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{4, 1, 9, 3, 2, 7}),
2951 true,
2952 "Expected vector {4, 1, 9, 3, 2, 7}");
2953}
2954
2955/**
2956 * @ingroup rng-tests
2957 * Test case for laplacian distribution random variable stream generator
2958 */
2960{
2961 public:
2963
2964 private:
2965 void DoRun() override;
2966
2967 /**
2968 * Tolerance for testing rng values against expectation,
2969 * as a fraction of mean value.
2970 */
2971 static constexpr double TOLERANCE{1e-2};
2972};
2973
2975 : TestCaseBase("Laplacian Random Variable Stream Generator")
2976{
2977}
2978
2979void
2981{
2982 NS_LOG_FUNCTION(this);
2984
2985 double mu = -5.0;
2986 double scale = 4.0;
2987 double bound = 20.0;
2988
2989 // Create unbounded RNG with the specified range.
2991 x1->SetAttribute("Location", DoubleValue(mu));
2992 x1->SetAttribute("Scale", DoubleValue(scale));
2993
2994 // Calculate the mean of these values.
2995 auto valueMean = Average(x1);
2996
2997 // Calculate the variance of these values.
2998 auto valueVariance = Variance(x1, valueMean);
2999
3000 // Test that values have approximately the right mean value.
3001 const auto expectedMean = mu;
3002 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3003
3004 // Test that values have approximately the right variance value.
3005 const auto expectedVariance = LaplacianRandomVariable::GetVariance(scale);
3006 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3007 expectedVariance,
3008 TOLERANCE * expectedVariance,
3009 "Wrong variance value.");
3010
3011 // Create bounded RNG with the specified range.
3013 x2->SetAttribute("Location", DoubleValue(mu));
3014 x2->SetAttribute("Scale", DoubleValue(scale));
3015 x2->SetAttribute("Bound", DoubleValue(bound));
3016
3017 // Calculate the mean of these values.
3018 valueMean = Average(x2);
3019
3020 // Test that values have approximately the right mean value.
3021 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3022
3023 // Check that only the correct values are returned
3024 const auto lowerBound = mu - bound;
3025 const auto upperBound = mu + bound;
3026 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
3027 {
3028 const auto value = x2->GetValue();
3029 NS_TEST_EXPECT_MSG_EQ((value >= lowerBound) || (value <= upperBound),
3030 true,
3031 "Value not in expected boundaries.");
3032 }
3033}
3034
3035/**
3036 * @ingroup rng-tests
3037 * Test case for largest extreme value distribution random variable stream generator
3038 */
3040{
3041 public:
3043
3044 private:
3045 void DoRun() override;
3046
3047 /**
3048 * Tolerance for testing rng values against expectation,
3049 * as a fraction of mean value.
3050 */
3051 static constexpr double TOLERANCE{1e-2};
3052};
3053
3055 : TestCaseBase("Largest Extreme Value Random Variable Stream Generator")
3056{
3057}
3058
3059void
3061{
3062 NS_LOG_FUNCTION(this);
3064
3065 double mu = 2.0;
3066 double scale = 1.0;
3067
3068 // Create RNG with the specified range.
3070 x->SetAttribute("Location", DoubleValue(mu));
3071 x->SetAttribute("Scale", DoubleValue(scale));
3072
3073 // Calculate the mean of these values.
3074 auto valueMean = Average(x);
3075
3076 // Calculate the variance of these values.
3077 auto valueVariance = Variance(x, valueMean);
3078
3079 // Test that values have approximately the right mean value.
3080 const auto expectedMean = LargestExtremeValueRandomVariable::GetMean(mu, scale);
3081 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3082
3083 // Test that values have approximately the right variance value.
3084 const auto expectedVariance = LargestExtremeValueRandomVariable::GetVariance(scale);
3085 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3086 expectedVariance,
3087 TOLERANCE * expectedVariance,
3088 "Wrong variance value.");
3089}
3090
3091/**
3092 * @ingroup rng-tests
3093 * RandomVariableStream test suite, covering all random number variable
3094 * stream generator types.
3095 */
3097{
3098 public:
3099 // Constructor
3101};
3102
3104 : TestSuite("random-variable-stream-generators", Type::UNIT)
3105{
3119 /// @todo This test is currently disabled because it fails sometimes.
3120 /// A possible reason for the failure is that the antithetic code is
3121 /// not implemented properly for this log-normal case.
3122 /*
3123 AddTestCase (new LogNormalAntitheticTestCase);
3124 */
3126 /// @todo This test is currently disabled because it fails sometimes.
3127 /// A possible reason for the failure is that the antithetic code is
3128 /// not implemented properly for this gamma case.
3129 /*
3130 AddTestCase (new GammaAntitheticTestCase);
3131 */
3141 /// Issue #302: NormalRandomVariable produces stale values
3150}
3151
3152static RandomVariableSuite randomVariableSuite; //!< Static variable for test initialization
3153
3154} // namespace RandomVariable
3155
3156} // namespace test
3157
3158} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
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