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
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 // Repeat test when setting via stddev attribute instead of variance
749 x->SetStdDev(sqrt(variance));
750
751 // Calculate the mean of these values.
752 valueMean = Average(x);
753
754 // The expected value for the mean of the values returned by a
755 // normally distributed random variable is equal to mean.
756 expectedMean = mean;
757 expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
758
759 // Test that values have approximately the right mean value.
761 expectedMean,
762 expectedRms * TOLERANCE,
763 "Wrong mean value.");
764}
765
766/**
767 * @ingroup rng-tests
768 * Test case for antithetic normal distribution random variable stream generator
769 */
771{
772 public:
773 // Constructor
775
776 // Inherited
777 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
778
779 private:
780 // Inherited
781 void DoRun() override;
782
783 /** Tolerance for testing rng values against expectation, in rms. */
784 static constexpr double TOLERANCE{5};
785};
786
788 : TestCaseBase("Antithetic Normal Random Variable Stream Generator")
789{
790}
791
792double
794{
795 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
796 auto range = UniformHistogramBins(h, -4, 4);
797
798 std::vector<double> expected(N_BINS);
799
800 // Note that this assumes that n has mean equal to zero and standard
801 // deviation equal to one, which are their default values for this
802 // distribution.
803 double sigma = 1.;
804
805 for (std::size_t i = 0; i < N_BINS; ++i)
806 {
807 expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
808 expected[i] *= N_MEASUREMENTS;
809 }
810
811 double chiSquared = ChiSquared(h, expected, rng);
812
813 gsl_histogram_free(h);
814 return chiSquared;
815}
816
817void
819{
820 NS_LOG_FUNCTION(this);
822
823 auto generator = RngGenerator<NormalRandomVariable>(true);
824 double sum = ChiSquaredsAverage(&generator, N_RUNS);
825 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
826 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
827
828 double mean = 5.0;
829 double variance = 2.0;
830
831 // Create the RNG with the specified range.
833 x->SetAttribute("Mean", DoubleValue(mean));
834 x->SetAttribute("Variance", DoubleValue(variance));
835
836 // Make this generate antithetic values.
837 x->SetAttribute("Antithetic", BooleanValue(true));
838
839 // Calculate the mean of these values.
840 double valueMean = Average(x);
841
842 // The expected value for the mean of the values returned by a
843 // normally distributed random variable is equal to mean.
844 double expectedMean = mean;
845 double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
846
847 // Test that values have approximately the right mean value.
849 expectedMean,
850 expectedRms * TOLERANCE,
851 "Wrong mean value.");
852}
853
854/**
855 * @ingroup rng-tests
856 * Test case for exponential distribution random variable stream generator
857 */
859{
860 public:
861 // Constructor
863
864 // Inherited
865 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
866
867 private:
868 // Inherited
869 void DoRun() override;
870
871 /** Tolerance for testing rng values against expectation, in rms. */
872 static constexpr double TOLERANCE{5};
873};
874
876 : TestCaseBase("Exponential Random Variable Stream Generator")
877{
878}
879
880double
882{
883 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
884 auto range = UniformHistogramBins(h, 0, 10, false);
885
886 std::vector<double> expected(N_BINS);
887
888 // Note that this assumes that e has mean equal to one, which is the
889 // default value for this distribution.
890 double mu = 1.;
891
892 for (std::size_t i = 0; i < N_BINS; ++i)
893 {
894 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
895 expected[i] *= N_MEASUREMENTS;
896 }
897
898 double chiSquared = ChiSquared(h, expected, rng);
899
900 gsl_histogram_free(h);
901 return chiSquared;
902}
903
904void
906{
907 NS_LOG_FUNCTION(this);
909
911 double sum = ChiSquaredsAverage(&generator, N_RUNS);
912 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
913 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
914
915 double mean = 3.14;
916 double bound = 0.0;
917
918 // Create the RNG with the specified range.
920 x->SetAttribute("Mean", DoubleValue(mean));
921 x->SetAttribute("Bound", DoubleValue(bound));
922
923 // Calculate the mean of these values.
924 double valueMean = Average(x);
925 double expectedMean = mean;
926 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
927
928 // Test that values have approximately the right mean value.
930 expectedMean,
931 expectedRms * TOLERANCE,
932 "Wrong mean value.");
933}
934
935/**
936 * @ingroup rng-tests
937 * Test case for antithetic exponential distribution random variable stream generator
938 */
940{
941 public:
942 // Constructor
944
945 // Inherited
946 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
947
948 private:
949 // Inherited
950 void DoRun() override;
951
952 /** Tolerance for testing rng values against expectation, in rms. */
953 static constexpr double TOLERANCE{5};
954};
955
957 : TestCaseBase("Antithetic Exponential Random Variable Stream Generator")
958{
959}
960
961double
963{
964 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
965 auto range = UniformHistogramBins(h, 0, 10, false);
966
967 std::vector<double> expected(N_BINS);
968
969 // Note that this assumes that e has mean equal to one, which is the
970 // default value for this distribution.
971 double mu = 1.;
972
973 for (std::size_t i = 0; i < N_BINS; ++i)
974 {
975 expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
976 expected[i] *= N_MEASUREMENTS;
977 }
978
979 double chiSquared = ChiSquared(h, expected, rng);
980
981 gsl_histogram_free(h);
982 return chiSquared;
983}
984
985void
987{
988 NS_LOG_FUNCTION(this);
990
991 auto generator = RngGenerator<ExponentialRandomVariable>(true);
992 double sum = ChiSquaredsAverage(&generator, N_RUNS);
993 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
994 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
995
996 double mean = 3.14;
997 double bound = 0.0;
998
999 // Create the RNG with the specified range.
1001 x->SetAttribute("Mean", DoubleValue(mean));
1002 x->SetAttribute("Bound", DoubleValue(bound));
1003
1004 // Make this generate antithetic values.
1005 x->SetAttribute("Antithetic", BooleanValue(true));
1006
1007 // Calculate the mean of these values.
1008 double valueMean = Average(x);
1009 double expectedMean = mean;
1010 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
1011
1012 // Test that values have approximately the right mean value.
1013 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1014 expectedMean,
1015 expectedRms * TOLERANCE,
1016 "Wrong mean value.");
1017}
1018
1019/**
1020 * @ingroup rng-tests
1021 * Test case for Pareto distribution random variable stream generator
1022 */
1024{
1025 public:
1026 // Constructor
1028
1029 // Inherited
1030 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1031
1032 private:
1033 // Inherited
1034 void DoRun() override;
1035
1036 /**
1037 * Tolerance for testing rng values against expectation,
1038 * as a fraction of mean value.
1039 */
1040 static constexpr double TOLERANCE{1e-2};
1041};
1042
1044 : TestCaseBase("Pareto Random Variable Stream Generator")
1045{
1046}
1047
1048double
1050{
1051 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1052 auto range = UniformHistogramBins(h, 1, 10, false);
1053
1054 std::vector<double> expected(N_BINS);
1055
1056 double shape = 2.0;
1057 double scale = 1.0;
1058
1059 for (std::size_t i = 0; i < N_BINS; ++i)
1060 {
1061 expected[i] =
1062 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1063 expected[i] *= N_MEASUREMENTS;
1064 }
1065
1066 double chiSquared = ChiSquared(h, expected, rng);
1067
1068 gsl_histogram_free(h);
1069 return chiSquared;
1070}
1071
1072void
1074{
1075 NS_LOG_FUNCTION(this);
1077
1078 auto generator = RngGenerator<ParetoRandomVariable>();
1079 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1080 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1081 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1082
1083 double shape = 2.0;
1084 double scale = 1.0;
1085
1086 // Create the RNG with the specified range.
1088 x->SetAttribute("Shape", DoubleValue(shape));
1089 x->SetAttribute("Scale", DoubleValue(scale));
1090
1091 // Calculate the mean of these values.
1092 double valueMean = Average(x);
1093
1094 // The expected value for the mean is given by
1095 //
1096 // shape * scale
1097 // E[value] = --------------- ,
1098 // shape - 1
1099 //
1100 // where
1101 //
1102 // scale = mean * (shape - 1.0) / shape .
1103 double expectedMean = (shape * scale) / (shape - 1.0);
1104
1105 // Test that values have approximately the right mean value.
1106 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1107 expectedMean,
1108 expectedMean * TOLERANCE,
1109 "Wrong mean value.");
1110}
1111
1112/**
1113 * @ingroup rng-tests
1114 * Test case for antithetic Pareto distribution random variable stream generator
1115 */
1117{
1118 public:
1119 // Constructor
1121
1122 // Inherited
1123 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1124
1125 private:
1126 // Inherited
1127 void DoRun() override;
1128
1129 /**
1130 * Tolerance for testing rng values against expectation,
1131 * as a fraction of mean value.
1132 */
1133 static constexpr double TOLERANCE{1e-2};
1134};
1135
1137 : TestCaseBase("Antithetic Pareto Random Variable Stream Generator")
1138{
1139}
1140
1141double
1143{
1144 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1145 auto range = UniformHistogramBins(h, 1, 10, false);
1146
1147 std::vector<double> expected(N_BINS);
1148
1149 double shape = 2.0;
1150 double scale = 1.0;
1151
1152 for (std::size_t i = 0; i < N_BINS; ++i)
1153 {
1154 expected[i] =
1155 gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1156 expected[i] *= N_MEASUREMENTS;
1157 }
1158
1159 double chiSquared = ChiSquared(h, expected, rng);
1160
1161 gsl_histogram_free(h);
1162 return chiSquared;
1163}
1164
1165void
1167{
1168 NS_LOG_FUNCTION(this);
1170
1171 auto generator = RngGenerator<ParetoRandomVariable>(true);
1172 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1173 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1174 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1175
1176 double shape = 2.0;
1177 double scale = 1.0;
1178
1179 // Create the RNG with the specified range.
1181 x->SetAttribute("Shape", DoubleValue(shape));
1182 x->SetAttribute("Scale", DoubleValue(scale));
1183
1184 // Make this generate antithetic values.
1185 x->SetAttribute("Antithetic", BooleanValue(true));
1186
1187 // Calculate the mean of these values.
1188 double valueMean = Average(x);
1189
1190 // The expected value for the mean is given by
1191 //
1192 // shape * scale
1193 // E[value] = --------------- ,
1194 // shape - 1
1195 //
1196 // where
1197 //
1198 // scale = mean * (shape - 1.0) / shape .
1199 //
1200 double expectedMean = (shape * scale) / (shape - 1.0);
1201
1202 // Test that values have approximately the right mean value.
1203 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1204 expectedMean,
1205 expectedMean * TOLERANCE,
1206 "Wrong mean value.");
1207}
1208
1209/**
1210 * @ingroup rng-tests
1211 * Test case for Weibull distribution random variable stream generator
1212 */
1214{
1215 public:
1216 // Constructor
1218
1219 // Inherited
1220 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1221
1222 private:
1223 // Inherited
1224 void DoRun() override;
1225
1226 /**
1227 * Tolerance for testing rng values against expectation,
1228 * as a fraction of mean value.
1229 */
1230 static constexpr double TOLERANCE{1e-2};
1231};
1232
1234 : TestCaseBase("Weibull Random Variable Stream Generator")
1235{
1236}
1237
1238double
1240{
1241 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1242 auto range = UniformHistogramBins(h, 1, 10, false);
1243
1244 std::vector<double> expected(N_BINS);
1245
1246 // Note that this assumes that p has shape equal to one and scale
1247 // equal to one, which are their default values for this
1248 // distribution.
1249 double a = 1.0;
1250 double b = 1.0;
1251
1252 for (std::size_t i = 0; i < N_BINS; ++i)
1253 {
1254 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1255 expected[i] *= N_MEASUREMENTS;
1256 NS_LOG_INFO("weibull: " << expected[i]);
1257 }
1258
1259 double chiSquared = ChiSquared(h, expected, rng);
1260
1261 gsl_histogram_free(h);
1262 return chiSquared;
1263}
1264
1265void
1267{
1268 NS_LOG_FUNCTION(this);
1270
1271 auto generator = RngGenerator<WeibullRandomVariable>();
1272 const auto sum = ChiSquaredsAverage(&generator, N_RUNS);
1273 const auto maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1274 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1275
1276 const auto scale = 5.0;
1277 const auto shape = 1.0;
1278
1279 // Create the RNG with the specified range.
1281 x->SetAttribute("Scale", DoubleValue(scale));
1282 x->SetAttribute("Shape", DoubleValue(shape));
1283
1284 // Calculate the mean of these values.
1285 const auto measuredMean = Average(x);
1286
1287 // The expected value for the mean of the values returned by a
1288 // Weibull distributed random variable is
1289 //
1290 // E[value] = scale * Gamma(1 + 1 / shape) ,
1291 //
1292 // where Gamma() is the Gamma function. Note that
1293 //
1294 // Gamma(n) = (n - 1)!
1295 //
1296 // if n is a positive integer.
1297 //
1298 // For this test,
1299 //
1300 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1301 // = Gamma(2)
1302 // = (2 - 1)!
1303 // = 1
1304 //
1305 // which means
1306 //
1307 // E[value] = scale .
1308 //
1309 const auto expectedMean = scale;
1310
1311 // Test calculated and expected mean values are identical.
1312 const auto valueMean = x->GetMean();
1313 NS_TEST_ASSERT_MSG_EQ(valueMean, expectedMean, "Wrong calculated mean value.");
1314
1315 // Test that values have approximately the right mean value.
1316 NS_TEST_ASSERT_MSG_EQ_TOL(measuredMean,
1317 expectedMean,
1318 expectedMean * TOLERANCE,
1319 "Wrong measured mean value.");
1320}
1321
1322/**
1323 * @ingroup rng-tests
1324 * Test case for antithetic Weibull distribution random variable stream generator
1325 */
1327{
1328 public:
1329 // Constructor
1331
1332 // Inherited
1333 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1334
1335 private:
1336 // Inherited
1337 void DoRun() override;
1338
1339 /**
1340 * Tolerance for testing rng values against expectation,
1341 * as a fraction of mean value.
1342 */
1343 static constexpr double TOLERANCE{1e-2};
1344};
1345
1347 : TestCaseBase("Antithetic Weibull Random Variable Stream Generator")
1348{
1349}
1350
1351double
1353{
1354 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1355 auto range = UniformHistogramBins(h, 1, 10, false);
1356
1357 std::vector<double> expected(N_BINS);
1358
1359 // Note that this assumes that p has shape equal to one and scale
1360 // equal to one, which are their default values for this
1361 // distribution.
1362 double a = 1.0;
1363 double b = 1.0;
1364
1365 for (std::size_t i = 0; i < N_BINS; ++i)
1366 {
1367 expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1368 expected[i] *= N_MEASUREMENTS;
1369 }
1370
1371 double chiSquared = ChiSquared(h, expected, rng);
1372
1373 gsl_histogram_free(h);
1374 return chiSquared;
1375}
1376
1377void
1379{
1380 NS_LOG_FUNCTION(this);
1382
1383 auto generator = RngGenerator<WeibullRandomVariable>(true);
1384 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1385 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1386 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1387
1388 double scale = 5.0;
1389 double shape = 1.0;
1390
1391 // Create the RNG with the specified range.
1393 x->SetAttribute("Scale", DoubleValue(scale));
1394 x->SetAttribute("Shape", DoubleValue(shape));
1395
1396 // Make this generate antithetic values.
1397 x->SetAttribute("Antithetic", BooleanValue(true));
1398
1399 // Calculate the mean of these values.
1400 double valueMean = Average(x);
1401
1402 // The expected value for the mean of the values returned by a
1403 // Weibull distributed random variable is
1404 //
1405 // E[value] = scale * Gamma(1 + 1 / shape) ,
1406 //
1407 // where Gamma() is the Gamma function. Note that
1408 //
1409 // Gamma(n) = (n - 1)!
1410 //
1411 // if n is a positive integer.
1412 //
1413 // For this test,
1414 //
1415 // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1416 // = Gamma(2)
1417 // = (2 - 1)!
1418 // = 1
1419 //
1420 // which means
1421 //
1422 // E[value] = scale .
1423 //
1424 double expectedMean = scale;
1425
1426 // Test that values have approximately the right mean value.
1427 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1428 expectedMean,
1429 expectedMean * TOLERANCE,
1430 "Wrong mean value.");
1431}
1432
1433/**
1434 * @ingroup rng-tests
1435 * Test case for log-normal distribution random variable stream generator
1436 */
1438{
1439 public:
1440 // Constructor
1442
1443 // Inherited
1444 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1445
1446 private:
1447 // Inherited
1448 void DoRun() override;
1449
1450 /**
1451 * Tolerance for testing rng values against expectation,
1452 * as a fraction of mean value.
1453 */
1454 static constexpr double TOLERANCE{3e-2};
1455};
1456
1458 : TestCaseBase("Log-Normal Random Variable Stream Generator")
1459{
1460}
1461
1462double
1464{
1465 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1466 auto range = UniformHistogramBins(h, 0, 10, false);
1467
1468 std::vector<double> expected(N_BINS);
1469
1470 // Note that this assumes that n has mu equal to zero and sigma
1471 // equal to one, which are their default values for this
1472 // distribution.
1473 double mu = 0.0;
1474 double sigma = 1.0;
1475
1476 for (std::size_t i = 0; i < N_BINS; ++i)
1477 {
1478 expected[i] =
1479 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1480 expected[i] *= N_MEASUREMENTS;
1481 }
1482
1483 double chiSquared = ChiSquared(h, expected, rng);
1484
1485 gsl_histogram_free(h);
1486 return chiSquared;
1487}
1488
1489void
1491{
1492 NS_LOG_FUNCTION(this);
1494
1495 auto generator = RngGenerator<LogNormalRandomVariable>();
1496 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1497 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1498
1499 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1500
1501 double mu = 5.0;
1502 double sigma = 2.0;
1503
1504 // Create the RNG with the specified range.
1506 x->SetAttribute("Mu", DoubleValue(mu));
1507 x->SetAttribute("Sigma", DoubleValue(sigma));
1508
1509 // Calculate the mean of these values.
1510 double valueMean = Average(x);
1511
1512 // The expected value for the mean of the values returned by a
1513 // log-normally distributed random variable is equal to
1514 //
1515 // 2
1516 // mu + sigma / 2
1517 // E[value] = e .
1518 //
1519 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1520
1521 // Test that values have approximately the right mean value.
1522 //
1523 /**
1524 * @todo This test fails sometimes if the required tolerance is less
1525 * than 3%, which may be because there is a bug in the
1526 * implementation or that the mean of this distribution is more
1527 * sensitive to its parameters than the others are.
1528 */
1529 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1530 expectedMean,
1531 expectedMean * TOLERANCE,
1532 "Wrong mean value.");
1533}
1534
1535/**
1536 * @ingroup rng-tests
1537 * Test case for antithetic log-normal distribution random variable stream generator
1538 */
1540{
1541 public:
1542 // Constructor
1544
1545 // Inherited
1546 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1547
1548 private:
1549 // Inherited
1550 void DoRun() override;
1551
1552 /**
1553 * Tolerance for testing rng values against expectation,
1554 * as a fraction of mean value.
1555 */
1556 static constexpr double TOLERANCE{3e-2};
1557};
1558
1560 : TestCaseBase("Antithetic Log-Normal Random Variable Stream Generator")
1561{
1562}
1563
1564double
1566{
1567 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1568 auto range = UniformHistogramBins(h, 0, 10, false);
1569
1570 std::vector<double> expected(N_BINS);
1571
1572 // Note that this assumes that n has mu equal to zero and sigma
1573 // equal to one, which are their default values for this
1574 // distribution.
1575 double mu = 0.0;
1576 double sigma = 1.0;
1577
1578 for (std::size_t i = 0; i < N_BINS; ++i)
1579 {
1580 expected[i] =
1581 gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1582 expected[i] *= N_MEASUREMENTS;
1583 }
1584
1585 double chiSquared = ChiSquared(h, expected, rng);
1586
1587 gsl_histogram_free(h);
1588 return chiSquared;
1589}
1590
1591void
1593{
1594 NS_LOG_FUNCTION(this);
1596
1597 auto generator = RngGenerator<LogNormalRandomVariable>(true);
1598 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1599 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1600 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1601
1602 double mu = 5.0;
1603 double sigma = 2.0;
1604
1605 // Create the RNG with the specified range.
1607 x->SetAttribute("Mu", DoubleValue(mu));
1608 x->SetAttribute("Sigma", DoubleValue(sigma));
1609
1610 // Make this generate antithetic values.
1611 x->SetAttribute("Antithetic", BooleanValue(true));
1612
1613 // Calculate the mean of these values.
1614 double valueMean = Average(x);
1615
1616 // The expected value for the mean of the values returned by a
1617 // log-normally distributed random variable is equal to
1618 //
1619 // 2
1620 // mu + sigma / 2
1621 // E[value] = e .
1622 //
1623 double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1624
1625 // Test that values have approximately the right mean value.
1626 //
1627 /**
1628 * @todo This test fails sometimes if the required tolerance is less
1629 * than 3%, which may be because there is a bug in the
1630 * implementation or that the mean of this distribution is more
1631 * sensitive to its parameters than the others are.
1632 */
1633 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1634 expectedMean,
1635 expectedMean * TOLERANCE,
1636 "Wrong mean value.");
1637}
1638
1639/**
1640 * @ingroup rng-tests
1641 * Test case for gamma distribution random variable stream generator
1642 */
1644{
1645 public:
1646 // Constructor
1647 GammaTestCase();
1648
1649 // Inherited
1650 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1651
1652 private:
1653 // Inherited
1654 void DoRun() override;
1655
1656 /**
1657 * Tolerance for testing rng values against expectation,
1658 * as a fraction of mean value.
1659 */
1660 static constexpr double TOLERANCE{1e-2};
1661};
1662
1664 : TestCaseBase("Gamma Random Variable Stream Generator")
1665{
1666}
1667
1668double
1670{
1671 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1672 auto range = UniformHistogramBins(h, 0, 10, false);
1673
1674 std::vector<double> expected(N_BINS);
1675
1676 // Note that this assumes that n has alpha equal to one and beta
1677 // equal to one, which are their default values for this
1678 // distribution.
1679 double alpha = 1.0;
1680 double beta = 1.0;
1681
1682 for (std::size_t i = 0; i < N_BINS; ++i)
1683 {
1684 expected[i] =
1685 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1686 expected[i] *= N_MEASUREMENTS;
1687 }
1688
1689 double chiSquared = ChiSquared(h, expected, rng);
1690
1691 gsl_histogram_free(h);
1692 return chiSquared;
1693}
1694
1695void
1697{
1698 NS_LOG_FUNCTION(this);
1700
1701 auto generator = RngGenerator<GammaRandomVariable>();
1702 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1703 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1704 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1705
1706 double alpha = 5.0;
1707 double beta = 2.0;
1708
1709 // Create the RNG with the specified range.
1711 x->SetAttribute("Alpha", DoubleValue(alpha));
1712 x->SetAttribute("Beta", DoubleValue(beta));
1713
1714 // Calculate the mean of these values.
1715 double valueMean = Average(x);
1716
1717 // The expected value for the mean of the values returned by a
1718 // gammaly distributed random variable is equal to
1719 //
1720 // E[value] = alpha * beta .
1721 //
1722 double expectedMean = alpha * beta;
1723
1724 // Test that values have approximately the right mean value.
1725 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1726 expectedMean,
1727 expectedMean * TOLERANCE,
1728 "Wrong mean value.");
1729}
1730
1731/**
1732 * @ingroup rng-tests
1733 * Test case for antithetic gamma distribution random variable stream generator
1734 */
1736{
1737 public:
1738 // Constructor
1740
1741 // Inherited
1742 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1743
1744 private:
1745 // Inherited
1746 void DoRun() override;
1747
1748 /**
1749 * Tolerance for testing rng values against expectation,
1750 * as a fraction of mean value.
1751 */
1752 static constexpr double TOLERANCE{1e-2};
1753};
1754
1756 : TestCaseBase("Antithetic Gamma Random Variable Stream Generator")
1757{
1758}
1759
1760double
1762{
1763 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1764 auto range = UniformHistogramBins(h, 0, 10, false);
1765
1766 std::vector<double> expected(N_BINS);
1767
1768 // Note that this assumes that n has alpha equal to one and beta
1769 // equal to one, which are their default values for this
1770 // distribution.
1771 double alpha = 1.0;
1772 double beta = 1.0;
1773
1774 for (std::size_t i = 0; i < N_BINS; ++i)
1775 {
1776 expected[i] =
1777 gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1778 expected[i] *= N_MEASUREMENTS;
1779 }
1780
1781 double chiSquared = ChiSquared(h, expected, rng);
1782
1783 gsl_histogram_free(h);
1784 return chiSquared;
1785}
1786
1787void
1789{
1790 NS_LOG_FUNCTION(this);
1792
1793 auto generator = RngGenerator<GammaRandomVariable>(true);
1794 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1795 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1796 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1797
1798 double alpha = 5.0;
1799 double beta = 2.0;
1800
1801 // Create the RNG with the specified range.
1803
1804 // Make this generate antithetic values.
1805 x->SetAttribute("Antithetic", BooleanValue(true));
1806
1807 x->SetAttribute("Alpha", DoubleValue(alpha));
1808 x->SetAttribute("Beta", DoubleValue(beta));
1809
1810 // Calculate the mean of these values.
1811 double valueMean = Average(x);
1812
1813 // The expected value for the mean of the values returned by a
1814 // gammaly distributed random variable is equal to
1815 //
1816 // E[value] = alpha * beta .
1817 //
1818 double expectedMean = alpha * beta;
1819
1820 // Test that values have approximately the right mean value.
1821 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1822 expectedMean,
1823 expectedMean * TOLERANCE,
1824 "Wrong mean value.");
1825}
1826
1827/**
1828 * @ingroup rng-tests
1829 * Test case for Erlang distribution random variable stream generator
1830 */
1832{
1833 public:
1834 // Constructor
1836
1837 // Inherited
1838 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1839
1840 private:
1841 // Inherited
1842 void DoRun() override;
1843
1844 /**
1845 * Tolerance for testing rng values against expectation,
1846 * as a fraction of mean value.
1847 */
1848 static constexpr double TOLERANCE{1e-2};
1849};
1850
1852 : TestCaseBase("Erlang Random Variable Stream Generator")
1853{
1854}
1855
1856double
1858{
1859 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1860 auto range = UniformHistogramBins(h, 0, 10, false);
1861
1862 std::vector<double> expected(N_BINS);
1863
1864 // Note that this assumes that n has k equal to one and lambda
1865 // equal to one, which are their default values for this
1866 // distribution.
1867 uint32_t k = 1;
1868 double lambda = 1.0;
1869
1870 // Note that Erlang distribution is equal to the gamma distribution
1871 // when k is an integer, which is why the gamma distribution's cdf
1872 // function can be used here.
1873 for (std::size_t i = 0; i < N_BINS; ++i)
1874 {
1875 expected[i] =
1876 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1877 expected[i] *= N_MEASUREMENTS;
1878 }
1879
1880 double chiSquared = ChiSquared(h, expected, rng);
1881
1882 gsl_histogram_free(h);
1883 return chiSquared;
1884}
1885
1886void
1888{
1889 NS_LOG_FUNCTION(this);
1891
1892 auto generator = RngGenerator<ErlangRandomVariable>();
1893 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1894 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1895 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1896
1897 uint32_t k = 5;
1898 double lambda = 2.0;
1899
1900 // Create the RNG with the specified range.
1902 x->SetAttribute("K", IntegerValue(k));
1903 x->SetAttribute("Lambda", DoubleValue(lambda));
1904
1905 // Calculate the mean of these values.
1906 double valueMean = Average(x);
1907
1908 // The expected value for the mean of the values returned by a
1909 // Erlangly distributed random variable is equal to
1910 //
1911 // E[value] = k * lambda .
1912 //
1913 double expectedMean = k * lambda;
1914
1915 // Test that values have approximately the right mean value.
1916 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1917 expectedMean,
1918 expectedMean * TOLERANCE,
1919 "Wrong mean value.");
1920}
1921
1922/**
1923 * @ingroup rng-tests
1924 * Test case for antithetic Erlang distribution random variable stream generator
1925 */
1927{
1928 public:
1929 // Constructor
1931
1932 // Inherited
1933 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1934
1935 private:
1936 // Inherited
1937 void DoRun() override;
1938
1939 /**
1940 * Tolerance for testing rng values against expectation,
1941 * as a fraction of mean value.
1942 */
1943 static constexpr double TOLERANCE{1e-2};
1944};
1945
1947 : TestCaseBase("Antithetic Erlang Random Variable Stream Generator")
1948{
1949}
1950
1951double
1953{
1954 gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1955 auto range = UniformHistogramBins(h, 0, 10, false);
1956
1957 std::vector<double> expected(N_BINS);
1958
1959 // Note that this assumes that n has k equal to one and lambda
1960 // equal to one, which are their default values for this
1961 // distribution.
1962 uint32_t k = 1;
1963 double lambda = 1.0;
1964
1965 // Note that Erlang distribution is equal to the gamma distribution
1966 // when k is an integer, which is why the gamma distribution's cdf
1967 // function can be used here.
1968 for (std::size_t i = 0; i < N_BINS; ++i)
1969 {
1970 expected[i] =
1971 gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1972 expected[i] *= N_MEASUREMENTS;
1973 }
1974
1975 double chiSquared = ChiSquared(h, expected, rng);
1976
1977 gsl_histogram_free(h);
1978 return chiSquared;
1979}
1980
1981void
1983{
1984 NS_LOG_FUNCTION(this);
1986
1987 auto generator = RngGenerator<ErlangRandomVariable>(true);
1988 double sum = ChiSquaredsAverage(&generator, N_RUNS);
1989 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1990 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1991
1992 uint32_t k = 5;
1993 double lambda = 2.0;
1994
1995 // Create the RNG with the specified range.
1997
1998 // Make this generate antithetic values.
1999 x->SetAttribute("Antithetic", BooleanValue(true));
2000
2001 x->SetAttribute("K", IntegerValue(k));
2002 x->SetAttribute("Lambda", DoubleValue(lambda));
2003
2004 // Calculate the mean of these values.
2005 double valueMean = Average(x);
2006
2007 // The expected value for the mean of the values returned by a
2008 // Erlangly distributed random variable is equal to
2009 //
2010 // E[value] = k * lambda .
2011 //
2012 double expectedMean = k * lambda;
2013
2014 // Test that values have approximately the right mean value.
2015 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2016 expectedMean,
2017 expectedMean * TOLERANCE,
2018 "Wrong mean value.");
2019}
2020
2021/**
2022 * @ingroup rng-tests
2023 * Test case for Zipf distribution random variable stream generator
2024 */
2026{
2027 public:
2028 // Constructor
2029 ZipfTestCase();
2030
2031 private:
2032 // Inherited
2033 void DoRun() override;
2034
2035 /**
2036 * Tolerance for testing rng values against expectation,
2037 * as a fraction of mean value.
2038 */
2039 static constexpr double TOLERANCE{1e-2};
2040};
2041
2043 : TestCaseBase("Zipf Random Variable Stream Generator")
2044{
2045}
2046
2047void
2049{
2050 NS_LOG_FUNCTION(this);
2052
2053 uint32_t n = 1;
2054 double alpha = 2.0;
2055
2056 // Create the RNG with the specified range.
2058 x->SetAttribute("N", IntegerValue(n));
2059 x->SetAttribute("Alpha", DoubleValue(alpha));
2060
2061 // Calculate the mean of these values.
2062 double valueMean = Average(x);
2063
2064 // The expected value for the mean of the values returned by a
2065 // Zipfly distributed random variable is equal to
2066 //
2067 // H
2068 // N, alpha - 1
2069 // E[value] = ---------------
2070 // H
2071 // N, alpha
2072 //
2073 // where
2074 //
2075 // N
2076 // ---
2077 // \ -alpha
2078 // H = / m .
2079 // N, alpha ---
2080 // m=1
2081 //
2082 // For this test,
2083 //
2084 // -(alpha - 1)
2085 // 1
2086 // E[value] = ---------------
2087 // -alpha
2088 // 1
2089 //
2090 // = 1 .
2091 //
2092 double expectedMean = 1.0;
2093
2094 // Test that values have approximately the right mean value.
2095 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2096 expectedMean,
2097 expectedMean * TOLERANCE,
2098 "Wrong mean value.");
2099}
2100
2101/**
2102 * @ingroup rng-tests
2103 * Test case for antithetic Zipf distribution random variable stream generator
2104 */
2106{
2107 public:
2108 // Constructor
2110
2111 private:
2112 // Inherited
2113 void DoRun() override;
2114
2115 /**
2116 * Tolerance for testing rng values against expectation,
2117 * as a fraction of mean value.
2118 */
2119 static constexpr double TOLERANCE{1e-2};
2120};
2121
2123 : TestCaseBase("Antithetic Zipf Random Variable Stream Generator")
2124{
2125}
2126
2127void
2129{
2130 NS_LOG_FUNCTION(this);
2132
2133 uint32_t n = 1;
2134 double alpha = 2.0;
2135
2136 // Create the RNG with the specified range.
2138 x->SetAttribute("N", IntegerValue(n));
2139 x->SetAttribute("Alpha", DoubleValue(alpha));
2140
2141 // Make this generate antithetic values.
2142 x->SetAttribute("Antithetic", BooleanValue(true));
2143
2144 // Calculate the mean of these values.
2145 double valueMean = Average(x);
2146
2147 // The expected value for the mean of the values returned by a
2148 // Zipfly distributed random variable is equal to
2149 //
2150 // H
2151 // N, alpha - 1
2152 // E[value] = ---------------
2153 // H
2154 // N, alpha
2155 //
2156 // where
2157 //
2158 // N
2159 // ---
2160 // \ -alpha
2161 // H = / m .
2162 // N, alpha ---
2163 // m=1
2164 //
2165 // For this test,
2166 //
2167 // -(alpha - 1)
2168 // 1
2169 // E[value] = ---------------
2170 // -alpha
2171 // 1
2172 //
2173 // = 1 .
2174 //
2175 double expectedMean = 1.0;
2176
2177 // Test that values have approximately the right mean value.
2178 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2179 expectedMean,
2180 expectedMean * TOLERANCE,
2181 "Wrong mean value.");
2182}
2183
2184/**
2185 * @ingroup rng-tests
2186 * Test case for Zeta distribution random variable stream generator
2187 */
2189{
2190 public:
2191 // Constructor
2192 ZetaTestCase();
2193
2194 private:
2195 // Inherited
2196 void DoRun() override;
2197
2198 /**
2199 * Tolerance for testing rng values against expectation,
2200 * as a fraction of mean value.
2201 */
2202 static constexpr double TOLERANCE{1e-2};
2203};
2204
2206 : TestCaseBase("Zeta Random Variable Stream Generator")
2207{
2208}
2209
2210void
2212{
2213 NS_LOG_FUNCTION(this);
2215
2216 double alpha = 5.0;
2217
2218 // Create the RNG with the specified range.
2220 x->SetAttribute("Alpha", DoubleValue(alpha));
2221
2222 // Calculate the mean of these values.
2223 double valueMean = Average(x);
2224
2225 // The expected value for the mean of the values returned by a
2226 // zetaly distributed random variable is equal to
2227 //
2228 // zeta(alpha - 1)
2229 // E[value] = --------------- for alpha > 2 ,
2230 // zeta(alpha)
2231 //
2232 // where zeta(alpha) is the Riemann zeta function.
2233 //
2234 // There are no simple analytic forms for the Riemann zeta function,
2235 // which is why the gsl library is used in this test to calculate
2236 // the known mean of the values.
2237 double expectedMean =
2238 gsl_sf_zeta_int(static_cast<int>(alpha - 1)) / gsl_sf_zeta_int(static_cast<int>(alpha));
2239
2240 // Test that values have approximately the right mean value.
2241 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2242 expectedMean,
2243 expectedMean * TOLERANCE,
2244 "Wrong mean value.");
2245}
2246
2247/**
2248 * @ingroup rng-tests
2249 * Test case for antithetic Zeta distribution random variable stream generator
2250 */
2252{
2253 public:
2254 // Constructor
2256
2257 private:
2258 // Inherited
2259 void DoRun() override;
2260
2261 /**
2262 * Tolerance for testing rng values against expectation,
2263 * as a fraction of mean value.
2264 */
2265 static constexpr double TOLERANCE{1e-2};
2266};
2267
2269 : TestCaseBase("Antithetic Zeta Random Variable Stream Generator")
2270{
2271}
2272
2273void
2275{
2276 NS_LOG_FUNCTION(this);
2278
2279 double alpha = 5.0;
2280
2281 // Create the RNG with the specified range.
2283 x->SetAttribute("Alpha", DoubleValue(alpha));
2284
2285 // Make this generate antithetic values.
2286 x->SetAttribute("Antithetic", BooleanValue(true));
2287
2288 // Calculate the mean of these values.
2289 double valueMean = Average(x);
2290
2291 // The expected value for the mean of the values returned by a
2292 // zetaly distributed random variable is equal to
2293 //
2294 // zeta(alpha - 1)
2295 // E[value] = --------------- for alpha > 2 ,
2296 // zeta(alpha)
2297 //
2298 // where zeta(alpha) is the Riemann zeta function.
2299 //
2300 // There are no simple analytic forms for the Riemann zeta function,
2301 // which is why the gsl library is used in this test to calculate
2302 // the known mean of the values.
2303 double expectedMean =
2304 gsl_sf_zeta_int(static_cast<int>(alpha) - 1) / gsl_sf_zeta_int(static_cast<int>(alpha));
2305
2306 // Test that values have approximately the right mean value.
2307 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2308 expectedMean,
2309 expectedMean * TOLERANCE,
2310 "Wrong mean value.");
2311}
2312
2313/**
2314 * @ingroup rng-tests
2315 * Test case for deterministic random variable stream generator
2316 */
2318{
2319 public:
2320 // Constructor
2322
2323 private:
2324 // Inherited
2325 void DoRun() override;
2326
2327 /** Tolerance for testing rng values against expectation. */
2328 static constexpr double TOLERANCE{1e-8};
2329};
2330
2332 : TestCaseBase("Deterministic Random Variable Stream Generator")
2333{
2334}
2335
2336void
2338{
2339 NS_LOG_FUNCTION(this);
2341
2343
2344 // The following array should give the sequence
2345 //
2346 // 4, 4, 7, 7, 10, 10 .
2347 //
2348 double array1[] = {4, 4, 7, 7, 10, 10};
2349 std::size_t count1 = 6;
2350 s->SetValueArray(array1, count1);
2351
2352 double value;
2353
2354 // Test that the first sequence is correct.
2355 value = s->GetValue();
2356 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2357 value = s->GetValue();
2358 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2359 value = s->GetValue();
2360 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2361 value = s->GetValue();
2362 NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2363 value = s->GetValue();
2364 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2365 value = s->GetValue();
2366 NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2367
2368 // The following array should give the sequence
2369 //
2370 // 1000, 2000, 7, 7 .
2371 //
2372 double array2[] = {1000, 2000, 3000, 4000};
2373 std::size_t count2 = 4;
2374 s->SetValueArray(array2, count2);
2375
2376 // Test that the second sequence is correct.
2377 value = s->GetValue();
2378 NS_TEST_ASSERT_MSG_EQ_TOL(value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2379 value = s->GetValue();
2380 NS_TEST_ASSERT_MSG_EQ_TOL(value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2381 value = s->GetValue();
2382 NS_TEST_ASSERT_MSG_EQ_TOL(value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2383 value = s->GetValue();
2384 NS_TEST_ASSERT_MSG_EQ_TOL(value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2385 value = s->GetValue();
2386}
2387
2388/**
2389 * @ingroup rng-tests
2390 * Test case for empirical distribution random variable stream generator
2391 */
2393{
2394 public:
2395 // Constructor
2397
2398 private:
2399 // Inherited
2400 void DoRun() override;
2401
2402 /**
2403 * Tolerance for testing rng values against expectation,
2404 * as a fraction of mean value.
2405 */
2406 static constexpr double TOLERANCE{1e-2};
2407};
2408
2410 : TestCaseBase("Empirical Random Variable Stream Generator")
2411{
2412}
2413
2414void
2416{
2417 NS_LOG_FUNCTION(this);
2419
2420 // Create the RNG with a uniform distribution between 0 and 10.
2422 x->SetInterpolate(false);
2423 x->CDF(0.0, 0.0);
2424 x->CDF(5.0, 0.25);
2425 x->CDF(10.0, 1.0);
2426
2427 // Check that only the correct values are returned
2428 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2429 {
2430 double value = x->GetValue();
2431 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2432 true,
2433 "Incorrect value returned, expected only 5 or 10.");
2434 }
2435
2436 // Calculate the mean of the sampled values.
2437 double valueMean = Average(x);
2438
2439 // The expected distribution with sampled values is
2440 // Value Probability
2441 // 5 25%
2442 // 10 75%
2443 //
2444 // The expected mean is
2445 //
2446 // E[value] = 5 * 25% + 10 * 75% = 8.75
2447 //
2448 // Test that values have approximately the right mean value.
2449 double expectedMean = 8.75;
2450 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2451 expectedMean,
2452 expectedMean * TOLERANCE,
2453 "Wrong mean value.");
2454
2455 // Calculate the mean of the interpolated values.
2456 x->SetInterpolate(true);
2457 valueMean = Average(x);
2458
2459 // The expected distribution (with interpolation) is
2460 // Bin Probability
2461 // [0, 5) 25%
2462 // [5, 10) 75%
2463 //
2464 // Each bin is uniformly sampled, so the average of the samples in the
2465 // bin is the center of the bin.
2466 //
2467 // The expected mean is
2468 //
2469 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2470 //
2471 expectedMean = 6.25;
2472
2473 // Test that values have approximately the right mean value.
2474 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2475 expectedMean,
2476 expectedMean * TOLERANCE,
2477 "Wrong mean value.");
2478
2479 // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2481 y->SetInterpolate(false);
2482 y->CDF(-1.0, 0.0);
2483 y->CDF(0.0, 0.5);
2484 y->CDF(1.0, 1.0);
2485 NS_TEST_ASSERT_MSG_LT(y->GetValue(), 2, "Empirical variable with negative domain");
2486}
2487
2488/**
2489 * @ingroup rng-tests
2490 * Test case for antithetic empirical distribution random variable stream generator
2491 */
2493{
2494 public:
2495 // Constructor
2497
2498 private:
2499 // Inherited
2500 void DoRun() override;
2501
2502 /**
2503 * Tolerance for testing rng values against expectation,
2504 * as a fraction of mean value.
2505 */
2506 static constexpr double TOLERANCE{1e-2};
2507};
2508
2510 : TestCaseBase("EmpiricalAntithetic Random Variable Stream Generator")
2511{
2512}
2513
2514void
2516{
2517 NS_LOG_FUNCTION(this);
2519
2520 // Create the RNG with a uniform distribution between 0 and 10.
2522 x->SetInterpolate(false);
2523 x->CDF(0.0, 0.0);
2524 x->CDF(5.0, 0.25);
2525 x->CDF(10.0, 1.0);
2526
2527 // Make this generate antithetic values.
2528 x->SetAttribute("Antithetic", BooleanValue(true));
2529
2530 // Check that only the correct values are returned
2531 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2532 {
2533 double value = x->GetValue();
2534 NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2535 true,
2536 "Incorrect value returned, expected only 5 or 10.");
2537 }
2538
2539 // Calculate the mean of these values.
2540 double valueMean = Average(x);
2541 // Expected
2542 // E[value] = 5 * 25% + 10 * 75% = 8.75
2543 double expectedMean = 8.75;
2544 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2545 expectedMean,
2546 expectedMean * TOLERANCE,
2547 "Wrong mean value.");
2548
2549 // Check interpolated sampling
2550 x->SetInterpolate(true);
2551 valueMean = Average(x);
2552
2553 // The expected value for the mean of the values returned by this
2554 // empirical distribution with interpolation is
2555 //
2556 // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2557 //
2558 expectedMean = 6.25;
2559
2560 // Test that values have approximately the right mean value.
2561 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2562 expectedMean,
2563 expectedMean * TOLERANCE,
2564 "Wrong mean value.");
2565}
2566
2567/**
2568 * @ingroup rng-tests
2569 * Test case for caching of Normal RV parameters (see issue #302)
2570 */
2572{
2573 public:
2574 // Constructor
2576
2577 private:
2578 // Inherited
2579 void DoRun() override;
2580};
2581
2583 : TestCaseBase("NormalRandomVariable caching of parameters")
2584{
2585}
2586
2587void
2589{
2590 NS_LOG_FUNCTION(this);
2592
2594 double v1 = n->GetValue(-10, 1, 10); // Mean -10, variance 1, bounded to [-20,0]
2595 double v2 = n->GetValue(10, 1, 10); // Mean 10, variance 1, bounded to [0,20]
2596
2597 NS_TEST_ASSERT_MSG_LT(v1, 0, "Incorrect value returned, expected < 0");
2598 NS_TEST_ASSERT_MSG_GT(v2, 0, "Incorrect value returned, expected > 0");
2599}
2600
2601/**
2602 * @ingroup rng-tests
2603 * Test case for bernoulli distribution random variable stream generator
2604 */
2606{
2607 public:
2608 // Constructor
2610
2611 // Inherited
2612 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2613
2614 private:
2615 // Inherited
2616 void DoRun() override;
2617
2618 /** Tolerance for testing rng values against expectation, in rms. */
2619 static constexpr double TOLERANCE{5};
2620};
2621
2623 : TestCaseBase("Bernoulli Random Variable Stream Generator")
2624{
2625}
2626
2627double
2629{
2630 gsl_histogram* h = gsl_histogram_alloc(2);
2631 auto range = UniformHistogramBins(h, 0, 1);
2632
2633 double p = 0.5;
2634 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2635
2636 double chiSquared = ChiSquared(h, expected, rng);
2637
2638 gsl_histogram_free(h);
2639 return chiSquared;
2640}
2641
2642void
2644{
2645 NS_LOG_FUNCTION(this);
2647
2648 auto generator = RngGenerator<BernoulliRandomVariable>();
2649 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2650 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2651 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2652
2653 double probability = 0.5;
2654
2655 // Create the RNG with the specified range.
2657 x->SetAttribute("Probability", DoubleValue(probability));
2658
2659 // Calculate the mean of these values.
2660 double mean = probability;
2661 double valueMean = Average(x);
2662 double expectedMean = mean;
2663 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2664
2665 // Test that values have approximately the right mean value.
2666 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2667 expectedMean,
2668 expectedRms * TOLERANCE,
2669 "Wrong mean value.");
2670}
2671
2672/**
2673 * @ingroup rng-tests
2674 * Test case for antithetic bernoulli distribution random variable stream generator
2675 */
2677{
2678 public:
2679 // Constructor
2681
2682 // Inherited
2683 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2684
2685 private:
2686 // Inherited
2687 void DoRun() override;
2688
2689 /** Tolerance for testing rng values against expectation, in rms. */
2690 static constexpr double TOLERANCE{5};
2691};
2692
2694 : TestCaseBase("Antithetic Bernoulli Random Variable Stream Generator")
2695{
2696}
2697
2698double
2700{
2701 gsl_histogram* h = gsl_histogram_alloc(2);
2702 auto range = UniformHistogramBins(h, 0, 1);
2703
2704 double p = 0.5;
2705 std::vector<double> expected = {N_MEASUREMENTS * (1 - p), N_MEASUREMENTS * p};
2706
2707 double chiSquared = ChiSquared(h, expected, rng);
2708
2709 gsl_histogram_free(h);
2710 return chiSquared;
2711}
2712
2713void
2715{
2716 NS_LOG_FUNCTION(this);
2718
2719 auto generator = RngGenerator<BernoulliRandomVariable>(true);
2720 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2721 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, 1);
2722 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2723
2724 double probability = 0.5;
2725
2726 // Create the RNG with the specified range.
2728 x->SetAttribute("Probability", DoubleValue(probability));
2729
2730 // Make this generate antithetic values.
2731 x->SetAttribute("Antithetic", BooleanValue(true));
2732
2733 // Calculate the mean of these values.
2734 double mean = probability;
2735 double valueMean = Average(x);
2736 double expectedMean = mean;
2737 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2738
2739 // Test that values have approximately the right mean value.
2740 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2741 expectedMean,
2742 expectedRms * TOLERANCE,
2743 "Wrong mean value.");
2744}
2745
2746/**
2747 * @ingroup rng-tests
2748 * Test case for binomial distribution random variable stream generator
2749 */
2751{
2752 public:
2753 // Constructor
2755
2756 // Inherited
2757 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2758
2759 private:
2760 // Inherited
2761 void DoRun() override;
2762
2763 /** Tolerance for testing rng values against expectation, in rms. */
2764 static constexpr double TOLERANCE{5};
2765};
2766
2768 : TestCaseBase("Binomial Random Variable Stream Generator")
2769{
2770}
2771
2772double
2774{
2775 uint32_t trials = 10;
2776 double probability = 0.5;
2777
2778 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2779 auto range = UniformHistogramBins(h, 0, trials);
2780
2781 std::vector<double> expected(trials + 1);
2782 for (std::size_t i = 0; i < trials + 1; ++i)
2783 {
2784 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2785 }
2786
2787 double chiSquared = ChiSquared(h, expected, rng);
2788
2789 gsl_histogram_free(h);
2790 return chiSquared;
2791}
2792
2793void
2795{
2796 NS_LOG_FUNCTION(this);
2798
2799 uint32_t trials = 10;
2800 double probability = 0.5;
2801
2802 auto generator = RngGenerator<BinomialRandomVariable>();
2803 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2804 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2805 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2806
2807 // Create the RNG with the specified range.
2809 x->SetAttribute("Trials", IntegerValue(trials));
2810 x->SetAttribute("Probability", DoubleValue(probability));
2811
2812 // Calculate the mean of these values.
2813 double mean = trials * probability;
2814 double valueMean = Average(x);
2815 double expectedMean = mean;
2816 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2817
2818 // Test that values have approximately the right mean value.
2819 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2820 expectedMean,
2821 expectedRms * TOLERANCE,
2822 "Wrong mean value.");
2823}
2824
2825/**
2826 * @ingroup rng-tests
2827 * Test case for antithetic binomial distribution random variable stream generator
2828 */
2830{
2831 public:
2832 // Constructor
2834
2835 // Inherited
2836 double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
2837
2838 private:
2839 // Inherited
2840 void DoRun() override;
2841
2842 /** Tolerance for testing rng values against expectation, in rms. */
2843 static constexpr double TOLERANCE{5};
2844};
2845
2847 : TestCaseBase("Antithetic Binomial Random Variable Stream Generator")
2848{
2849}
2850
2851double
2853{
2854 uint32_t trials = 10;
2855 double probability = 0.5;
2856
2857 gsl_histogram* h = gsl_histogram_alloc(trials + 1);
2858 auto range = UniformHistogramBins(h, 0, trials);
2859
2860 std::vector<double> expected(trials + 1);
2861 for (std::size_t i = 0; i < trials + 1; ++i)
2862 {
2863 expected[i] = N_MEASUREMENTS * gsl_ran_binomial_pdf(i, probability, trials);
2864 }
2865
2866 double chiSquared = ChiSquared(h, expected, rng);
2867
2868 gsl_histogram_free(h);
2869 return chiSquared;
2870}
2871
2872void
2874{
2875 NS_LOG_FUNCTION(this);
2877
2878 uint32_t trials = 10;
2879 double probability = 0.5;
2880
2881 auto generator = RngGenerator<BinomialRandomVariable>(true);
2882 double sum = ChiSquaredsAverage(&generator, N_RUNS);
2883 double maxStatistic = gsl_cdf_chisq_Qinv(0.05, trials);
2884 NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
2885
2886 // Create the RNG with the specified range.
2888 x->SetAttribute("Trials", IntegerValue(trials));
2889 x->SetAttribute("Probability", DoubleValue(probability));
2890
2891 // Make this generate antithetic values.
2892 x->SetAttribute("Antithetic", BooleanValue(true));
2893
2894 // Calculate the mean of these values.
2895 double mean = trials * probability;
2896 double valueMean = Average(x);
2897 double expectedMean = mean;
2898 double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
2899
2900 // Test that values have approximately the right mean value.
2901 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2902 expectedMean,
2903 expectedRms * TOLERANCE,
2904 "Wrong mean value.");
2905}
2906
2907/**
2908 * @ingroup rng-test
2909 * @ingroup tests
2910 *
2911 * @brief Test the Shuffle function
2912 *
2913 * Check that the Shuffle function actually shuffles the elements and does so in a portable way.
2914 */
2916{
2917 public:
2919
2920 private:
2921 void DoRun() override;
2922};
2923
2925 : TestCase("Check correct operation of the Shuffle function")
2926{
2927}
2928
2929void
2931{
2934
2936 rv->SetStream(1);
2937
2938 // test empty vector
2939 std::vector<uint8_t> vec{};
2940
2941 Shuffle(vec.begin(), vec.end(), rv);
2942
2943 NS_TEST_EXPECT_MSG_EQ(vec.empty(), true, "Expected an empty vector");
2944
2945 // test vector with one value
2946 vec.push_back(3);
2947
2948 Shuffle(vec.begin(), vec.end(), rv);
2949
2950 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{3}), true, "Expected vector {3}");
2951
2952 // test vector with two values
2953 vec.push_back(1);
2954
2955 Shuffle(vec.begin(), vec.end(), rv);
2956
2957 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{1, 3}), true, "Expected vector {1, 3}");
2958
2959 // test vector with multiple values
2960 vec.push_back(7);
2961 vec.push_back(2);
2962 vec.push_back(4);
2963 vec.push_back(9);
2964
2965 Shuffle(vec.begin(), vec.end(), rv);
2966
2967 NS_TEST_EXPECT_MSG_EQ((vec == std::vector<uint8_t>{4, 1, 9, 3, 2, 7}),
2968 true,
2969 "Expected vector {4, 1, 9, 3, 2, 7}");
2970}
2971
2972/**
2973 * @ingroup rng-tests
2974 * Test case for laplacian distribution random variable stream generator
2975 */
2977{
2978 public:
2980
2981 private:
2982 void DoRun() override;
2983
2984 /**
2985 * Tolerance for testing rng values against expectation,
2986 * as a fraction of mean value.
2987 */
2988 static constexpr double TOLERANCE{1e-2};
2989};
2990
2992 : TestCaseBase("Laplacian Random Variable Stream Generator")
2993{
2994}
2995
2996void
2998{
2999 NS_LOG_FUNCTION(this);
3001
3002 double mu = -5.0;
3003 double scale = 4.0;
3004 double bound = 20.0;
3005
3006 // Create unbounded RNG with the specified range.
3008 x1->SetAttribute("Location", DoubleValue(mu));
3009 x1->SetAttribute("Scale", DoubleValue(scale));
3010
3011 // Calculate the mean of these values.
3012 auto valueMean = Average(x1);
3013
3014 // Calculate the variance of these values.
3015 auto valueVariance = Variance(x1, valueMean);
3016
3017 // Test that values have approximately the right mean value.
3018 const auto expectedMean = mu;
3019 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3020
3021 // Test that values have approximately the right variance value.
3022 const auto expectedVariance = LaplacianRandomVariable::GetVariance(scale);
3023 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3024 expectedVariance,
3025 TOLERANCE * expectedVariance,
3026 "Wrong variance value.");
3027
3028 // Create bounded RNG with the specified range.
3030 x2->SetAttribute("Location", DoubleValue(mu));
3031 x2->SetAttribute("Scale", DoubleValue(scale));
3032 x2->SetAttribute("Bound", DoubleValue(bound));
3033
3034 // Calculate the mean of these values.
3035 valueMean = Average(x2);
3036
3037 // Test that values have approximately the right mean value.
3038 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3039
3040 // Check that only the correct values are returned
3041 const auto lowerBound = mu - bound;
3042 const auto upperBound = mu + bound;
3043 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
3044 {
3045 const auto value = x2->GetValue();
3046 NS_TEST_EXPECT_MSG_EQ((value >= lowerBound) || (value <= upperBound),
3047 true,
3048 "Value not in expected boundaries.");
3049 }
3050}
3051
3052/**
3053 * @ingroup rng-tests
3054 * Test case for largest extreme value distribution random variable stream generator
3055 */
3057{
3058 public:
3060
3061 private:
3062 void DoRun() override;
3063
3064 /**
3065 * Tolerance for testing rng values against expectation,
3066 * as a fraction of mean value.
3067 */
3068 static constexpr double TOLERANCE{1e-2};
3069};
3070
3072 : TestCaseBase("Largest Extreme Value Random Variable Stream Generator")
3073{
3074}
3075
3076void
3078{
3079 NS_LOG_FUNCTION(this);
3081
3082 double mu = 2.0;
3083 double scale = 1.0;
3084
3085 // Create RNG with the specified range.
3087 x->SetAttribute("Location", DoubleValue(mu));
3088 x->SetAttribute("Scale", DoubleValue(scale));
3089
3090 // Calculate the mean of these values.
3091 auto valueMean = Average(x);
3092
3093 // Calculate the variance of these values.
3094 auto valueVariance = Variance(x, valueMean);
3095
3096 // Test that values have approximately the right mean value.
3097 const auto expectedMean = LargestExtremeValueRandomVariable::GetMean(mu, scale);
3098 NS_TEST_ASSERT_MSG_EQ_TOL(valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
3099
3100 // Test that values have approximately the right variance value.
3101 const auto expectedVariance = LargestExtremeValueRandomVariable::GetVariance(scale);
3102 NS_TEST_ASSERT_MSG_EQ_TOL(valueVariance,
3103 expectedVariance,
3104 TOLERANCE * expectedVariance,
3105 "Wrong variance value.");
3106}
3107
3108/**
3109 * @ingroup rng-tests
3110 * RandomVariableStream test suite, covering all random number variable
3111 * stream generator types.
3112 */
3114{
3115 public:
3116 // Constructor
3118};
3119
3121 : TestSuite("random-variable-stream-generators", Type::UNIT)
3122{
3136 /// @todo This test is currently disabled because it fails sometimes.
3137 /// A possible reason for the failure is that the antithetic code is
3138 /// not implemented properly for this log-normal case.
3139 /*
3140 AddTestCase (new LogNormalAntitheticTestCase);
3141 */
3143 /// @todo This test is currently disabled because it fails sometimes.
3144 /// A possible reason for the failure is that the antithetic code is
3145 /// not implemented properly for this gamma case.
3146 /*
3147 AddTestCase (new GammaAntitheticTestCase);
3148 */
3158 /// Issue #302: NormalRandomVariable produces stale values
3167}
3168
3169static RandomVariableSuite randomVariableSuite; //!< Static variable for test initialization
3170
3171} // namespace RandomVariable
3172
3173} // namespace test
3174
3175} // namespace ns3
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
uint32_t r
return result
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.
Definition ptr.h:67
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
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:293
TestCase(const TestCase &)=delete
Type
Type of test.
Definition test.h:1257
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:491
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.
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.
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.
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:698
#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:133
#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:240
#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:553
#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:863
#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:326
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