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