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