A Discrete-Event Network Simulator
API
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/string.h"
30 #include "ns3/test.h"
31 
32 #include <cmath>
33 #include <ctime>
34 #include <fstream>
35 #include <gsl/gsl_cdf.h>
36 #include <gsl/gsl_histogram.h>
37 #include <gsl/gsl_sf_zeta.h>
38 
39 using namespace ns3;
40 
41 NS_LOG_COMPONENT_DEFINE("RandomVariableStreamGenerators");
42 
43 namespace ns3
44 {
45 
46 namespace test
47 {
48 
49 namespace RandomVariable
50 {
51 
62 class TestCaseBase : public TestCase
63 {
64  public:
66  static const uint32_t N_BINS{50};
68  static const uint32_t N_MEASUREMENTS{1000000};
70  static const uint32_t N_RUNS{5};
71 
76  TestCaseBase(std::string name)
77  : TestCase(name)
78  {
79  }
80 
92  std::vector<double> UniformHistogramBins(gsl_histogram* h,
93  double start,
94  double end,
95  bool underflow = true,
96  bool overflow = true) const
97  {
98  NS_LOG_FUNCTION(this << h << start << end);
99  std::size_t nBins = gsl_histogram_bins(h);
100  double increment = (end - start) / (nBins - 1.);
101  double d = start;
102 
103  std::vector<double> range(nBins + 1);
104 
105  for (auto& r : range)
106  {
107  r = d;
108  d += increment;
109  }
110  if (underflow)
111  {
112  range[0] = -std::numeric_limits<double>::max();
113  }
114  if (overflow)
115  {
116  range[nBins] = std::numeric_limits<double>::max();
117  }
118 
119  gsl_histogram_set_ranges(h, range.data(), nBins + 1);
120  return range;
121  }
122 
129  {
130  NS_LOG_FUNCTION(this << rng);
131  double sum = 0.0;
132  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
133  {
134  double value = rng->GetValue();
135  sum += value;
136  }
137  double valueMean = sum / N_MEASUREMENTS;
138  return valueMean;
139  }
140 
143  {
144  public:
149  virtual Ptr<RandomVariableStream> Create() const = 0;
150  };
151 
157  template <typename RNG>
159  {
160  public:
165  RngGenerator(bool anti = false)
166  : m_anti(anti)
167  {
168  }
169 
170  // Inherited
172  {
173  auto rng = CreateObject<RNG>();
174  rng->SetAttribute("Antithetic", BooleanValue(m_anti));
175  return rng;
176  }
177 
178  private:
180  bool m_anti;
181  };
182 
198  double ChiSquared(gsl_histogram* h,
199  const std::vector<double>& expected,
200  Ptr<RandomVariableStream> rng) const
201  {
202  NS_LOG_FUNCTION(this << h << expected.size() << rng);
203  NS_ASSERT_MSG(gsl_histogram_bins(h) == expected.size(),
204  "Histogram and expected vector have different sizes.");
205 
206  // Sample the rng into the histogram
207  for (std::size_t i = 0; i < N_MEASUREMENTS; ++i)
208  {
209  double value = rng->GetValue();
210  gsl_histogram_increment(h, value);
211  }
212 
213  // Compute the chi square value
214  double chiSquared = 0;
215  std::size_t nBins = gsl_histogram_bins(h);
216  for (std::size_t i = 0; i < nBins; ++i)
217  {
218  double hbin = gsl_histogram_get(h, i);
219  double tmp = hbin - expected[i];
220  tmp *= tmp;
221  tmp /= expected[i];
222  chiSquared += tmp;
223  }
224 
225  return chiSquared;
226  }
227 
258  virtual double ChiSquaredTest(Ptr<RandomVariableStream> rng) const
259  {
260  return 0;
261  }
262 
271  double ChiSquaredsAverage(const RngGeneratorBase* generator, std::size_t nRuns) const
272  {
273  NS_LOG_FUNCTION(this << generator << nRuns);
274 
275  double sum = 0.;
276  for (std::size_t i = 0; i < nRuns; ++i)
277  {
278  auto rng = generator->Create();
279  double result = ChiSquaredTest(rng);
280  sum += result;
281  }
282  sum /= (double)nRuns;
283  return sum;
284  }
285 
318  {
319  if (m_seedSet == false)
320  {
321  uint32_t seed;
322  if (RngSeedManager::GetRun() == 0)
323  {
324  seed = static_cast<uint32_t>(time(nullptr));
325  m_seedSet = true;
326  NS_LOG_DEBUG(
327  "Special run number value of zero; seeding with time of day: " << seed);
328  }
329  else
330  {
331  seed = RngSeedManager::GetSeed();
332  m_seedSet = true;
333  NS_LOG_DEBUG("Using the values seed: " << seed
334  << " and run: " << RngSeedManager::GetRun());
335  }
336  SeedManager::SetSeed(seed);
337  }
338  }
339 
340  private:
342  bool m_seedSet = false;
343 
344 }; // class TestCaseBase
345 
351 {
352  public:
353  // Constructor
354  UniformTestCase();
355 
356  // Inherited
357  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
358 
359  private:
360  // Inherited
361  void DoRun() override;
362 };
363 
365  : TestCaseBase("Uniform Random Variable Stream Generator")
366 {
367 }
368 
369 double
371 {
372  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
373 
374  // Note that this assumes that the range for u is [0,1], which is
375  // the default range for this distribution.
376  gsl_histogram_set_ranges_uniform(h, 0., 1.);
377 
378  std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
379 
380  double chiSquared = ChiSquared(h, expected, rng);
381  gsl_histogram_free(h);
382  return chiSquared;
383 }
384 
385 void
387 {
388  NS_LOG_FUNCTION(this);
390 
391  double confidence = 0.99;
392  double maxStatistic = gsl_cdf_chisq_Pinv(confidence, (N_BINS - 1));
393  NS_LOG_DEBUG("Chi square required at " << confidence << " confidence for " << N_BINS
394  << " bins is " << maxStatistic);
395 
396  double result = maxStatistic;
397  // If chi-squared test fails, re-try it up to N_RUNS times
398  for (uint32_t i = 0; i < N_RUNS; ++i)
399  {
400  Ptr<UniformRandomVariable> rng = CreateObject<UniformRandomVariable>();
401  result = ChiSquaredTest(rng);
402  NS_LOG_DEBUG("Chi square result is " << result);
403  if (result < maxStatistic)
404  {
405  break;
406  }
407  }
408 
409  NS_TEST_ASSERT_MSG_LT(result, maxStatistic, "Chi-squared statistic out of range");
410 
411  double min = 0.0;
412  double max = 10.0;
413  double value;
414 
415  // Create the RNG with the specified range.
416  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable>();
417 
418  x->SetAttribute("Min", DoubleValue(min));
419  x->SetAttribute("Max", DoubleValue(max));
420 
421  // Test that values are always within the range:
422  //
423  // [min, max)
424  //
425  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
426  {
427  value = x->GetValue();
428  NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
429  NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
430  }
431 
432  // Boundary checking on GetInteger; should be [min,max]; from bug 1964
433  static const uint32_t UNIFORM_INTEGER_MIN{0};
434  static const uint32_t UNIFORM_INTEGER_MAX{4294967295U};
435  // [0,0] should return 0
436  uint32_t intValue;
437  intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN);
438  NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MIN, "Uniform RV GetInteger boundary testing");
439  // [UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX] should return UNIFORM_INTEGER_MAX
440  intValue = x->GetInteger(UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX);
441  NS_TEST_ASSERT_MSG_EQ(intValue, UNIFORM_INTEGER_MAX, "Uniform RV GetInteger boundary testing");
442  // [0,1] should return mix of 0 or 1
443  intValue = 0;
444  for (int i = 0; i < 20; i++)
445  {
446  intValue += x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN + 1);
447  }
448  NS_TEST_ASSERT_MSG_GT(intValue, 0, "Uniform RV GetInteger boundary testing");
449  NS_TEST_ASSERT_MSG_LT(intValue, 20, "Uniform RV GetInteger boundary testing");
450  // [MAX-1,MAX] should return mix of MAX-1 or MAX
451  uint32_t count = 0;
452  for (int i = 0; i < 20; i++)
453  {
454  intValue = x->GetInteger(UNIFORM_INTEGER_MAX - 1, UNIFORM_INTEGER_MAX);
455  if (intValue == UNIFORM_INTEGER_MAX)
456  {
457  count++;
458  }
459  }
460  NS_TEST_ASSERT_MSG_GT(count, 0, "Uniform RV GetInteger boundary testing");
461  NS_TEST_ASSERT_MSG_LT(count, 20, "Uniform RV GetInteger boundary testing");
462  // multiple [0,UNIFORM_INTEGER_MAX] should return non-zero
463  intValue = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
464  uint32_t intValue2 = x->GetInteger(UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
465  NS_TEST_ASSERT_MSG_GT(intValue + intValue2, 0, "Uniform RV GetInteger boundary testing");
466 }
467 
473 {
474  public:
475  // Constructor
477 
478  // Inherited
479  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
480 
481  private:
482  // Inherited
483  void DoRun() override;
484 };
485 
487  : TestCaseBase("Antithetic Uniform Random Variable Stream Generator")
488 {
489 }
490 
491 double
493 {
494  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
495 
496  // Note that this assumes that the range for u is [0,1], which is
497  // the default range for this distribution.
498  gsl_histogram_set_ranges_uniform(h, 0., 1.);
499 
500  std::vector<double> expected(N_BINS, ((double)N_MEASUREMENTS / (double)N_BINS));
501 
502  double chiSquared = ChiSquared(h, expected, rng);
503  gsl_histogram_free(h);
504  return chiSquared;
505 }
506 
507 void
509 {
510  NS_LOG_FUNCTION(this);
512 
513  auto generator = RngGenerator<UniformRandomVariable>(true);
514  double sum = ChiSquaredsAverage(&generator, N_RUNS);
515  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
516  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
517 
518  double min = 0.0;
519  double max = 10.0;
520  double value;
521 
522  // Create the RNG with the specified range.
523  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable>();
524 
525  // Make this generate antithetic values.
526  x->SetAttribute("Antithetic", BooleanValue(true));
527 
528  x->SetAttribute("Min", DoubleValue(min));
529  x->SetAttribute("Max", DoubleValue(max));
530 
531  // Test that values are always within the range:
532  //
533  // [min, max)
534  //
535  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
536  {
537  value = x->GetValue();
538  NS_TEST_ASSERT_MSG_EQ((value >= min), true, "Value less than minimum.");
539  NS_TEST_ASSERT_MSG_LT(value, max, "Value greater than or equal to maximum.");
540  }
541 }
542 
548 {
549  public:
550  // Constructor
552 
553  private:
554  // Inherited
555  void DoRun() override;
556 
558  static constexpr double TOLERANCE{1e-8};
559 };
560 
562  : TestCaseBase("Constant Random Variable Stream Generator")
563 {
564 }
565 
566 void
568 {
569  NS_LOG_FUNCTION(this);
571 
572  Ptr<ConstantRandomVariable> c = CreateObject<ConstantRandomVariable>();
573 
574  double constant;
575 
576  // Test that the constant value can be changed using its attribute.
577  constant = 10.0;
578  c->SetAttribute("Constant", DoubleValue(constant));
579  NS_TEST_ASSERT_MSG_EQ_TOL(c->GetValue(), constant, TOLERANCE, "Constant value changed");
580  c->SetAttribute("Constant", DoubleValue(20.0));
581  NS_TEST_ASSERT_MSG_NE(c->GetValue(), constant, "Constant value not changed");
582 
583  // Test that the constant value does not change.
584  constant = c->GetValue();
585  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
586  {
588  constant,
589  TOLERANCE,
590  "Constant value changed in loop");
591  }
592 }
593 
599 {
600  public:
601  // Constructor
603 
604  private:
605  // Inherited
606  void DoRun() override;
607 
609  static constexpr double TOLERANCE{1e-8};
610 };
611 
613  : TestCaseBase("Sequential Random Variable Stream Generator")
614 {
615 }
616 
617 void
619 {
620  NS_LOG_FUNCTION(this);
622 
623  Ptr<SequentialRandomVariable> s = CreateObject<SequentialRandomVariable>();
624 
625  // The following four attributes should give the sequence
626  //
627  // 4, 4, 7, 7, 10, 10
628  //
629  s->SetAttribute("Min", DoubleValue(4));
630  s->SetAttribute("Max", DoubleValue(11));
631  s->SetAttribute("Increment", StringValue("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
632  s->SetAttribute("Consecutive", IntegerValue(2));
633 
634  double value;
635 
636  // Test that the sequencet is correct.
637  value = s->GetValue();
638  NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 1 wrong.");
639  value = s->GetValue();
640  NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence value 2 wrong.");
641  value = s->GetValue();
642  NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 3 wrong.");
643  value = s->GetValue();
644  NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence value 4 wrong.");
645  value = s->GetValue();
646  NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 5 wrong.");
647  value = s->GetValue();
648  NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence value 6 wrong.");
649 }
650 
656 {
657  public:
658  // Constructor
659  NormalTestCase();
660 
661  // Inherited
662  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
663 
664  private:
665  // Inherited
666  void DoRun() override;
667 
669  static constexpr double TOLERANCE{5};
670 };
671 
673  : TestCaseBase("Normal Random Variable Stream Generator")
674 {
675 }
676 
677 double
679 {
680  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
681  auto range = UniformHistogramBins(h, -4., 4.);
682 
683  std::vector<double> expected(N_BINS);
684 
685  // Note that this assumes that n has mean equal to zero and standard
686  // deviation equal to one, which are their default values for this
687  // distribution.
688  double sigma = 1.;
689 
690  for (std::size_t i = 0; i < N_BINS; ++i)
691  {
692  expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
693  expected[i] *= N_MEASUREMENTS;
694  }
695 
696  double chiSquared = ChiSquared(h, expected, rng);
697  gsl_histogram_free(h);
698  return chiSquared;
699 }
700 
701 void
703 {
704  NS_LOG_FUNCTION(this);
706 
707  auto generator = RngGenerator<NormalRandomVariable>();
708  auto rng = generator.Create();
709 
710  double sum = ChiSquaredsAverage(&generator, N_RUNS);
711  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
712  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
713 
714  double mean = 5.0;
715  double variance = 2.0;
716 
717  // Create the RNG with the specified range.
718  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable>();
719  x->SetAttribute("Mean", DoubleValue(mean));
720  x->SetAttribute("Variance", DoubleValue(variance));
721 
722  // Calculate the mean of these values.
723  double valueMean = Average(x);
724 
725  // The expected value for the mean of the values returned by a
726  // normally distributed random variable is equal to mean.
727  double expectedMean = mean;
728  double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
729 
730  // Test that values have approximately the right mean value.
731  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
732  expectedMean,
733  expectedRms * TOLERANCE,
734  "Wrong mean value.");
735 }
736 
742 {
743  public:
744  // Constructor
746 
747  // Inherited
748  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
749 
750  private:
751  // Inherited
752  void DoRun() override;
753 
755  static constexpr double TOLERANCE{5};
756 };
757 
759  : TestCaseBase("Antithetic Normal Random Variable Stream Generator")
760 {
761 }
762 
763 double
765 {
766  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
767  auto range = UniformHistogramBins(h, -4, 4);
768 
769  std::vector<double> expected(N_BINS);
770 
771  // Note that this assumes that n has mean equal to zero and standard
772  // deviation equal to one, which are their default values for this
773  // distribution.
774  double sigma = 1.;
775 
776  for (std::size_t i = 0; i < N_BINS; ++i)
777  {
778  expected[i] = gsl_cdf_gaussian_P(range[i + 1], sigma) - gsl_cdf_gaussian_P(range[i], sigma);
779  expected[i] *= N_MEASUREMENTS;
780  }
781 
782  double chiSquared = ChiSquared(h, expected, rng);
783 
784  gsl_histogram_free(h);
785  return chiSquared;
786 }
787 
788 void
790 {
791  NS_LOG_FUNCTION(this);
793 
794  auto generator = RngGenerator<NormalRandomVariable>(true);
795  double sum = ChiSquaredsAverage(&generator, N_RUNS);
796  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
797  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
798 
799  double mean = 5.0;
800  double variance = 2.0;
801 
802  // Create the RNG with the specified range.
803  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable>();
804  x->SetAttribute("Mean", DoubleValue(mean));
805  x->SetAttribute("Variance", DoubleValue(variance));
806 
807  // Make this generate antithetic values.
808  x->SetAttribute("Antithetic", BooleanValue(true));
809 
810  // Calculate the mean of these values.
811  double valueMean = Average(x);
812 
813  // The expected value for the mean of the values returned by a
814  // normally distributed random variable is equal to mean.
815  double expectedMean = mean;
816  double expectedRms = mean / std::sqrt(variance * N_MEASUREMENTS);
817 
818  // Test that values have approximately the right mean value.
819  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
820  expectedMean,
821  expectedRms * TOLERANCE,
822  "Wrong mean value.");
823 }
824 
830 {
831  public:
832  // Constructor
834 
835  // Inherited
836  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
837 
838  private:
839  // Inherited
840  void DoRun() override;
841 
843  static constexpr double TOLERANCE{5};
844 };
845 
847  : TestCaseBase("Exponential Random Variable Stream Generator")
848 {
849 }
850 
851 double
853 {
854  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
855  auto range = UniformHistogramBins(h, 0, 10, false);
856 
857  std::vector<double> expected(N_BINS);
858 
859  // Note that this assumes that e has mean equal to one, which is the
860  // default value for this distribution.
861  double mu = 1.;
862 
863  for (std::size_t i = 0; i < N_BINS; ++i)
864  {
865  expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
866  expected[i] *= N_MEASUREMENTS;
867  }
868 
869  double chiSquared = ChiSquared(h, expected, rng);
870 
871  gsl_histogram_free(h);
872  return chiSquared;
873 }
874 
875 void
877 {
878  NS_LOG_FUNCTION(this);
880 
881  auto generator = RngGenerator<ExponentialRandomVariable>();
882  double sum = ChiSquaredsAverage(&generator, N_RUNS);
883  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
884  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
885 
886  double mean = 3.14;
887  double bound = 0.0;
888 
889  // Create the RNG with the specified range.
890  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable>();
891  x->SetAttribute("Mean", DoubleValue(mean));
892  x->SetAttribute("Bound", DoubleValue(bound));
893 
894  // Calculate the mean of these values.
895  double valueMean = Average(x);
896  double expectedMean = mean;
897  double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
898 
899  // Test that values have approximately the right mean value.
900  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
901  expectedMean,
902  expectedRms * TOLERANCE,
903  "Wrong mean value.");
904 }
905 
911 {
912  public:
913  // Constructor
915 
916  // Inherited
917  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
918 
919  private:
920  // Inherited
921  void DoRun() override;
922 
924  static constexpr double TOLERANCE{5};
925 };
926 
928  : TestCaseBase("Antithetic Exponential Random Variable Stream Generator")
929 {
930 }
931 
932 double
934 {
935  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
936  auto range = UniformHistogramBins(h, 0, 10, false);
937 
938  std::vector<double> expected(N_BINS);
939 
940  // Note that this assumes that e has mean equal to one, which is the
941  // default value for this distribution.
942  double mu = 1.;
943 
944  for (std::size_t i = 0; i < N_BINS; ++i)
945  {
946  expected[i] = gsl_cdf_exponential_P(range[i + 1], mu) - gsl_cdf_exponential_P(range[i], mu);
947  expected[i] *= N_MEASUREMENTS;
948  }
949 
950  double chiSquared = ChiSquared(h, expected, rng);
951 
952  gsl_histogram_free(h);
953  return chiSquared;
954 }
955 
956 void
958 {
959  NS_LOG_FUNCTION(this);
961 
962  auto generator = RngGenerator<ExponentialRandomVariable>(true);
963  double sum = ChiSquaredsAverage(&generator, N_RUNS);
964  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
965  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
966 
967  double mean = 3.14;
968  double bound = 0.0;
969 
970  // Create the RNG with the specified range.
971  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable>();
972  x->SetAttribute("Mean", DoubleValue(mean));
973  x->SetAttribute("Bound", DoubleValue(bound));
974 
975  // Make this generate antithetic values.
976  x->SetAttribute("Antithetic", BooleanValue(true));
977 
978  // Calculate the mean of these values.
979  double valueMean = Average(x);
980  double expectedMean = mean;
981  double expectedRms = std::sqrt(mean / N_MEASUREMENTS);
982 
983  // Test that values have approximately the right mean value.
984  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
985  expectedMean,
986  expectedRms * TOLERANCE,
987  "Wrong mean value.");
988 }
989 
995 {
996  public:
997  // Constructor
998  ParetoTestCase();
999 
1000  // Inherited
1001  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1002 
1003  private:
1004  // Inherited
1005  void DoRun() override;
1006 
1011  static constexpr double TOLERANCE{1e-2};
1012 };
1013 
1015  : TestCaseBase("Pareto Random Variable Stream Generator")
1016 {
1017 }
1018 
1019 double
1021 {
1022  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1023  auto range = UniformHistogramBins(h, 1, 10, false);
1024 
1025  std::vector<double> expected(N_BINS);
1026 
1027  double shape = 2.0;
1028  double scale = 1.0;
1029 
1030  for (std::size_t i = 0; i < N_BINS; ++i)
1031  {
1032  expected[i] =
1033  gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1034  expected[i] *= N_MEASUREMENTS;
1035  }
1036 
1037  double chiSquared = ChiSquared(h, expected, rng);
1038 
1039  gsl_histogram_free(h);
1040  return chiSquared;
1041 }
1042 
1043 void
1045 {
1046  NS_LOG_FUNCTION(this);
1047  SetTestSuiteSeed();
1048 
1049  auto generator = RngGenerator<ParetoRandomVariable>();
1050  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1051  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1052  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1053 
1054  double shape = 2.0;
1055  double scale = 1.0;
1056 
1057  // Create the RNG with the specified range.
1058  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable>();
1059  x->SetAttribute("Shape", DoubleValue(shape));
1060  x->SetAttribute("Scale", DoubleValue(scale));
1061 
1062  // Calculate the mean of these values.
1063  double valueMean = Average(x);
1064 
1065  // The expected value for the mean is given by
1066  //
1067  // shape * scale
1068  // E[value] = --------------- ,
1069  // shape - 1
1070  //
1071  // where
1072  //
1073  // scale = mean * (shape - 1.0) / shape .
1074  double expectedMean = (shape * scale) / (shape - 1.0);
1075 
1076  // Test that values have approximately the right mean value.
1077  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1078  expectedMean,
1079  expectedMean * TOLERANCE,
1080  "Wrong mean value.");
1081 }
1082 
1088 {
1089  public:
1090  // Constructor
1092 
1093  // Inherited
1094  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1095 
1096  private:
1097  // Inherited
1098  void DoRun() override;
1099 
1104  static constexpr double TOLERANCE{1e-2};
1105 };
1106 
1108  : TestCaseBase("Antithetic Pareto Random Variable Stream Generator")
1109 {
1110 }
1111 
1112 double
1114 {
1115  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1116  auto range = UniformHistogramBins(h, 1, 10, false);
1117 
1118  std::vector<double> expected(N_BINS);
1119 
1120  double shape = 2.0;
1121  double scale = 1.0;
1122 
1123  for (std::size_t i = 0; i < N_BINS; ++i)
1124  {
1125  expected[i] =
1126  gsl_cdf_pareto_P(range[i + 1], shape, scale) - gsl_cdf_pareto_P(range[i], shape, scale);
1127  expected[i] *= N_MEASUREMENTS;
1128  }
1129 
1130  double chiSquared = ChiSquared(h, expected, rng);
1131 
1132  gsl_histogram_free(h);
1133  return chiSquared;
1134 }
1135 
1136 void
1138 {
1139  NS_LOG_FUNCTION(this);
1140  SetTestSuiteSeed();
1141 
1142  auto generator = RngGenerator<ParetoRandomVariable>(true);
1143  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1144  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1145  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1146 
1147  double shape = 2.0;
1148  double scale = 1.0;
1149 
1150  // Create the RNG with the specified range.
1151  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable>();
1152  x->SetAttribute("Shape", DoubleValue(shape));
1153  x->SetAttribute("Scale", DoubleValue(scale));
1154 
1155  // Make this generate antithetic values.
1156  x->SetAttribute("Antithetic", BooleanValue(true));
1157 
1158  // Calculate the mean of these values.
1159  double valueMean = Average(x);
1160 
1161  // The expected value for the mean is given by
1162  //
1163  // shape * scale
1164  // E[value] = --------------- ,
1165  // shape - 1
1166  //
1167  // where
1168  //
1169  // scale = mean * (shape - 1.0) / shape .
1170  //
1171  double expectedMean = (shape * scale) / (shape - 1.0);
1172 
1173  // Test that values have approximately the right mean value.
1174  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1175  expectedMean,
1176  expectedMean * TOLERANCE,
1177  "Wrong mean value.");
1178 }
1179 
1185 {
1186  public:
1187  // Constructor
1188  WeibullTestCase();
1189 
1190  // Inherited
1191  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1192 
1193  private:
1194  // Inherited
1195  void DoRun() override;
1196 
1201  static constexpr double TOLERANCE{1e-2};
1202 };
1203 
1205  : TestCaseBase("Weibull Random Variable Stream Generator")
1206 {
1207 }
1208 
1209 double
1211 {
1212  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1213  auto range = UniformHistogramBins(h, 1, 10, false);
1214 
1215  std::vector<double> expected(N_BINS);
1216 
1217  // Note that this assumes that p has shape equal to one and scale
1218  // equal to one, which are their default values for this
1219  // distribution.
1220  double a = 1.0;
1221  double b = 1.0;
1222 
1223  for (std::size_t i = 0; i < N_BINS; ++i)
1224  {
1225  expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1226  expected[i] *= N_MEASUREMENTS;
1227  NS_LOG_INFO("weibull: " << expected[i]);
1228  }
1229 
1230  double chiSquared = ChiSquared(h, expected, rng);
1231 
1232  gsl_histogram_free(h);
1233  return chiSquared;
1234 }
1235 
1236 void
1238 {
1239  NS_LOG_FUNCTION(this);
1240  SetTestSuiteSeed();
1241 
1242  auto generator = RngGenerator<WeibullRandomVariable>();
1243  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1244  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1245  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1246 
1247  double scale = 5.0;
1248  double shape = 1.0;
1249 
1250  // Create the RNG with the specified range.
1251  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable>();
1252  x->SetAttribute("Scale", DoubleValue(scale));
1253  x->SetAttribute("Shape", DoubleValue(shape));
1254 
1255  // Calculate the mean of these values.
1256  double valueMean = Average(x);
1257 
1258  // The expected value for the mean of the values returned by a
1259  // Weibull distributed random variable is
1260  //
1261  // E[value] = scale * Gamma(1 + 1 / shape) ,
1262  //
1263  // where Gamma() is the Gamma function. Note that
1264  //
1265  // Gamma(n) = (n - 1)!
1266  //
1267  // if n is a positive integer.
1268  //
1269  // For this test,
1270  //
1271  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1272  // = Gamma(2)
1273  // = (2 - 1)!
1274  // = 1
1275  //
1276  // which means
1277  //
1278  // E[value] = scale .
1279  //
1280  double expectedMean = scale;
1281 
1282  // Test that values have approximately the right mean value.
1283  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1284  expectedMean,
1285  expectedMean * TOLERANCE,
1286  "Wrong mean value.");
1287 }
1288 
1294 {
1295  public:
1296  // Constructor
1298 
1299  // Inherited
1300  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1301 
1302  private:
1303  // Inherited
1304  void DoRun() override;
1305 
1310  static constexpr double TOLERANCE{1e-2};
1311 };
1312 
1314  : TestCaseBase("Antithetic Weibull Random Variable Stream Generator")
1315 {
1316 }
1317 
1318 double
1320 {
1321  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1322  auto range = UniformHistogramBins(h, 1, 10, false);
1323 
1324  std::vector<double> expected(N_BINS);
1325 
1326  // Note that this assumes that p has shape equal to one and scale
1327  // equal to one, which are their default values for this
1328  // distribution.
1329  double a = 1.0;
1330  double b = 1.0;
1331 
1332  for (std::size_t i = 0; i < N_BINS; ++i)
1333  {
1334  expected[i] = gsl_cdf_weibull_P(range[i + 1], a, b) - gsl_cdf_weibull_P(range[i], a, b);
1335  expected[i] *= N_MEASUREMENTS;
1336  }
1337 
1338  double chiSquared = ChiSquared(h, expected, rng);
1339 
1340  gsl_histogram_free(h);
1341  return chiSquared;
1342 }
1343 
1344 void
1346 {
1347  NS_LOG_FUNCTION(this);
1348  SetTestSuiteSeed();
1349 
1350  auto generator = RngGenerator<WeibullRandomVariable>(true);
1351  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1352  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1353  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1354 
1355  double scale = 5.0;
1356  double shape = 1.0;
1357 
1358  // Create the RNG with the specified range.
1359  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable>();
1360  x->SetAttribute("Scale", DoubleValue(scale));
1361  x->SetAttribute("Shape", DoubleValue(shape));
1362 
1363  // Make this generate antithetic values.
1364  x->SetAttribute("Antithetic", BooleanValue(true));
1365 
1366  // Calculate the mean of these values.
1367  double valueMean = Average(x);
1368 
1369  // The expected value for the mean of the values returned by a
1370  // Weibull distributed random variable is
1371  //
1372  // E[value] = scale * Gamma(1 + 1 / shape) ,
1373  //
1374  // where Gamma() is the Gamma function. Note that
1375  //
1376  // Gamma(n) = (n - 1)!
1377  //
1378  // if n is a positive integer.
1379  //
1380  // For this test,
1381  //
1382  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1383  // = Gamma(2)
1384  // = (2 - 1)!
1385  // = 1
1386  //
1387  // which means
1388  //
1389  // E[value] = scale .
1390  //
1391  double expectedMean = scale;
1392 
1393  // Test that values have approximately the right mean value.
1394  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1395  expectedMean,
1396  expectedMean * TOLERANCE,
1397  "Wrong mean value.");
1398 }
1399 
1405 {
1406  public:
1407  // Constructor
1409 
1410  // Inherited
1411  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1412 
1413  private:
1414  // Inherited
1415  void DoRun() override;
1416 
1421  static constexpr double TOLERANCE{3e-2};
1422 };
1423 
1425  : TestCaseBase("Log-Normal Random Variable Stream Generator")
1426 {
1427 }
1428 
1429 double
1431 {
1432  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1433  auto range = UniformHistogramBins(h, 0, 10, false);
1434 
1435  std::vector<double> expected(N_BINS);
1436 
1437  // Note that this assumes that n has mu equal to zero and sigma
1438  // equal to one, which are their default values for this
1439  // distribution.
1440  double mu = 0.0;
1441  double sigma = 1.0;
1442 
1443  for (std::size_t i = 0; i < N_BINS; ++i)
1444  {
1445  expected[i] =
1446  gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1447  expected[i] *= N_MEASUREMENTS;
1448  }
1449 
1450  double chiSquared = ChiSquared(h, expected, rng);
1451 
1452  gsl_histogram_free(h);
1453  return chiSquared;
1454 }
1455 
1456 void
1458 {
1459  NS_LOG_FUNCTION(this);
1460  SetTestSuiteSeed();
1461 
1462  auto generator = RngGenerator<LogNormalRandomVariable>();
1463  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1464  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1465 
1466  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1467 
1468  double mu = 5.0;
1469  double sigma = 2.0;
1470 
1471  // Create the RNG with the specified range.
1472  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable>();
1473  x->SetAttribute("Mu", DoubleValue(mu));
1474  x->SetAttribute("Sigma", DoubleValue(sigma));
1475 
1476  // Calculate the mean of these values.
1477  double valueMean = Average(x);
1478 
1479  // The expected value for the mean of the values returned by a
1480  // log-normally distributed random variable is equal to
1481  //
1482  // 2
1483  // mu + sigma / 2
1484  // E[value] = e .
1485  //
1486  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1487 
1488  // Test that values have approximately the right mean value.
1489  //
1496  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1497  expectedMean,
1498  expectedMean * TOLERANCE,
1499  "Wrong mean value.");
1500 }
1501 
1507 {
1508  public:
1509  // Constructor
1511 
1512  // Inherited
1513  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1514 
1515  private:
1516  // Inherited
1517  void DoRun() override;
1518 
1523  static constexpr double TOLERANCE{3e-2};
1524 };
1525 
1527  : TestCaseBase("Antithetic Log-Normal Random Variable Stream Generator")
1528 {
1529 }
1530 
1531 double
1533 {
1534  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1535  auto range = UniformHistogramBins(h, 0, 10, false);
1536 
1537  std::vector<double> expected(N_BINS);
1538 
1539  // Note that this assumes that n has mu equal to zero and sigma
1540  // equal to one, which are their default values for this
1541  // distribution.
1542  double mu = 0.0;
1543  double sigma = 1.0;
1544 
1545  for (std::size_t i = 0; i < N_BINS; ++i)
1546  {
1547  expected[i] =
1548  gsl_cdf_lognormal_P(range[i + 1], mu, sigma) - gsl_cdf_lognormal_P(range[i], mu, sigma);
1549  expected[i] *= N_MEASUREMENTS;
1550  }
1551 
1552  double chiSquared = ChiSquared(h, expected, rng);
1553 
1554  gsl_histogram_free(h);
1555  return chiSquared;
1556 }
1557 
1558 void
1560 {
1561  NS_LOG_FUNCTION(this);
1562  SetTestSuiteSeed();
1563 
1564  auto generator = RngGenerator<LogNormalRandomVariable>(true);
1565  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1566  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1567  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1568 
1569  double mu = 5.0;
1570  double sigma = 2.0;
1571 
1572  // Create the RNG with the specified range.
1573  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable>();
1574  x->SetAttribute("Mu", DoubleValue(mu));
1575  x->SetAttribute("Sigma", DoubleValue(sigma));
1576 
1577  // Make this generate antithetic values.
1578  x->SetAttribute("Antithetic", BooleanValue(true));
1579 
1580  // Calculate the mean of these values.
1581  double valueMean = Average(x);
1582 
1583  // The expected value for the mean of the values returned by a
1584  // log-normally distributed random variable is equal to
1585  //
1586  // 2
1587  // mu + sigma / 2
1588  // E[value] = e .
1589  //
1590  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1591 
1592  // Test that values have approximately the right mean value.
1593  //
1600  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1601  expectedMean,
1602  expectedMean * TOLERANCE,
1603  "Wrong mean value.");
1604 }
1605 
1611 {
1612  public:
1613  // Constructor
1614  GammaTestCase();
1615 
1616  // Inherited
1617  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1618 
1619  private:
1620  // Inherited
1621  void DoRun() override;
1622 
1627  static constexpr double TOLERANCE{1e-2};
1628 };
1629 
1631  : TestCaseBase("Gamma Random Variable Stream Generator")
1632 {
1633 }
1634 
1635 double
1637 {
1638  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1639  auto range = UniformHistogramBins(h, 0, 10, false);
1640 
1641  std::vector<double> expected(N_BINS);
1642 
1643  // Note that this assumes that n has alpha equal to one and beta
1644  // equal to one, which are their default values for this
1645  // distribution.
1646  double alpha = 1.0;
1647  double beta = 1.0;
1648 
1649  for (std::size_t i = 0; i < N_BINS; ++i)
1650  {
1651  expected[i] =
1652  gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1653  expected[i] *= N_MEASUREMENTS;
1654  }
1655 
1656  double chiSquared = ChiSquared(h, expected, rng);
1657 
1658  gsl_histogram_free(h);
1659  return chiSquared;
1660 }
1661 
1662 void
1664 {
1665  NS_LOG_FUNCTION(this);
1666  SetTestSuiteSeed();
1667 
1668  auto generator = RngGenerator<GammaRandomVariable>();
1669  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1670  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1671  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1672 
1673  double alpha = 5.0;
1674  double beta = 2.0;
1675 
1676  // Create the RNG with the specified range.
1677  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable>();
1678  x->SetAttribute("Alpha", DoubleValue(alpha));
1679  x->SetAttribute("Beta", DoubleValue(beta));
1680 
1681  // Calculate the mean of these values.
1682  double valueMean = Average(x);
1683 
1684  // The expected value for the mean of the values returned by a
1685  // gammaly distributed random variable is equal to
1686  //
1687  // E[value] = alpha * beta .
1688  //
1689  double expectedMean = alpha * beta;
1690 
1691  // Test that values have approximately the right mean value.
1692  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1693  expectedMean,
1694  expectedMean * TOLERANCE,
1695  "Wrong mean value.");
1696 }
1697 
1703 {
1704  public:
1705  // Constructor
1707 
1708  // Inherited
1709  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1710 
1711  private:
1712  // Inherited
1713  void DoRun() override;
1714 
1719  static constexpr double TOLERANCE{1e-2};
1720 };
1721 
1723  : TestCaseBase("Antithetic Gamma Random Variable Stream Generator")
1724 {
1725 }
1726 
1727 double
1729 {
1730  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1731  auto range = UniformHistogramBins(h, 0, 10, false);
1732 
1733  std::vector<double> expected(N_BINS);
1734 
1735  // Note that this assumes that n has alpha equal to one and beta
1736  // equal to one, which are their default values for this
1737  // distribution.
1738  double alpha = 1.0;
1739  double beta = 1.0;
1740 
1741  for (std::size_t i = 0; i < N_BINS; ++i)
1742  {
1743  expected[i] =
1744  gsl_cdf_gamma_P(range[i + 1], alpha, beta) - gsl_cdf_gamma_P(range[i], alpha, beta);
1745  expected[i] *= N_MEASUREMENTS;
1746  }
1747 
1748  double chiSquared = ChiSquared(h, expected, rng);
1749 
1750  gsl_histogram_free(h);
1751  return chiSquared;
1752 }
1753 
1754 void
1756 {
1757  NS_LOG_FUNCTION(this);
1758  SetTestSuiteSeed();
1759 
1760  auto generator = RngGenerator<GammaRandomVariable>(true);
1761  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1762  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1763  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1764 
1765  double alpha = 5.0;
1766  double beta = 2.0;
1767 
1768  // Create the RNG with the specified range.
1769  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable>();
1770 
1771  // Make this generate antithetic values.
1772  x->SetAttribute("Antithetic", BooleanValue(true));
1773 
1774  x->SetAttribute("Alpha", DoubleValue(alpha));
1775  x->SetAttribute("Beta", DoubleValue(beta));
1776 
1777  // Calculate the mean of these values.
1778  double valueMean = Average(x);
1779 
1780  // The expected value for the mean of the values returned by a
1781  // gammaly distributed random variable is equal to
1782  //
1783  // E[value] = alpha * beta .
1784  //
1785  double expectedMean = alpha * beta;
1786 
1787  // Test that values have approximately the right mean value.
1788  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1789  expectedMean,
1790  expectedMean * TOLERANCE,
1791  "Wrong mean value.");
1792 }
1793 
1799 {
1800  public:
1801  // Constructor
1802  ErlangTestCase();
1803 
1804  // Inherited
1805  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1806 
1807  private:
1808  // Inherited
1809  void DoRun() override;
1810 
1815  static constexpr double TOLERANCE{1e-2};
1816 };
1817 
1819  : TestCaseBase("Erlang Random Variable Stream Generator")
1820 {
1821 }
1822 
1823 double
1825 {
1826  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1827  auto range = UniformHistogramBins(h, 0, 10, false);
1828 
1829  std::vector<double> expected(N_BINS);
1830 
1831  // Note that this assumes that n has k equal to one and lambda
1832  // equal to one, which are their default values for this
1833  // distribution.
1834  uint32_t k = 1;
1835  double lambda = 1.0;
1836 
1837  // Note that Erlang distribution is equal to the gamma distribution
1838  // when k is an integer, which is why the gamma distribution's cdf
1839  // function can be used here.
1840  for (std::size_t i = 0; i < N_BINS; ++i)
1841  {
1842  expected[i] =
1843  gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1844  expected[i] *= N_MEASUREMENTS;
1845  }
1846 
1847  double chiSquared = ChiSquared(h, expected, rng);
1848 
1849  gsl_histogram_free(h);
1850  return chiSquared;
1851 }
1852 
1853 void
1855 {
1856  NS_LOG_FUNCTION(this);
1857  SetTestSuiteSeed();
1858 
1859  auto generator = RngGenerator<ErlangRandomVariable>();
1860  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1861  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1862  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1863 
1864  uint32_t k = 5;
1865  double lambda = 2.0;
1866 
1867  // Create the RNG with the specified range.
1868  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable>();
1869  x->SetAttribute("K", IntegerValue(k));
1870  x->SetAttribute("Lambda", DoubleValue(lambda));
1871 
1872  // Calculate the mean of these values.
1873  double valueMean = Average(x);
1874 
1875  // The expected value for the mean of the values returned by a
1876  // Erlangly distributed random variable is equal to
1877  //
1878  // E[value] = k * lambda .
1879  //
1880  double expectedMean = k * lambda;
1881 
1882  // Test that values have approximately the right mean value.
1883  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1884  expectedMean,
1885  expectedMean * TOLERANCE,
1886  "Wrong mean value.");
1887 }
1888 
1894 {
1895  public:
1896  // Constructor
1898 
1899  // Inherited
1900  double ChiSquaredTest(Ptr<RandomVariableStream> rng) const override;
1901 
1902  private:
1903  // Inherited
1904  void DoRun() override;
1905 
1910  static constexpr double TOLERANCE{1e-2};
1911 };
1912 
1914  : TestCaseBase("Antithetic Erlang Random Variable Stream Generator")
1915 {
1916 }
1917 
1918 double
1920 {
1921  gsl_histogram* h = gsl_histogram_alloc(N_BINS);
1922  auto range = UniformHistogramBins(h, 0, 10, false);
1923 
1924  std::vector<double> expected(N_BINS);
1925 
1926  // Note that this assumes that n has k equal to one and lambda
1927  // equal to one, which are their default values for this
1928  // distribution.
1929  uint32_t k = 1;
1930  double lambda = 1.0;
1931 
1932  // Note that Erlang distribution is equal to the gamma distribution
1933  // when k is an integer, which is why the gamma distribution's cdf
1934  // function can be used here.
1935  for (std::size_t i = 0; i < N_BINS; ++i)
1936  {
1937  expected[i] =
1938  gsl_cdf_gamma_P(range[i + 1], k, lambda) - gsl_cdf_gamma_P(range[i], k, lambda);
1939  expected[i] *= N_MEASUREMENTS;
1940  }
1941 
1942  double chiSquared = ChiSquared(h, expected, rng);
1943 
1944  gsl_histogram_free(h);
1945  return chiSquared;
1946 }
1947 
1948 void
1950 {
1951  NS_LOG_FUNCTION(this);
1952  SetTestSuiteSeed();
1953 
1954  auto generator = RngGenerator<ErlangRandomVariable>(true);
1955  double sum = ChiSquaredsAverage(&generator, N_RUNS);
1956  double maxStatistic = gsl_cdf_chisq_Qinv(0.05, N_BINS);
1957  NS_TEST_ASSERT_MSG_LT(sum, maxStatistic, "Chi-squared statistic out of range");
1958 
1959  uint32_t k = 5;
1960  double lambda = 2.0;
1961 
1962  // Create the RNG with the specified range.
1963  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable>();
1964 
1965  // Make this generate antithetic values.
1966  x->SetAttribute("Antithetic", BooleanValue(true));
1967 
1968  x->SetAttribute("K", IntegerValue(k));
1969  x->SetAttribute("Lambda", DoubleValue(lambda));
1970 
1971  // Calculate the mean of these values.
1972  double valueMean = Average(x);
1973 
1974  // The expected value for the mean of the values returned by a
1975  // Erlangly distributed random variable is equal to
1976  //
1977  // E[value] = k * lambda .
1978  //
1979  double expectedMean = k * lambda;
1980 
1981  // Test that values have approximately the right mean value.
1982  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
1983  expectedMean,
1984  expectedMean * TOLERANCE,
1985  "Wrong mean value.");
1986 }
1987 
1993 {
1994  public:
1995  // Constructor
1996  ZipfTestCase();
1997 
1998  private:
1999  // Inherited
2000  void DoRun() override;
2001 
2006  static constexpr double TOLERANCE{1e-2};
2007 };
2008 
2010  : TestCaseBase("Zipf Random Variable Stream Generator")
2011 {
2012 }
2013 
2014 void
2016 {
2017  NS_LOG_FUNCTION(this);
2018  SetTestSuiteSeed();
2019 
2020  uint32_t n = 1;
2021  double alpha = 2.0;
2022 
2023  // Create the RNG with the specified range.
2024  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable>();
2025  x->SetAttribute("N", IntegerValue(n));
2026  x->SetAttribute("Alpha", DoubleValue(alpha));
2027 
2028  // Calculate the mean of these values.
2029  double valueMean = Average(x);
2030 
2031  // The expected value for the mean of the values returned by a
2032  // Zipfly distributed random variable is equal to
2033  //
2034  // H
2035  // N, alpha - 1
2036  // E[value] = ---------------
2037  // H
2038  // N, alpha
2039  //
2040  // where
2041  //
2042  // N
2043  // ---
2044  // \ -alpha
2045  // H = / m .
2046  // N, alpha ---
2047  // m=1
2048  //
2049  // For this test,
2050  //
2051  // -(alpha - 1)
2052  // 1
2053  // E[value] = ---------------
2054  // -alpha
2055  // 1
2056  //
2057  // = 1 .
2058  //
2059  double expectedMean = 1.0;
2060 
2061  // Test that values have approximately the right mean value.
2062  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2063  expectedMean,
2064  expectedMean * TOLERANCE,
2065  "Wrong mean value.");
2066 }
2067 
2073 {
2074  public:
2075  // Constructor
2077 
2078  private:
2079  // Inherited
2080  void DoRun() override;
2081 
2086  static constexpr double TOLERANCE{1e-2};
2087 };
2088 
2090  : TestCaseBase("Antithetic Zipf Random Variable Stream Generator")
2091 {
2092 }
2093 
2094 void
2096 {
2097  NS_LOG_FUNCTION(this);
2098  SetTestSuiteSeed();
2099 
2100  uint32_t n = 1;
2101  double alpha = 2.0;
2102 
2103  // Create the RNG with the specified range.
2104  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable>();
2105  x->SetAttribute("N", IntegerValue(n));
2106  x->SetAttribute("Alpha", DoubleValue(alpha));
2107 
2108  // Make this generate antithetic values.
2109  x->SetAttribute("Antithetic", BooleanValue(true));
2110 
2111  // Calculate the mean of these values.
2112  double valueMean = Average(x);
2113 
2114  // The expected value for the mean of the values returned by a
2115  // Zipfly distributed random variable is equal to
2116  //
2117  // H
2118  // N, alpha - 1
2119  // E[value] = ---------------
2120  // H
2121  // N, alpha
2122  //
2123  // where
2124  //
2125  // N
2126  // ---
2127  // \ -alpha
2128  // H = / m .
2129  // N, alpha ---
2130  // m=1
2131  //
2132  // For this test,
2133  //
2134  // -(alpha - 1)
2135  // 1
2136  // E[value] = ---------------
2137  // -alpha
2138  // 1
2139  //
2140  // = 1 .
2141  //
2142  double expectedMean = 1.0;
2143 
2144  // Test that values have approximately the right mean value.
2145  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2146  expectedMean,
2147  expectedMean * TOLERANCE,
2148  "Wrong mean value.");
2149 }
2150 
2156 {
2157  public:
2158  // Constructor
2159  ZetaTestCase();
2160 
2161  private:
2162  // Inherited
2163  void DoRun() override;
2164 
2169  static constexpr double TOLERANCE{1e-2};
2170 };
2171 
2173  : TestCaseBase("Zeta Random Variable Stream Generator")
2174 {
2175 }
2176 
2177 void
2179 {
2180  NS_LOG_FUNCTION(this);
2181  SetTestSuiteSeed();
2182 
2183  double alpha = 5.0;
2184 
2185  // Create the RNG with the specified range.
2186  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable>();
2187  x->SetAttribute("Alpha", DoubleValue(alpha));
2188 
2189  // Calculate the mean of these values.
2190  double valueMean = Average(x);
2191 
2192  // The expected value for the mean of the values returned by a
2193  // zetaly distributed random variable is equal to
2194  //
2195  // zeta(alpha - 1)
2196  // E[value] = --------------- for alpha > 2 ,
2197  // zeta(alpha)
2198  //
2199  // where zeta(alpha) is the Riemann zeta function.
2200  //
2201  // There are no simple analytic forms for the Riemann zeta function,
2202  // which is why the gsl library is used in this test to calculate
2203  // the known mean of the values.
2204  double expectedMean =
2205  gsl_sf_zeta_int(static_cast<int>(alpha - 1)) / gsl_sf_zeta_int(static_cast<int>(alpha));
2206 
2207  // Test that values have approximately the right mean value.
2208  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2209  expectedMean,
2210  expectedMean * TOLERANCE,
2211  "Wrong mean value.");
2212 }
2213 
2219 {
2220  public:
2221  // Constructor
2223 
2224  private:
2225  // Inherited
2226  void DoRun() override;
2227 
2232  static constexpr double TOLERANCE{1e-2};
2233 };
2234 
2236  : TestCaseBase("Antithetic Zeta Random Variable Stream Generator")
2237 {
2238 }
2239 
2240 void
2242 {
2243  NS_LOG_FUNCTION(this);
2244  SetTestSuiteSeed();
2245 
2246  double alpha = 5.0;
2247 
2248  // Create the RNG with the specified range.
2249  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable>();
2250  x->SetAttribute("Alpha", DoubleValue(alpha));
2251 
2252  // Make this generate antithetic values.
2253  x->SetAttribute("Antithetic", BooleanValue(true));
2254 
2255  // Calculate the mean of these values.
2256  double valueMean = Average(x);
2257 
2258  // The expected value for the mean of the values returned by a
2259  // zetaly distributed random variable is equal to
2260  //
2261  // zeta(alpha - 1)
2262  // E[value] = --------------- for alpha > 2 ,
2263  // zeta(alpha)
2264  //
2265  // where zeta(alpha) is the Riemann zeta function.
2266  //
2267  // There are no simple analytic forms for the Riemann zeta function,
2268  // which is why the gsl library is used in this test to calculate
2269  // the known mean of the values.
2270  double expectedMean =
2271  gsl_sf_zeta_int(static_cast<int>(alpha) - 1) / gsl_sf_zeta_int(static_cast<int>(alpha));
2272 
2273  // Test that values have approximately the right mean value.
2274  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2275  expectedMean,
2276  expectedMean * TOLERANCE,
2277  "Wrong mean value.");
2278 }
2279 
2285 {
2286  public:
2287  // Constructor
2289 
2290  private:
2291  // Inherited
2292  void DoRun() override;
2293 
2295  static constexpr double TOLERANCE{1e-8};
2296 };
2297 
2299  : TestCaseBase("Deterministic Random Variable Stream Generator")
2300 {
2301 }
2302 
2303 void
2305 {
2306  NS_LOG_FUNCTION(this);
2307  SetTestSuiteSeed();
2308 
2309  Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable>();
2310 
2311  // The following array should give the sequence
2312  //
2313  // 4, 4, 7, 7, 10, 10 .
2314  //
2315  double array1[] = {4, 4, 7, 7, 10, 10};
2316  std::size_t count1 = 6;
2317  s->SetValueArray(array1, count1);
2318 
2319  double value;
2320 
2321  // Test that the first sequence is correct.
2322  value = s->GetValue();
2323  NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2324  value = s->GetValue();
2325  NS_TEST_ASSERT_MSG_EQ_TOL(value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2326  value = s->GetValue();
2327  NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2328  value = s->GetValue();
2329  NS_TEST_ASSERT_MSG_EQ_TOL(value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2330  value = s->GetValue();
2331  NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2332  value = s->GetValue();
2333  NS_TEST_ASSERT_MSG_EQ_TOL(value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2334 
2335  // The following array should give the sequence
2336  //
2337  // 1000, 2000, 7, 7 .
2338  //
2339  double array2[] = {1000, 2000, 3000, 4000};
2340  std::size_t count2 = 4;
2341  s->SetValueArray(array2, count2);
2342 
2343  // Test that the second sequence is correct.
2344  value = s->GetValue();
2345  NS_TEST_ASSERT_MSG_EQ_TOL(value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2346  value = s->GetValue();
2347  NS_TEST_ASSERT_MSG_EQ_TOL(value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2348  value = s->GetValue();
2349  NS_TEST_ASSERT_MSG_EQ_TOL(value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2350  value = s->GetValue();
2351  NS_TEST_ASSERT_MSG_EQ_TOL(value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2352  value = s->GetValue();
2353 }
2354 
2360 {
2361  public:
2362  // Constructor
2364 
2365  private:
2366  // Inherited
2367  void DoRun() override;
2368 
2373  static constexpr double TOLERANCE{1e-2};
2374 };
2375 
2377  : TestCaseBase("Empirical Random Variable Stream Generator")
2378 {
2379 }
2380 
2381 void
2383 {
2384  NS_LOG_FUNCTION(this);
2385  SetTestSuiteSeed();
2386 
2387  // Create the RNG with a uniform distribution between 0 and 10.
2388  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable>();
2389  x->SetInterpolate(false);
2390  x->CDF(0.0, 0.0);
2391  x->CDF(5.0, 0.25);
2392  x->CDF(10.0, 1.0);
2393 
2394  // Check that only the correct values are returned
2395  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2396  {
2397  double value = x->GetValue();
2398  NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2399  true,
2400  "Incorrect value returned, expected only 5 or 10.");
2401  }
2402 
2403  // Calculate the mean of the sampled values.
2404  double valueMean = Average(x);
2405 
2406  // The expected distribution with sampled values is
2407  // Value Probability
2408  // 5 25%
2409  // 10 75%
2410  //
2411  // The expected mean is
2412  //
2413  // E[value] = 5 * 25% + 10 * 75% = 8.75
2414  //
2415  // Test that values have approximately the right mean value.
2416  double expectedMean = 8.75;
2417  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2418  expectedMean,
2419  expectedMean * TOLERANCE,
2420  "Wrong mean value.");
2421 
2422  // Calculate the mean of the interpolated values.
2423  x->SetInterpolate(true);
2424  valueMean = Average(x);
2425 
2426  // The expected distribution (with interpolation) is
2427  // Bin Probability
2428  // [0, 5) 25%
2429  // [5, 10) 75%
2430  //
2431  // Each bin is uniformly sampled, so the average of the samples in the
2432  // bin is the center of the bin.
2433  //
2434  // The expected mean is
2435  //
2436  // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2437  //
2438  expectedMean = 6.25;
2439 
2440  // Test that values have approximately the right mean value.
2441  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2442  expectedMean,
2443  expectedMean * TOLERANCE,
2444  "Wrong mean value.");
2445 
2446  // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2447  Ptr<EmpiricalRandomVariable> y = CreateObject<EmpiricalRandomVariable>();
2448  y->SetInterpolate(false);
2449  y->CDF(-1.0, 0.0);
2450  y->CDF(0.0, 0.5);
2451  y->CDF(1.0, 1.0);
2452  NS_TEST_ASSERT_MSG_LT(y->GetValue(), 2, "Empirical variable with negative domain");
2453 }
2454 
2460 {
2461  public:
2462  // Constructor
2464 
2465  private:
2466  // Inherited
2467  void DoRun() override;
2468 
2473  static constexpr double TOLERANCE{1e-2};
2474 };
2475 
2477  : TestCaseBase("EmpiricalAntithetic Random Variable Stream Generator")
2478 {
2479 }
2480 
2481 void
2483 {
2484  NS_LOG_FUNCTION(this);
2485  SetTestSuiteSeed();
2486 
2487  // Create the RNG with a uniform distribution between 0 and 10.
2488  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable>();
2489  x->SetInterpolate(false);
2490  x->CDF(0.0, 0.0);
2491  x->CDF(5.0, 0.25);
2492  x->CDF(10.0, 1.0);
2493 
2494  // Make this generate antithetic values.
2495  x->SetAttribute("Antithetic", BooleanValue(true));
2496 
2497  // Check that only the correct values are returned
2498  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2499  {
2500  double value = x->GetValue();
2501  NS_TEST_EXPECT_MSG_EQ((value == 5) || (value == 10),
2502  true,
2503  "Incorrect value returned, expected only 5 or 10.");
2504  }
2505 
2506  // Calculate the mean of these values.
2507  double valueMean = Average(x);
2508  // Expected
2509  // E[value] = 5 * 25% + 10 * 75% = 8.75
2510  double expectedMean = 8.75;
2511  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2512  expectedMean,
2513  expectedMean * TOLERANCE,
2514  "Wrong mean value.");
2515 
2516  // Check interpolated sampling
2517  x->SetInterpolate(true);
2518  valueMean = Average(x);
2519 
2520  // The expected value for the mean of the values returned by this
2521  // empirical distribution with interpolation is
2522  //
2523  // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2524  //
2525  expectedMean = 6.25;
2526 
2527  // Test that values have approximately the right mean value.
2528  NS_TEST_ASSERT_MSG_EQ_TOL(valueMean,
2529  expectedMean,
2530  expectedMean * TOLERANCE,
2531  "Wrong mean value.");
2532 }
2533 
2539 {
2540  public:
2541  // Constructor
2543 
2544  private:
2545  // Inherited
2546  void DoRun() override;
2547 };
2548 
2550  : TestCaseBase("NormalRandomVariable caching of parameters")
2551 {
2552 }
2553 
2554 void
2556 {
2557  NS_LOG_FUNCTION(this);
2558  SetTestSuiteSeed();
2559 
2560  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable>();
2561  double v1 = n->GetValue(-10, 1, 10); // Mean -10, variance 1, bounded to [-20,0]
2562  double v2 = n->GetValue(10, 1, 10); // Mean 10, variance 1, bounded to [0,20]
2563 
2564  NS_TEST_ASSERT_MSG_LT(v1, 0, "Incorrect value returned, expected < 0");
2565  NS_TEST_ASSERT_MSG_GT(v2, 0, "Incorrect value returned, expected > 0");
2566 }
2567 
2574 {
2575  public:
2576  // Constructor
2578 };
2579 
2581  : TestSuite("random-variable-stream-generators", UNIT)
2582 {
2599  /*
2600  AddTestCase (new LogNormalAntitheticTestCase);
2601  */
2606  /*
2607  AddTestCase (new GammaAntitheticTestCase);
2608  */
2620 }
2621 
2623 
2624 } // namespace RandomVariable
2625 
2626 } // namespace test
2627 
2628 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
AttributeValue implementation for Boolean.
Definition: boolean.h:37
double GetValue(double constant)
Get the next random value drawn from the distribution.
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
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
virtual double GetValue()=0
Get the next random value drawn from the distribution.
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:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
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.
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...
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.
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.
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:709
#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:144
#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:251
#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:564
#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:874
#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:337
static RandomVariableSuite randomVariableSuite
Static variable for test initialization.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
value
Definition: second.py:41