A Discrete-Event Network Simulator
API
random-variable-stream-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009-12 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * This file is based on rng-test-suite.cc.
19  *
20  * Modified by Mitch Watrous <watrous@u.washington.edu>
21  *
22  */
23 
24 
25 #include <gsl/gsl_cdf.h>
26 #include <gsl/gsl_histogram.h>
27 #include <gsl/gsl_sf_zeta.h>
28 #include <ctime>
29 #include <fstream>
30 #include <cmath>
31 
32 #include "ns3/boolean.h"
33 #include "ns3/double.h"
34 #include "ns3/string.h"
35 #include "ns3/integer.h"
36 #include "ns3/test.h"
37 #include "ns3/log.h"
38 #include "ns3/rng-seed-manager.h"
39 #include "ns3/random-variable-stream.h"
40 
41 using namespace ns3;
42 
43 NS_LOG_COMPONENT_DEFINE ("RandomVariableStreamGenerators");
44 
45 namespace {
46 
47 void
48 FillHistoRangeUniformly (double *array, uint32_t n, double start, double end)
49 {
50  double increment = (end - start) / (n - 1.);
51  double d = start;
52 
53  for (uint32_t i = 0; i < n; ++i)
54  {
55  array[i] = d;
56  d += increment;
57  }
58 }
59 
60 bool seedSet = false;
61 
62 // Over time, this test suite is designed to be run with varying seed
63 // values so that the distributions can be evaluated with chi-squared
64 // tests. To enable this, normal invocation of this test suite will
65 // result in a seed value corresponding to the seconds since epoch
66 // (time (0) from ctime). Note: this is not a recommended practice for
67 // seeding normal simulations, as described in the ns-3 manual, but
68 // suits our purposes here.
69 //
70 // However, we also want to provide the ability to run this test suite
71 // with a repeatable value, such as when the seed or run number is configured
72 // to a specific value. Therefore, we adopt the following policy. When
73 // the test program is being run with the default global values for seed
74 // and run number, this function will instead pick a random, time-based
75 // seed for use within this test suite. If the global values for seed or
76 // run number have been configured differently from the default values,
77 // the global seed value will be used instead of the time-based one.
78 //
79 // For example, this command will cause this test suite to use the
80 // deterministic value of seed=3 every time:
81 // NS_GLOBAL_VALUE="RngSeed=3" ./test.py -s random-variable-stream-generators
82 // or equivalently (to see log output):
83 // NS_LOG="RandomVariableStreamGenerators" NS_GLOBAL_VALUE="RngSeed=3" ./waf --run "test-runner --suite=random-variable-stream-generators"
84 // Similarly, if the value of RngRun is not set to 1, the globals will be
85 // used.
86 //
87 void
89 {
90  if (seedSet == false)
91  {
92  uint32_t seed;
93  if (RngSeedManager::GetSeed () == 1 && RngSeedManager::GetRun () == 1)
94  {
95  seed = static_cast<uint32_t> (time (0));
96  seedSet = true;
97  NS_LOG_DEBUG ("Global seed and run number are default; seeding with time of day: " << seed);
98 
99  }
100  else
101  {
102  seed = RngSeedManager::GetSeed ();
103  seedSet = true;
104  NS_LOG_DEBUG ("Global seed and run number are not default; using the non-default values seed: " <<
105  seed << " and run: " << RngSeedManager::GetRun ());
106  }
107  SeedManager::SetSeed (seed);
108  }
109 }
110 
111 } // anonymous namespace
112 
113 // ===========================================================================
114 // Test case for uniform distribution random variable stream generator
115 // ===========================================================================
117 {
118 public:
119  // We want the number of observations in each bin to be > 5
120  // The following values should yield many more than 5 per bin
121  static const uint32_t N_BINS = 100;
122  static const uint32_t N_MEASUREMENTS = 1000000;
123 
124  // Number of times to wrap the Chi-Squared test and retry
125  static const uint32_t N_RUNS = 2;
126 
129 
130  double ChiSquaredTest (Ptr<UniformRandomVariable> u);
131 
132 private:
133  virtual void DoRun (void);
134 };
135 
137  : TestCase ("Uniform Random Variable Stream Generator")
138 {}
139 
141 {}
142 
143 double
145 {
146  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
147 
148  // Note that this assumes that the range for u is [0,1], which is
149  // the default range for this distribution.
150  gsl_histogram_set_ranges_uniform (h, 0., 1.);
151 
152  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
153  {
154  gsl_histogram_increment (h, u->GetValue ());
155  }
156 
157  double tmp[N_BINS];
158 
159  double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
160 
161  for (uint32_t i = 0; i < N_BINS; ++i)
162  {
163  tmp[i] = gsl_histogram_get (h, i);
164  tmp[i] -= expected;
165  tmp[i] *= tmp[i];
166  tmp[i] /= expected;
167  }
168 
169  gsl_histogram_free (h);
170 
171  double chiSquared = 0;
172 
173  for (uint32_t i = 0; i < N_BINS; ++i)
174  {
175  chiSquared += tmp[i];
176  }
177 
178  return chiSquared;
179 }
180 
181 void
183 {
184  SetTestSuiteSeed ();
185 
186  double confidence = 0.99;
187  double maxStatistic = gsl_cdf_chisq_Pinv (confidence, (N_BINS - 1));
188  NS_LOG_DEBUG ("Chi square required at " << confidence << " confidence for " << N_BINS << " bins is " << maxStatistic);
189 
190  double result = maxStatistic;
191  // If chi-squared test fails, re-try it up to N_RUNS times
192  for (uint32_t i = 0; i < N_RUNS; ++i)
193  {
194  Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
195  result = ChiSquaredTest (u);
196  NS_LOG_DEBUG ("Chi square result is " << result);
197  if (result < maxStatistic)
198  {
199  break;
200  }
201  }
202 
203  NS_TEST_ASSERT_MSG_LT (result, maxStatistic, "Chi-squared statistic out of range");
204 
205  double min = 0.0;
206  double max = 10.0;
207  double value;
208 
209  // Create the RNG with the specified range.
210  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
211 
212  x->SetAttribute ("Min", DoubleValue (min));
213  x->SetAttribute ("Max", DoubleValue (max));
214 
215  // Test that values are always within the range:
216  //
217  // [min, max)
218  //
219  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
220  {
221  value = x->GetValue ();
222  NS_TEST_ASSERT_MSG_EQ ((value >= min), true, "Value less than minimum.");
223  NS_TEST_ASSERT_MSG_LT (value, max, "Value greater than or equal to maximum.");
224  }
225 
226  // Boundary checking on GetInteger; should be [min,max]; from bug 1964
227  static const uint32_t UNIFORM_INTEGER_MIN = 0;
228  static const uint32_t UNIFORM_INTEGER_MAX = 4294967295U;
229  // [0,0] should return 0
230  uint32_t intValue;
231  intValue = x->GetInteger (UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN);
232  NS_TEST_ASSERT_MSG_EQ (intValue, UNIFORM_INTEGER_MIN, "Uniform RV GetInteger boundary testing");
233  // [UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX] should return UNIFORM_INTEGER_MAX
234  intValue = x->GetInteger (UNIFORM_INTEGER_MAX, UNIFORM_INTEGER_MAX);
235  NS_TEST_ASSERT_MSG_EQ (intValue, UNIFORM_INTEGER_MAX, "Uniform RV GetInteger boundary testing");
236  // [0,1] should return mix of 0 or 1
237  intValue = 0;
238  for (int i = 0; i < 20; i++)
239  {
240  intValue += x->GetInteger (UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MIN + 1);
241  }
242  NS_TEST_ASSERT_MSG_GT (intValue, 0, "Uniform RV GetInteger boundary testing");
243  NS_TEST_ASSERT_MSG_LT (intValue, 20, "Uniform RV GetInteger boundary testing");
244  // [MAX-1,MAX] should return mix of MAX-1 or MAX
245  uint32_t count = 0;
246  for (int i = 0; i < 20; i++)
247  {
248  intValue = x->GetInteger (UNIFORM_INTEGER_MAX - 1, UNIFORM_INTEGER_MAX);
249  if (intValue == UNIFORM_INTEGER_MAX)
250  {
251  count++;
252  }
253  }
254  NS_TEST_ASSERT_MSG_GT (count, 0, "Uniform RV GetInteger boundary testing");
255  NS_TEST_ASSERT_MSG_LT (count, 20, "Uniform RV GetInteger boundary testing");
256  // multiple [0,UNIFORM_INTEGER_MAX] should return non-zero
257  intValue = x->GetInteger (UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
258  uint32_t intValue2 = x->GetInteger (UNIFORM_INTEGER_MIN, UNIFORM_INTEGER_MAX);
259  NS_TEST_ASSERT_MSG_GT (intValue + intValue2, 0, "Uniform RV GetInteger boundary testing");
260 
261 }
262 
263 // ===========================================================================
264 // Test case for antithetic uniform distribution random variable stream generator
265 // ===========================================================================
267 {
268 public:
269  static const uint32_t N_RUNS = 5;
270  static const uint32_t N_BINS = 50;
271  static const uint32_t N_MEASUREMENTS = 1000000;
272 
275 
277 
278 private:
279  virtual void DoRun (void);
280 };
281 
283  : TestCase ("Antithetic Uniform Random Variable Stream Generator")
284 {}
285 
287 {}
288 
289 double
291 {
292  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
293 
294  // Note that this assumes that the range for u is [0,1], which is
295  // the default range for this distribution.
296  gsl_histogram_set_ranges_uniform (h, 0., 1.);
297 
298  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
299  {
300  gsl_histogram_increment (h, u->GetValue ());
301  }
302 
303  double tmp[N_BINS];
304 
305  double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
306 
307  for (uint32_t i = 0; i < N_BINS; ++i)
308  {
309  tmp[i] = gsl_histogram_get (h, i);
310  tmp[i] -= expected;
311  tmp[i] *= tmp[i];
312  tmp[i] /= expected;
313  }
314 
315  gsl_histogram_free (h);
316 
317  double chiSquared = 0;
318 
319  for (uint32_t i = 0; i < N_BINS; ++i)
320  {
321  chiSquared += tmp[i];
322  }
323 
324  return chiSquared;
325 }
326 
327 void
329 {
330  SetTestSuiteSeed ();
331 
332  double sum = 0.;
333  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
334 
335  for (uint32_t i = 0; i < N_RUNS; ++i)
336  {
337  Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
338 
339  // Make this generate antithetic values.
340  u->SetAttribute ("Antithetic", BooleanValue (true));
341 
342  double result = ChiSquaredTest (u);
343  sum += result;
344  }
345 
346  sum /= (double)N_RUNS;
347 
348  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
349 
350  double min = 0.0;
351  double max = 10.0;
352  double value;
353 
354  // Create the RNG with the specified range.
355  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
356 
357  // Make this generate antithetic values.
358  x->SetAttribute ("Antithetic", BooleanValue (true));
359 
360  x->SetAttribute ("Min", DoubleValue (min));
361  x->SetAttribute ("Max", DoubleValue (max));
362 
363  // Test that values are always within the range:
364  //
365  // [min, max)
366  //
367  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
368  {
369  value = x->GetValue ();
370  NS_TEST_ASSERT_MSG_EQ ((value >= min), true, "Value less than minimum.");
371  NS_TEST_ASSERT_MSG_LT (value, max, "Value greater than or equal to maximum.");
372  }
373 
374 
375 }
376 
377 // ===========================================================================
378 // Test case for constant random variable stream generator
379 // ===========================================================================
381 {
382 public:
383  static const uint32_t N_MEASUREMENTS = 1000000;
384  static const double TOLERANCE;
385 
388 
389 private:
390  virtual void DoRun (void);
391 };
392 
394 
396  : TestCase ("Constant Random Variable Stream Generator")
397 {}
398 
400 {}
401 
402 void
404 {
405  SetTestSuiteSeed ();
406 
407  Ptr<ConstantRandomVariable> c = CreateObject<ConstantRandomVariable> ();
408 
409  double constant;
410 
411  // Test that the constant value can be changed using its attribute.
412  constant = 10.0;
413  c->SetAttribute ("Constant", DoubleValue (constant));
414  NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed");
415  c->SetAttribute ("Constant", DoubleValue (20.0));
416  NS_TEST_ASSERT_MSG_NE (c->GetValue (), constant, "Constant value not changed");
417 
418  // Test that the constant value does not change.
419  constant = c->GetValue ();
420  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
421  {
422  NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed in loop");
423  }
424 }
425 
426 // ===========================================================================
427 // Test case for sequential random variable stream generator
428 // ===========================================================================
430 {
431 public:
432  static const double TOLERANCE;
433 
436 
437 private:
438  virtual void DoRun (void);
439 };
440 
442 
444  : TestCase ("Sequential Random Variable Stream Generator")
445 {}
446 
448 {}
449 
450 void
452 {
453  SetTestSuiteSeed ();
454 
455  Ptr<SequentialRandomVariable> s = CreateObject<SequentialRandomVariable> ();
456 
457  // The following four attributes should give the sequence
458  //
459  // 4, 4, 7, 7, 10, 10
460  //
461  s->SetAttribute ("Min", DoubleValue (4));
462  s->SetAttribute ("Max", DoubleValue (11));
463  s->SetAttribute ("Increment", StringValue ("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
464  s->SetAttribute ("Consecutive", IntegerValue (2));
465 
466  double value;
467 
468  // Test that the sequencet is correct.
469  value = s->GetValue ();
470  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 1 wrong.");
471  value = s->GetValue ();
472  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 2 wrong.");
473  value = s->GetValue ();
474  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 3 wrong.");
475  value = s->GetValue ();
476  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 4 wrong.");
477  value = s->GetValue ();
478  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 5 wrong.");
479  value = s->GetValue ();
480  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 6 wrong.");
481 
482 }
483 
484 // ===========================================================================
485 // Test case for normal distribution random variable stream generator
486 // ===========================================================================
488 {
489 public:
490  static const uint32_t N_RUNS = 5;
491  static const uint32_t N_BINS = 50;
492  static const uint32_t N_MEASUREMENTS = 1000000;
493 
496 
498 
499 private:
500  virtual void DoRun (void);
501 };
502 
504  : TestCase ("Normal Random Variable Stream Generator")
505 {}
506 
508 {}
509 
510 double
512 {
513  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
514 
515  double range[N_BINS + 1];
516  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
517  range[0] = -std::numeric_limits<double>::max ();
519 
520  gsl_histogram_set_ranges (h, range, N_BINS + 1);
521 
522  double expected[N_BINS];
523 
524  // Note that this assumes that n has mean equal to zero and standard
525  // deviation equal to one, which are their default values for this
526  // distribution.
527  double sigma = 1.;
528 
529  for (uint32_t i = 0; i < N_BINS; ++i)
530  {
531  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
532  expected[i] *= N_MEASUREMENTS;
533  }
534 
535  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
536  {
537  gsl_histogram_increment (h, n->GetValue ());
538  }
539 
540  double tmp[N_BINS];
541 
542  for (uint32_t i = 0; i < N_BINS; ++i)
543  {
544  tmp[i] = gsl_histogram_get (h, i);
545  tmp[i] -= expected[i];
546  tmp[i] *= tmp[i];
547  tmp[i] /= expected[i];
548  }
549 
550  gsl_histogram_free (h);
551 
552  double chiSquared = 0;
553 
554  for (uint32_t i = 0; i < N_BINS; ++i)
555  {
556  chiSquared += tmp[i];
557  }
558 
559  return chiSquared;
560 }
561 
562 void
564 {
565  SetTestSuiteSeed ();
566 
567  double sum = 0.;
568  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
569 
570  for (uint32_t i = 0; i < N_RUNS; ++i)
571  {
572  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
573  double result = ChiSquaredTest (n);
574  sum += result;
575  }
576 
577  sum /= (double)N_RUNS;
578 
579  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
580 
581  double mean = 5.0;
582  double variance = 2.0;
583  double value;
584 
585  // Create the RNG with the specified range.
586  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
587  x->SetAttribute ("Mean", DoubleValue (mean));
588  x->SetAttribute ("Variance", DoubleValue (variance));
589 
590  // Calculate the mean of these values.
591  sum = 0.0;
592  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
593  {
594  value = x->GetValue ();
595  sum += value;
596  }
597  double valueMean = sum / N_MEASUREMENTS;
598 
599  // The expected value for the mean of the values returned by a
600  // normally distributed random variable is equal to mean.
601  double expectedMean = mean;
602 
603  // Test that values have approximately the right mean value.
604  double TOLERANCE = expectedMean * 1e-2;
605  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
606 }
607 
608 // ===========================================================================
609 // Test case for antithetic normal distribution random variable stream generator
610 // ===========================================================================
612 {
613 public:
614  static const uint32_t N_RUNS = 5;
615  static const uint32_t N_BINS = 50;
616  static const uint32_t N_MEASUREMENTS = 1000000;
617 
620 
622 
623 private:
624  virtual void DoRun (void);
625 };
626 
628  : TestCase ("Antithetic Normal Random Variable Stream Generator")
629 {}
630 
632 {}
633 
634 double
636 {
637  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
638 
639  double range[N_BINS + 1];
640  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
641  range[0] = -std::numeric_limits<double>::max ();
643 
644  gsl_histogram_set_ranges (h, range, N_BINS + 1);
645 
646  double expected[N_BINS];
647 
648  // Note that this assumes that n has mean equal to zero and standard
649  // deviation equal to one, which are their default values for this
650  // distribution.
651  double sigma = 1.;
652 
653  for (uint32_t i = 0; i < N_BINS; ++i)
654  {
655  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
656  expected[i] *= N_MEASUREMENTS;
657  }
658 
659  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
660  {
661  gsl_histogram_increment (h, n->GetValue ());
662  }
663 
664  double tmp[N_BINS];
665 
666  for (uint32_t i = 0; i < N_BINS; ++i)
667  {
668  tmp[i] = gsl_histogram_get (h, i);
669  tmp[i] -= expected[i];
670  tmp[i] *= tmp[i];
671  tmp[i] /= expected[i];
672  }
673 
674  gsl_histogram_free (h);
675 
676  double chiSquared = 0;
677 
678  for (uint32_t i = 0; i < N_BINS; ++i)
679  {
680  chiSquared += tmp[i];
681  }
682 
683  return chiSquared;
684 }
685 
686 void
688 {
689  SetTestSuiteSeed ();
690 
691  double sum = 0.;
692  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
693 
694  for (uint32_t i = 0; i < N_RUNS; ++i)
695  {
696  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
697 
698  // Make this generate antithetic values.
699  n->SetAttribute ("Antithetic", BooleanValue (true));
700 
701  double result = ChiSquaredTest (n);
702  sum += result;
703  }
704 
705  sum /= (double)N_RUNS;
706 
707  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
708 
709  double mean = 5.0;
710  double variance = 2.0;
711  double value;
712 
713  // Create the RNG with the specified range.
714  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
715  x->SetAttribute ("Mean", DoubleValue (mean));
716  x->SetAttribute ("Variance", DoubleValue (variance));
717 
718  // Make this generate antithetic values.
719  x->SetAttribute ("Antithetic", BooleanValue (true));
720 
721  // Calculate the mean of these values.
722  sum = 0.0;
723  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
724  {
725  value = x->GetValue ();
726  sum += value;
727  }
728  double valueMean = sum / N_MEASUREMENTS;
729 
730  // The expected value for the mean of the values returned by a
731  // normally distributed random variable is equal to mean.
732  double expectedMean = mean;
733 
734  // Test that values have approximately the right mean value.
735  double TOLERANCE = expectedMean * 1e-2;
736  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
737 }
738 
739 // ===========================================================================
740 // Test case for exponential distribution random variable stream generator
741 // ===========================================================================
743 {
744 public:
745  static const uint32_t N_RUNS = 5;
746  static const uint32_t N_BINS = 50;
747  static const uint32_t N_MEASUREMENTS = 1000000;
748 
751 
753 
754 private:
755  virtual void DoRun (void);
756 };
757 
759  : TestCase ("Exponential Random Variable Stream Generator")
760 {}
761 
763 {}
764 
765 double
767 {
768  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
769 
770  double range[N_BINS + 1];
771  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
773 
774  gsl_histogram_set_ranges (h, range, N_BINS + 1);
775 
776  double expected[N_BINS];
777 
778  // Note that this assumes that e has mean equal to one, which is the
779  // default value for this distribution.
780  double mu = 1.;
781 
782  for (uint32_t i = 0; i < N_BINS; ++i)
783  {
784  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
785  expected[i] *= N_MEASUREMENTS;
786  }
787 
788  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
789  {
790  gsl_histogram_increment (h, e->GetValue ());
791  }
792 
793  double tmp[N_BINS];
794 
795  for (uint32_t i = 0; i < N_BINS; ++i)
796  {
797  tmp[i] = gsl_histogram_get (h, i);
798  tmp[i] -= expected[i];
799  tmp[i] *= tmp[i];
800  tmp[i] /= expected[i];
801  }
802 
803  gsl_histogram_free (h);
804 
805  double chiSquared = 0;
806 
807  for (uint32_t i = 0; i < N_BINS; ++i)
808  {
809  chiSquared += tmp[i];
810  }
811 
812  return chiSquared;
813 }
814 
815 void
817 {
818  SetTestSuiteSeed ();
819 
820  double sum = 0.;
821  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
822 
823  for (uint32_t i = 0; i < N_RUNS; ++i)
824  {
825  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
826  double result = ChiSquaredTest (e);
827  sum += result;
828  }
829 
830  sum /= (double)N_RUNS;
831 
832  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
833 
834  double mean = 3.14;
835  double bound = 0.0;
836  double value;
837 
838  // Create the RNG with the specified range.
839  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
840  x->SetAttribute ("Mean", DoubleValue (mean));
841  x->SetAttribute ("Bound", DoubleValue (bound));
842 
843  // Calculate the mean of these values.
844  sum = 0.0;
845  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
846  {
847  value = x->GetValue ();
848  sum += value;
849  }
850  double valueMean = sum / N_MEASUREMENTS;
851 
852  // Test that values have approximately the right mean value.
853  double TOLERANCE = mean * 1e-2;
854  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
855 }
856 
857 // ===========================================================================
858 // Test case for antithetic exponential distribution random variable stream generator
859 // ===========================================================================
861 {
862 public:
863  static const uint32_t N_RUNS = 5;
864  static const uint32_t N_BINS = 50;
865  static const uint32_t N_MEASUREMENTS = 1000000;
866 
869 
871 
872 private:
873  virtual void DoRun (void);
874 };
875 
877  : TestCase ("Antithetic Exponential Random Variable Stream Generator")
878 {}
879 
881 {}
882 
883 double
885 {
886  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
887 
888  double range[N_BINS + 1];
889  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
891 
892  gsl_histogram_set_ranges (h, range, N_BINS + 1);
893 
894  double expected[N_BINS];
895 
896  // Note that this assumes that e has mean equal to one, which is the
897  // default value for this distribution.
898  double mu = 1.;
899 
900  for (uint32_t i = 0; i < N_BINS; ++i)
901  {
902  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
903  expected[i] *= N_MEASUREMENTS;
904  }
905 
906  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
907  {
908  gsl_histogram_increment (h, e->GetValue ());
909  }
910 
911  double tmp[N_BINS];
912 
913  for (uint32_t i = 0; i < N_BINS; ++i)
914  {
915  tmp[i] = gsl_histogram_get (h, i);
916  tmp[i] -= expected[i];
917  tmp[i] *= tmp[i];
918  tmp[i] /= expected[i];
919  }
920 
921  gsl_histogram_free (h);
922 
923  double chiSquared = 0;
924 
925  for (uint32_t i = 0; i < N_BINS; ++i)
926  {
927  chiSquared += tmp[i];
928  }
929 
930  return chiSquared;
931 }
932 
933 void
935 {
936  SetTestSuiteSeed ();
937 
938  double sum = 0.;
939  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
940 
941  for (uint32_t i = 0; i < N_RUNS; ++i)
942  {
943  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
944 
945  // Make this generate antithetic values.
946  e->SetAttribute ("Antithetic", BooleanValue (true));
947 
948  double result = ChiSquaredTest (e);
949  sum += result;
950  }
951 
952  sum /= (double)N_RUNS;
953 
954  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
955 
956  double mean = 3.14;
957  double bound = 0.0;
958  double value;
959 
960  // Create the RNG with the specified range.
961  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
962  x->SetAttribute ("Mean", DoubleValue (mean));
963  x->SetAttribute ("Bound", DoubleValue (bound));
964 
965  // Make this generate antithetic values.
966  x->SetAttribute ("Antithetic", BooleanValue (true));
967 
968  // Calculate the mean of these values.
969  sum = 0.0;
970  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
971  {
972  value = x->GetValue ();
973  sum += value;
974  }
975  double valueMean = sum / N_MEASUREMENTS;
976 
977  // Test that values have approximately the right mean value.
978  double TOLERANCE = mean * 1e-2;
979  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
980 }
981 
982 // ===========================================================================
983 // Test case for Pareto distribution random variable stream generator
984 // ===========================================================================
986 {
987 public:
988  static const uint32_t N_RUNS = 5;
989  static const uint32_t N_BINS = 50;
990  static const uint32_t N_MEASUREMENTS = 1000000;
991 
994 
996 
997 private:
998  virtual void DoRun (void);
999 };
1000 
1002  : TestCase ("Pareto Random Variable Stream Generator")
1003 {}
1004 
1006 {}
1007 
1008 double
1010 {
1011  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1012 
1013  double range[N_BINS + 1];
1014  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1016 
1017  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1018 
1019  double expected[N_BINS];
1020 
1021  double shape = 2.0;
1022  double scale = 1.0;
1023 
1024  for (uint32_t i = 0; i < N_BINS; ++i)
1025  {
1026  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
1027  expected[i] *= N_MEASUREMENTS;
1028  }
1029 
1030  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1031  {
1032  gsl_histogram_increment (h, p->GetValue ());
1033  }
1034 
1035  double tmp[N_BINS];
1036 
1037  for (uint32_t i = 0; i < N_BINS; ++i)
1038  {
1039  tmp[i] = gsl_histogram_get (h, i);
1040  tmp[i] -= expected[i];
1041  tmp[i] *= tmp[i];
1042  tmp[i] /= expected[i];
1043  }
1044 
1045  gsl_histogram_free (h);
1046 
1047  double chiSquared = 0;
1048 
1049  for (uint32_t i = 0; i < N_BINS; ++i)
1050  {
1051  chiSquared += tmp[i];
1052  }
1053 
1054  return chiSquared;
1055 }
1056 
1057 void
1059 {
1060  SetTestSuiteSeed ();
1061 
1062  double sum = 0.;
1063  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1064 
1065  for (uint32_t i = 0; i < N_RUNS; ++i)
1066  {
1067  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
1068  double result = ChiSquaredTest (e);
1069  sum += result;
1070  }
1071 
1072  sum /= (double)N_RUNS;
1073 
1074  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1075 
1076  double shape = 2.0;
1077  double scale = 1.0;
1078  double value;
1079 
1080  // Create the RNG with the specified range.
1081  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1082  x->SetAttribute ("Shape", DoubleValue (shape));
1083  x->SetAttribute ("Scale", DoubleValue (scale));
1084 
1085  // Calculate the mean of these values.
1086  sum = 0.0;
1087  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1088  {
1089  value = x->GetValue ();
1090  sum += value;
1091  }
1092  double valueMean = sum / N_MEASUREMENTS;
1093 
1094  // The expected value for the mean is given by
1095  //
1096  // shape * scale
1097  // E[value] = --------------- ,
1098  // shape - 1
1099  //
1100  // where
1101  //
1102  // scale = mean * (shape - 1.0) / shape .
1103  double expectedMean = (shape * scale) / (shape - 1.0);
1104 
1105  // Test that values have approximately the right mean value.
1106  double TOLERANCE = expectedMean * 1e-2;
1107  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1108 }
1109 
1110 // ===========================================================================
1111 // Test case for antithetic Pareto distribution random variable stream generator
1112 // ===========================================================================
1114 {
1115 public:
1116  static const uint32_t N_RUNS = 5;
1117  static const uint32_t N_BINS = 50;
1118  static const uint32_t N_MEASUREMENTS = 1000000;
1119 
1122 
1124 
1125 private:
1126  virtual void DoRun (void);
1127 };
1128 
1130  : TestCase ("Antithetic Pareto Random Variable Stream Generator")
1131 {}
1132 
1134 {}
1135 
1136 double
1138 {
1139  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1140 
1141  double range[N_BINS + 1];
1142  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1144 
1145  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1146 
1147  double expected[N_BINS];
1148 
1149  double shape = 2.0;
1150  double scale = 1.0;
1151 
1152  for (uint32_t i = 0; i < N_BINS; ++i)
1153  {
1154  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
1155  expected[i] *= N_MEASUREMENTS;
1156  }
1157 
1158  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1159  {
1160  gsl_histogram_increment (h, p->GetValue ());
1161  }
1162 
1163  double tmp[N_BINS];
1164 
1165  for (uint32_t i = 0; i < N_BINS; ++i)
1166  {
1167  tmp[i] = gsl_histogram_get (h, i);
1168  tmp[i] -= expected[i];
1169  tmp[i] *= tmp[i];
1170  tmp[i] /= expected[i];
1171  }
1172 
1173  gsl_histogram_free (h);
1174 
1175  double chiSquared = 0;
1176 
1177  for (uint32_t i = 0; i < N_BINS; ++i)
1178  {
1179  chiSquared += tmp[i];
1180  }
1181 
1182  return chiSquared;
1183 }
1184 
1185 void
1187 {
1188  SetTestSuiteSeed ();
1189 
1190  double sum = 0.;
1191  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1192 
1193  for (uint32_t i = 0; i < N_RUNS; ++i)
1194  {
1195  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
1196 
1197  // Make this generate antithetic values.
1198  e->SetAttribute ("Antithetic", BooleanValue (true));
1199 
1200  double result = ChiSquaredTest (e);
1201  sum += result;
1202  }
1203 
1204  sum /= (double)N_RUNS;
1205 
1206  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1207 
1208  double shape = 2.0;
1209  double scale = 1.0;
1210  double value;
1211 
1212  // Create the RNG with the specified range.
1213  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1214  x->SetAttribute ("Shape", DoubleValue (shape));
1215  x->SetAttribute ("Scale", DoubleValue (scale));
1216 
1217  // Make this generate antithetic values.
1218  x->SetAttribute ("Antithetic", BooleanValue (true));
1219 
1220  // Calculate the mean of these values.
1221  sum = 0.0;
1222  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1223  {
1224  value = x->GetValue ();
1225  sum += value;
1226  }
1227  double valueMean = sum / N_MEASUREMENTS;
1228 
1229  // The expected value for the mean is given by
1230  //
1231  // shape * scale
1232  // E[value] = --------------- ,
1233  // shape - 1
1234  //
1235  // where
1236  //
1237  // scale = mean * (shape - 1.0) / shape .
1238  //
1239  double expectedMean = (shape * scale) / (shape - 1.0);
1240 
1241  // Test that values have approximately the right mean value.
1242  double TOLERANCE = expectedMean * 1e-2;
1243  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1244 }
1245 
1246 // ===========================================================================
1247 // Test case for Weibull distribution random variable stream generator
1248 // ===========================================================================
1250 {
1251 public:
1252  static const uint32_t N_RUNS = 5;
1253  static const uint32_t N_BINS = 50;
1254  static const uint32_t N_MEASUREMENTS = 1000000;
1255 
1258 
1260 
1261 private:
1262  virtual void DoRun (void);
1263 };
1264 
1266  : TestCase ("Weibull Random Variable Stream Generator")
1267 {}
1268 
1270 {}
1271 
1272 double
1274 {
1275  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1276 
1277  double range[N_BINS + 1];
1278  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1280 
1281  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1282 
1283  double expected[N_BINS];
1284 
1285  // Note that this assumes that p has shape equal to one and scale
1286  // equal to one, which are their default values for this
1287  // distribution.
1288  double a = 1.0;
1289  double b = 1.0;
1290 
1291  for (uint32_t i = 0; i < N_BINS; ++i)
1292  {
1293  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1294  expected[i] *= N_MEASUREMENTS;
1295  }
1296 
1297  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1298  {
1299  gsl_histogram_increment (h, p->GetValue ());
1300  }
1301 
1302  double tmp[N_BINS];
1303 
1304  for (uint32_t i = 0; i < N_BINS; ++i)
1305  {
1306  tmp[i] = gsl_histogram_get (h, i);
1307  tmp[i] -= expected[i];
1308  tmp[i] *= tmp[i];
1309  tmp[i] /= expected[i];
1310  }
1311 
1312  gsl_histogram_free (h);
1313 
1314  double chiSquared = 0;
1315 
1316  for (uint32_t i = 0; i < N_BINS; ++i)
1317  {
1318  chiSquared += tmp[i];
1319  }
1320 
1321  return chiSquared;
1322 }
1323 
1324 void
1326 {
1327  SetTestSuiteSeed ();
1328 
1329  double sum = 0.;
1330  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1331 
1332  for (uint32_t i = 0; i < N_RUNS; ++i)
1333  {
1334  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1335  double result = ChiSquaredTest (e);
1336  sum += result;
1337  }
1338 
1339  sum /= (double)N_RUNS;
1340 
1341  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1342 
1343  double scale = 5.0;
1344  double shape = 1.0;
1345  double value;
1346 
1347  // Create the RNG with the specified range.
1348  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1349  x->SetAttribute ("Scale", DoubleValue (scale));
1350  x->SetAttribute ("Shape", DoubleValue (shape));
1351 
1352  // Calculate the mean of these values.
1353  sum = 0.0;
1354  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1355  {
1356  value = x->GetValue ();
1357  sum += value;
1358  }
1359  double valueMean = sum / N_MEASUREMENTS;
1360 
1361  // The expected value for the mean of the values returned by a
1362  // Weibull distributed random variable is
1363  //
1364  // E[value] = scale * Gamma(1 + 1 / shape) ,
1365  //
1366  // where Gamma() is the Gamma function. Note that
1367  //
1368  // Gamma(n) = (n - 1)!
1369  //
1370  // if n is a positive integer.
1371  //
1372  // For this test,
1373  //
1374  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1375  // = Gamma(2)
1376  // = (2 - 1)!
1377  // = 1
1378  //
1379  // which means
1380  //
1381  // E[value] = scale .
1382  //
1383  double expectedMean = scale;
1384 
1385  // Test that values have approximately the right mean value.
1386  double TOLERANCE = expectedMean * 1e-2;
1387  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1388 }
1389 
1390 // ===========================================================================
1391 // Test case for antithetic Weibull distribution random variable stream generator
1392 // ===========================================================================
1394 {
1395 public:
1396  static const uint32_t N_RUNS = 5;
1397  static const uint32_t N_BINS = 50;
1398  static const uint32_t N_MEASUREMENTS = 1000000;
1399 
1402 
1404 
1405 private:
1406  virtual void DoRun (void);
1407 };
1408 
1410  : TestCase ("Antithetic Weibull Random Variable Stream Generator")
1411 {}
1412 
1414 {}
1415 
1416 double
1418 {
1419  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1420 
1421  double range[N_BINS + 1];
1422  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1424 
1425  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1426 
1427  double expected[N_BINS];
1428 
1429  // Note that this assumes that p has shape equal to one and scale
1430  // equal to one, which are their default values for this
1431  // distribution.
1432  double a = 1.0;
1433  double b = 1.0;
1434 
1435  for (uint32_t i = 0; i < N_BINS; ++i)
1436  {
1437  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1438  expected[i] *= N_MEASUREMENTS;
1439  }
1440 
1441  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1442  {
1443  gsl_histogram_increment (h, p->GetValue ());
1444  }
1445 
1446  double tmp[N_BINS];
1447 
1448  for (uint32_t i = 0; i < N_BINS; ++i)
1449  {
1450  tmp[i] = gsl_histogram_get (h, i);
1451  tmp[i] -= expected[i];
1452  tmp[i] *= tmp[i];
1453  tmp[i] /= expected[i];
1454  }
1455 
1456  gsl_histogram_free (h);
1457 
1458  double chiSquared = 0;
1459 
1460  for (uint32_t i = 0; i < N_BINS; ++i)
1461  {
1462  chiSquared += tmp[i];
1463  }
1464 
1465  return chiSquared;
1466 }
1467 
1468 void
1470 {
1471  SetTestSuiteSeed ();
1472 
1473  double sum = 0.;
1474  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1475 
1476  for (uint32_t i = 0; i < N_RUNS; ++i)
1477  {
1478  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1479 
1480  // Make this generate antithetic values.
1481  e->SetAttribute ("Antithetic", BooleanValue (true));
1482 
1483  double result = ChiSquaredTest (e);
1484  sum += result;
1485  }
1486 
1487  sum /= (double)N_RUNS;
1488 
1489  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1490 
1491  double scale = 5.0;
1492  double shape = 1.0;
1493  double value;
1494 
1495  // Create the RNG with the specified range.
1496  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1497  x->SetAttribute ("Scale", DoubleValue (scale));
1498  x->SetAttribute ("Shape", DoubleValue (shape));
1499 
1500  // Make this generate antithetic values.
1501  x->SetAttribute ("Antithetic", BooleanValue (true));
1502 
1503  // Calculate the mean of these values.
1504  sum = 0.0;
1505  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1506  {
1507  value = x->GetValue ();
1508  sum += value;
1509  }
1510  double valueMean = sum / N_MEASUREMENTS;
1511 
1512  // The expected value for the mean of the values returned by a
1513  // Weibull distributed random variable is
1514  //
1515  // E[value] = scale * Gamma(1 + 1 / shape) ,
1516  //
1517  // where Gamma() is the Gamma function. Note that
1518  //
1519  // Gamma(n) = (n - 1)!
1520  //
1521  // if n is a positive integer.
1522  //
1523  // For this test,
1524  //
1525  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1526  // = Gamma(2)
1527  // = (2 - 1)!
1528  // = 1
1529  //
1530  // which means
1531  //
1532  // E[value] = scale .
1533  //
1534  double expectedMean = scale;
1535 
1536  // Test that values have approximately the right mean value.
1537  double TOLERANCE = expectedMean * 1e-2;
1538  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1539 }
1540 
1541 // ===========================================================================
1542 // Test case for log-normal distribution random variable stream generator
1543 // ===========================================================================
1545 {
1546 public:
1547  static const uint32_t N_RUNS = 5;
1548  static const uint32_t N_BINS = 50;
1549  static const uint32_t N_MEASUREMENTS = 1000000;
1550 
1553 
1555 
1556 private:
1557  virtual void DoRun (void);
1558 };
1559 
1561  : TestCase ("Log-Normal Random Variable Stream Generator")
1562 {}
1563 
1565 {}
1566 
1567 double
1569 {
1570  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1571 
1572  double range[N_BINS + 1];
1573  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1575 
1576  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1577 
1578  double expected[N_BINS];
1579 
1580  // Note that this assumes that n has mu equal to zero and sigma
1581  // equal to one, which are their default values for this
1582  // distribution.
1583  double mu = 0.0;
1584  double sigma = 1.0;
1585 
1586  for (uint32_t i = 0; i < N_BINS; ++i)
1587  {
1588  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1589  expected[i] *= N_MEASUREMENTS;
1590  }
1591 
1592  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1593  {
1594  gsl_histogram_increment (h, n->GetValue ());
1595  }
1596 
1597  double tmp[N_BINS];
1598 
1599  for (uint32_t i = 0; i < N_BINS; ++i)
1600  {
1601  tmp[i] = gsl_histogram_get (h, i);
1602  tmp[i] -= expected[i];
1603  tmp[i] *= tmp[i];
1604  tmp[i] /= expected[i];
1605  }
1606 
1607  gsl_histogram_free (h);
1608 
1609  double chiSquared = 0;
1610 
1611  for (uint32_t i = 0; i < N_BINS; ++i)
1612  {
1613  chiSquared += tmp[i];
1614  }
1615 
1616  return chiSquared;
1617 }
1618 
1619 void
1621 {
1622  SetTestSuiteSeed ();
1623 
1624  double sum = 0.;
1625  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1626 
1627  for (uint32_t i = 0; i < N_RUNS; ++i)
1628  {
1629  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1630  double result = ChiSquaredTest (n);
1631  sum += result;
1632  }
1633 
1634  sum /= (double)N_RUNS;
1635 
1636  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1637 
1638  double mu = 5.0;
1639  double sigma = 2.0;
1640  double value;
1641 
1642  // Create the RNG with the specified range.
1643  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1644  x->SetAttribute ("Mu", DoubleValue (mu));
1645  x->SetAttribute ("Sigma", DoubleValue (sigma));
1646 
1647  // Calculate the mean of these values.
1648  sum = 0.0;
1649  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1650  {
1651  value = x->GetValue ();
1652  sum += value;
1653  }
1654  double valueMean = sum / N_MEASUREMENTS;
1655 
1656  // The expected value for the mean of the values returned by a
1657  // log-normally distributed random variable is equal to
1658  //
1659  // 2
1660  // mu + sigma / 2
1661  // E[value] = e .
1662  //
1663  double expectedMean = std::exp (mu + sigma * sigma / 2.0);
1664 
1665  // Test that values have approximately the right mean value.
1666  //
1671  double TOLERANCE = expectedMean * 3e-2;
1672  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1673 }
1674 
1675 // ===========================================================================
1676 // Test case for antithetic log-normal distribution random variable stream generator
1677 // ===========================================================================
1679 {
1680 public:
1681  static const uint32_t N_RUNS = 5;
1682  static const uint32_t N_BINS = 50;
1683  static const uint32_t N_MEASUREMENTS = 1000000;
1684 
1687 
1689 
1690 private:
1691  virtual void DoRun (void);
1692 };
1693 
1695  : TestCase ("Antithetic Log-Normal Random Variable Stream Generator")
1696 {}
1697 
1699 {}
1700 
1701 double
1703 {
1704  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1705 
1706  double range[N_BINS + 1];
1707  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1709 
1710  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1711 
1712  double expected[N_BINS];
1713 
1714  // Note that this assumes that n has mu equal to zero and sigma
1715  // equal to one, which are their default values for this
1716  // distribution.
1717  double mu = 0.0;
1718  double sigma = 1.0;
1719 
1720  for (uint32_t i = 0; i < N_BINS; ++i)
1721  {
1722  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1723  expected[i] *= N_MEASUREMENTS;
1724  }
1725 
1726  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1727  {
1728  gsl_histogram_increment (h, n->GetValue ());
1729  }
1730 
1731  double tmp[N_BINS];
1732 
1733  for (uint32_t i = 0; i < N_BINS; ++i)
1734  {
1735  tmp[i] = gsl_histogram_get (h, i);
1736  tmp[i] -= expected[i];
1737  tmp[i] *= tmp[i];
1738  tmp[i] /= expected[i];
1739  }
1740 
1741  gsl_histogram_free (h);
1742 
1743  double chiSquared = 0;
1744 
1745  for (uint32_t i = 0; i < N_BINS; ++i)
1746  {
1747  chiSquared += tmp[i];
1748  }
1749 
1750  return chiSquared;
1751 }
1752 
1753 void
1755 {
1756  SetTestSuiteSeed ();
1757 
1758  double sum = 0.;
1759  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1760 
1761  for (uint32_t i = 0; i < N_RUNS; ++i)
1762  {
1763  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1764 
1765  // Make this generate antithetic values.
1766  n->SetAttribute ("Antithetic", BooleanValue (true));
1767 
1768  double result = ChiSquaredTest (n);
1769  sum += result;
1770  }
1771 
1772  sum /= (double)N_RUNS;
1773 
1774  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1775 
1776  double mu = 5.0;
1777  double sigma = 2.0;
1778  double value;
1779 
1780  // Create the RNG with the specified range.
1781  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1782  x->SetAttribute ("Mu", DoubleValue (mu));
1783  x->SetAttribute ("Sigma", DoubleValue (sigma));
1784 
1785  // Make this generate antithetic values.
1786  x->SetAttribute ("Antithetic", BooleanValue (true));
1787 
1788  // Calculate the mean of these values.
1789  sum = 0.0;
1790  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1791  {
1792  value = x->GetValue ();
1793  sum += value;
1794  }
1795  double valueMean = sum / N_MEASUREMENTS;
1796 
1797  // The expected value for the mean of the values returned by a
1798  // log-normally distributed random variable is equal to
1799  //
1800  // 2
1801  // mu + sigma / 2
1802  // E[value] = e .
1803  //
1804  double expectedMean = std::exp (mu + sigma * sigma / 2.0);
1805 
1806  // Test that values have approximately the right mean value.
1807  //
1812  double TOLERANCE = expectedMean * 3e-2;
1813  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1814 }
1815 
1816 // ===========================================================================
1817 // Test case for gamma distribution random variable stream generator
1818 // ===========================================================================
1820 {
1821 public:
1822  static const uint32_t N_RUNS = 5;
1823  static const uint32_t N_BINS = 50;
1824  static const uint32_t N_MEASUREMENTS = 1000000;
1825 
1828 
1830 
1831 private:
1832  virtual void DoRun (void);
1833 };
1834 
1836  : TestCase ("Gamma Random Variable Stream Generator")
1837 {}
1838 
1840 {}
1841 
1842 double
1844 {
1845  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1846 
1847  double range[N_BINS + 1];
1848  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1850 
1851  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1852 
1853  double expected[N_BINS];
1854 
1855  // Note that this assumes that n has alpha equal to one and beta
1856  // equal to one, which are their default values for this
1857  // distribution.
1858  double alpha = 1.0;
1859  double beta = 1.0;
1860 
1861  for (uint32_t i = 0; i < N_BINS; ++i)
1862  {
1863  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
1864  expected[i] *= N_MEASUREMENTS;
1865  }
1866 
1867  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1868  {
1869  gsl_histogram_increment (h, n->GetValue ());
1870  }
1871 
1872  double tmp[N_BINS];
1873 
1874  for (uint32_t i = 0; i < N_BINS; ++i)
1875  {
1876  tmp[i] = gsl_histogram_get (h, i);
1877  tmp[i] -= expected[i];
1878  tmp[i] *= tmp[i];
1879  tmp[i] /= expected[i];
1880  }
1881 
1882  gsl_histogram_free (h);
1883 
1884  double chiSquared = 0;
1885 
1886  for (uint32_t i = 0; i < N_BINS; ++i)
1887  {
1888  chiSquared += tmp[i];
1889  }
1890 
1891  return chiSquared;
1892 }
1893 
1894 void
1896 {
1897  SetTestSuiteSeed ();
1898 
1899  double sum = 0.;
1900  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1901 
1902  for (uint32_t i = 0; i < N_RUNS; ++i)
1903  {
1904  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
1905  double result = ChiSquaredTest (n);
1906  sum += result;
1907  }
1908 
1909  sum /= (double)N_RUNS;
1910 
1911  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1912 
1913  double alpha = 5.0;
1914  double beta = 2.0;
1915  double value;
1916 
1917  // Create the RNG with the specified range.
1918  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
1919  x->SetAttribute ("Alpha", DoubleValue (alpha));
1920  x->SetAttribute ("Beta", DoubleValue (beta));
1921 
1922  // Calculate the mean of these values.
1923  sum = 0.0;
1924  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1925  {
1926  value = x->GetValue ();
1927  sum += value;
1928  }
1929  double valueMean = sum / N_MEASUREMENTS;
1930 
1931  // The expected value for the mean of the values returned by a
1932  // gammaly distributed random variable is equal to
1933  //
1934  // E[value] = alpha * beta .
1935  //
1936  double expectedMean = alpha * beta;
1937 
1938  // Test that values have approximately the right mean value.
1939  double TOLERANCE = expectedMean * 1e-2;
1940  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1941 }
1942 
1943 // ===========================================================================
1944 // Test case for antithetic gamma distribution random variable stream generator
1945 // ===========================================================================
1947 {
1948 public:
1949  static const uint32_t N_RUNS = 5;
1950  static const uint32_t N_BINS = 50;
1951  static const uint32_t N_MEASUREMENTS = 1000000;
1952 
1955 
1957 
1958 private:
1959  virtual void DoRun (void);
1960 };
1961 
1963  : TestCase ("Antithetic Gamma Random Variable Stream Generator")
1964 {}
1965 
1967 {}
1968 
1969 double
1971 {
1972  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1973 
1974  double range[N_BINS + 1];
1975  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1977 
1978  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1979 
1980  double expected[N_BINS];
1981 
1982  // Note that this assumes that n has alpha equal to one and beta
1983  // equal to one, which are their default values for this
1984  // distribution.
1985  double alpha = 1.0;
1986  double beta = 1.0;
1987 
1988  for (uint32_t i = 0; i < N_BINS; ++i)
1989  {
1990  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
1991  expected[i] *= N_MEASUREMENTS;
1992  }
1993 
1994  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1995  {
1996  gsl_histogram_increment (h, n->GetValue ());
1997  }
1998 
1999  double tmp[N_BINS];
2000 
2001  for (uint32_t i = 0; i < N_BINS; ++i)
2002  {
2003  tmp[i] = gsl_histogram_get (h, i);
2004  tmp[i] -= expected[i];
2005  tmp[i] *= tmp[i];
2006  tmp[i] /= expected[i];
2007  }
2008 
2009  gsl_histogram_free (h);
2010 
2011  double chiSquared = 0;
2012 
2013  for (uint32_t i = 0; i < N_BINS; ++i)
2014  {
2015  chiSquared += tmp[i];
2016  }
2017 
2018  return chiSquared;
2019 }
2020 
2021 void
2023 {
2024  SetTestSuiteSeed ();
2025 
2026  double sum = 0.;
2027  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2028 
2029  for (uint32_t i = 0; i < N_RUNS; ++i)
2030  {
2031  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
2032 
2033  // Make this generate antithetic values.
2034  n->SetAttribute ("Antithetic", BooleanValue (true));
2035 
2036  double result = ChiSquaredTest (n);
2037  sum += result;
2038  }
2039 
2040  sum /= (double)N_RUNS;
2041 
2042  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2043 
2044  double alpha = 5.0;
2045  double beta = 2.0;
2046  double value;
2047 
2048  // Create the RNG with the specified range.
2049  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
2050 
2051  // Make this generate antithetic values.
2052  x->SetAttribute ("Antithetic", BooleanValue (true));
2053 
2054  x->SetAttribute ("Alpha", DoubleValue (alpha));
2055  x->SetAttribute ("Beta", DoubleValue (beta));
2056 
2057  // Calculate the mean of these values.
2058  sum = 0.0;
2059  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2060  {
2061  value = x->GetValue ();
2062  sum += value;
2063  }
2064  double valueMean = sum / N_MEASUREMENTS;
2065 
2066  // The expected value for the mean of the values returned by a
2067  // gammaly distributed random variable is equal to
2068  //
2069  // E[value] = alpha * beta .
2070  //
2071  double expectedMean = alpha * beta;
2072 
2073  // Test that values have approximately the right mean value.
2074  double TOLERANCE = expectedMean * 1e-2;
2075  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2076 }
2077 
2078 // ===========================================================================
2079 // Test case for Erlang distribution random variable stream generator
2080 // ===========================================================================
2082 {
2083 public:
2084  static const uint32_t N_RUNS = 5;
2085  static const uint32_t N_BINS = 50;
2086  static const uint32_t N_MEASUREMENTS = 1000000;
2087 
2090 
2092 
2093 private:
2094  virtual void DoRun (void);
2095 };
2096 
2098  : TestCase ("Erlang Random Variable Stream Generator")
2099 {}
2100 
2102 {}
2103 
2104 double
2106 {
2107  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2108 
2109  double range[N_BINS + 1];
2110  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2112 
2113  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2114 
2115  double expected[N_BINS];
2116 
2117  // Note that this assumes that n has k equal to one and lambda
2118  // equal to one, which are their default values for this
2119  // distribution.
2120  uint32_t k = 1;
2121  double lambda = 1.0;
2122 
2123  // Note that Erlang distribution is equal to the gamma distribution
2124  // when k is an iteger, which is why the gamma distribution's cdf
2125  // function can be used here.
2126  for (uint32_t i = 0; i < N_BINS; ++i)
2127  {
2128  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2129  expected[i] *= N_MEASUREMENTS;
2130  }
2131 
2132  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2133  {
2134  gsl_histogram_increment (h, n->GetValue ());
2135  }
2136 
2137  double tmp[N_BINS];
2138 
2139  for (uint32_t i = 0; i < N_BINS; ++i)
2140  {
2141  tmp[i] = gsl_histogram_get (h, i);
2142  tmp[i] -= expected[i];
2143  tmp[i] *= tmp[i];
2144  tmp[i] /= expected[i];
2145  }
2146 
2147  gsl_histogram_free (h);
2148 
2149  double chiSquared = 0;
2150 
2151  for (uint32_t i = 0; i < N_BINS; ++i)
2152  {
2153  chiSquared += tmp[i];
2154  }
2155 
2156  return chiSquared;
2157 }
2158 
2159 void
2161 {
2162  SetTestSuiteSeed ();
2163 
2164  double sum = 0.;
2165  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2166 
2167  for (uint32_t i = 0; i < N_RUNS; ++i)
2168  {
2169  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2170  double result = ChiSquaredTest (n);
2171  sum += result;
2172  }
2173 
2174  sum /= (double)N_RUNS;
2175 
2176  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2177 
2178  uint32_t k = 5;
2179  double lambda = 2.0;
2180  double value;
2181 
2182  // Create the RNG with the specified range.
2183  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2184  x->SetAttribute ("K", IntegerValue (k));
2185  x->SetAttribute ("Lambda", DoubleValue (lambda));
2186 
2187  // Calculate the mean of these values.
2188  sum = 0.0;
2189  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2190  {
2191  value = x->GetValue ();
2192  sum += value;
2193  }
2194  double valueMean = sum / N_MEASUREMENTS;
2195 
2196  // The expected value for the mean of the values returned by a
2197  // Erlangly distributed random variable is equal to
2198  //
2199  // E[value] = k * lambda .
2200  //
2201  double expectedMean = k * lambda;
2202 
2203  // Test that values have approximately the right mean value.
2204  double TOLERANCE = expectedMean * 1e-2;
2205  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2206 }
2207 
2208 // ===========================================================================
2209 // Test case for antithetic Erlang distribution random variable stream generator
2210 // ===========================================================================
2212 {
2213 public:
2214  static const uint32_t N_RUNS = 5;
2215  static const uint32_t N_BINS = 50;
2216  static const uint32_t N_MEASUREMENTS = 1000000;
2217 
2220 
2222 
2223 private:
2224  virtual void DoRun (void);
2225 };
2226 
2228  : TestCase ("Antithetic Erlang Random Variable Stream Generator")
2229 {}
2230 
2232 {}
2233 
2234 double
2236 {
2237  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2238 
2239  double range[N_BINS + 1];
2240  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2242 
2243  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2244 
2245  double expected[N_BINS];
2246 
2247  // Note that this assumes that n has k equal to one and lambda
2248  // equal to one, which are their default values for this
2249  // distribution.
2250  uint32_t k = 1;
2251  double lambda = 1.0;
2252 
2253  // Note that Erlang distribution is equal to the gamma distribution
2254  // when k is an iteger, which is why the gamma distribution's cdf
2255  // function can be used here.
2256  for (uint32_t i = 0; i < N_BINS; ++i)
2257  {
2258  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2259  expected[i] *= N_MEASUREMENTS;
2260  }
2261 
2262  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2263  {
2264  gsl_histogram_increment (h, n->GetValue ());
2265  }
2266 
2267  double tmp[N_BINS];
2268 
2269  for (uint32_t i = 0; i < N_BINS; ++i)
2270  {
2271  tmp[i] = gsl_histogram_get (h, i);
2272  tmp[i] -= expected[i];
2273  tmp[i] *= tmp[i];
2274  tmp[i] /= expected[i];
2275  }
2276 
2277  gsl_histogram_free (h);
2278 
2279  double chiSquared = 0;
2280 
2281  for (uint32_t i = 0; i < N_BINS; ++i)
2282  {
2283  chiSquared += tmp[i];
2284  }
2285 
2286  return chiSquared;
2287 }
2288 
2289 void
2291 {
2292  SetTestSuiteSeed ();
2293 
2294  double sum = 0.;
2295  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2296 
2297  for (uint32_t i = 0; i < N_RUNS; ++i)
2298  {
2299  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2300 
2301  // Make this generate antithetic values.
2302  n->SetAttribute ("Antithetic", BooleanValue (true));
2303 
2304  double result = ChiSquaredTest (n);
2305  sum += result;
2306  }
2307 
2308  sum /= (double)N_RUNS;
2309 
2310  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2311 
2312  uint32_t k = 5;
2313  double lambda = 2.0;
2314  double value;
2315 
2316  // Create the RNG with the specified range.
2317  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2318 
2319  // Make this generate antithetic values.
2320  x->SetAttribute ("Antithetic", BooleanValue (true));
2321 
2322  x->SetAttribute ("K", IntegerValue (k));
2323  x->SetAttribute ("Lambda", DoubleValue (lambda));
2324 
2325  // Calculate the mean of these values.
2326  sum = 0.0;
2327  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2328  {
2329  value = x->GetValue ();
2330  sum += value;
2331  }
2332  double valueMean = sum / N_MEASUREMENTS;
2333 
2334  // The expected value for the mean of the values returned by a
2335  // Erlangly distributed random variable is equal to
2336  //
2337  // E[value] = k * lambda .
2338  //
2339  double expectedMean = k * lambda;
2340 
2341  // Test that values have approximately the right mean value.
2342  double TOLERANCE = expectedMean * 1e-2;
2343  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2344 }
2345 
2346 // ===========================================================================
2347 // Test case for Zipf distribution random variable stream generator
2348 // ===========================================================================
2350 {
2351 public:
2352  static const uint32_t N_MEASUREMENTS = 1000000;
2353 
2356 
2357 private:
2358  virtual void DoRun (void);
2359 };
2360 
2362  : TestCase ("Zipf Random Variable Stream Generator")
2363 {}
2364 
2366 {}
2367 
2368 void
2370 {
2371  SetTestSuiteSeed ();
2372 
2373  uint32_t n = 1;
2374  double alpha = 2.0;
2375  double value;
2376 
2377  // Create the RNG with the specified range.
2378  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2379  x->SetAttribute ("N", IntegerValue (n));
2380  x->SetAttribute ("Alpha", DoubleValue (alpha));
2381 
2382  // Calculate the mean of these values.
2383  double sum = 0.0;
2384  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2385  {
2386  value = x->GetValue ();
2387  sum += value;
2388  }
2389  double valueMean = sum / N_MEASUREMENTS;
2390 
2391  // The expected value for the mean of the values returned by a
2392  // Zipfly distributed random variable is equal to
2393  //
2394  // H
2395  // N, alpha - 1
2396  // E[value] = ---------------
2397  // H
2398  // N, alpha
2399  //
2400  // where
2401  //
2402  // N
2403  // ---
2404  // \ -alpha
2405  // H = / m .
2406  // N, alpha ---
2407  // m=1
2408  //
2409  // For this test,
2410  //
2411  // -(alpha - 1)
2412  // 1
2413  // E[value] = ---------------
2414  // -alpha
2415  // 1
2416  //
2417  // = 1 .
2418  //
2419  double expectedMean = 1.0;
2420 
2421  // Test that values have approximately the right mean value.
2422  double TOLERANCE = expectedMean * 1e-2;
2423  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2424 }
2425 
2426 // ===========================================================================
2427 // Test case for antithetic Zipf distribution random variable stream generator
2428 // ===========================================================================
2430 {
2431 public:
2432  static const uint32_t N_MEASUREMENTS = 1000000;
2433 
2436 
2437 private:
2438  virtual void DoRun (void);
2439 };
2440 
2442  : TestCase ("Antithetic Zipf Random Variable Stream Generator")
2443 {}
2444 
2446 {}
2447 
2448 void
2450 {
2451  SetTestSuiteSeed ();
2452 
2453  uint32_t n = 1;
2454  double alpha = 2.0;
2455  double value;
2456 
2457  // Create the RNG with the specified range.
2458  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2459  x->SetAttribute ("N", IntegerValue (n));
2460  x->SetAttribute ("Alpha", DoubleValue (alpha));
2461 
2462  // Make this generate antithetic values.
2463  x->SetAttribute ("Antithetic", BooleanValue (true));
2464 
2465  // Calculate the mean of these values.
2466  double sum = 0.0;
2467  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2468  {
2469  value = x->GetValue ();
2470  sum += value;
2471  }
2472  double valueMean = sum / N_MEASUREMENTS;
2473 
2474  // The expected value for the mean of the values returned by a
2475  // Zipfly distributed random variable is equal to
2476  //
2477  // H
2478  // N, alpha - 1
2479  // E[value] = ---------------
2480  // H
2481  // N, alpha
2482  //
2483  // where
2484  //
2485  // N
2486  // ---
2487  // \ -alpha
2488  // H = / m .
2489  // N, alpha ---
2490  // m=1
2491  //
2492  // For this test,
2493  //
2494  // -(alpha - 1)
2495  // 1
2496  // E[value] = ---------------
2497  // -alpha
2498  // 1
2499  //
2500  // = 1 .
2501  //
2502  double expectedMean = 1.0;
2503 
2504  // Test that values have approximately the right mean value.
2505  double TOLERANCE = expectedMean * 1e-2;
2506  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2507 }
2508 
2509 // ===========================================================================
2510 // Test case for Zeta distribution random variable stream generator
2511 // ===========================================================================
2513 {
2514 public:
2515  static const uint32_t N_MEASUREMENTS = 1000000;
2516 
2519 
2520 private:
2521  virtual void DoRun (void);
2522 };
2523 
2525  : TestCase ("Zeta Random Variable Stream Generator")
2526 {}
2527 
2529 {}
2530 
2531 void
2533 {
2534  SetTestSuiteSeed ();
2535 
2536  double alpha = 5.0;
2537  double value;
2538 
2539  // Create the RNG with the specified range.
2540  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2541  x->SetAttribute ("Alpha", DoubleValue (alpha));
2542 
2543  // Calculate the mean of these values.
2544  double sum = 0.0;
2545  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2546  {
2547  value = x->GetValue ();
2548  sum += value;
2549  }
2550  double valueMean = sum / N_MEASUREMENTS;
2551 
2552  // The expected value for the mean of the values returned by a
2553  // zetaly distributed random variable is equal to
2554  //
2555  // zeta(alpha - 1)
2556  // E[value] = --------------- for alpha > 2 ,
2557  // zeta(alpha)
2558  //
2559  // where zeta(alpha) is the Riemann zeta function.
2560  //
2561  // There are no simple analytic forms for the Riemann zeta function,
2562  // which is why the gsl library is used in this test to calculate
2563  // the known mean of the values.
2564  double expectedMean =
2565  gsl_sf_zeta_int (static_cast<int> (alpha - 1)) /
2566  gsl_sf_zeta_int (static_cast<int> (alpha) );
2567 
2568  // Test that values have approximately the right mean value.
2569  double TOLERANCE = expectedMean * 1e-2;
2570  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2571 }
2572 
2573 // ===========================================================================
2574 // Test case for antithetic Zeta distribution random variable stream generator
2575 // ===========================================================================
2577 {
2578 public:
2579  static const uint32_t N_MEASUREMENTS = 1000000;
2580 
2583 
2584 private:
2585  virtual void DoRun (void);
2586 };
2587 
2589  : TestCase ("Antithetic Zeta Random Variable Stream Generator")
2590 {}
2591 
2593 {}
2594 
2595 void
2597 {
2598  SetTestSuiteSeed ();
2599 
2600  double alpha = 5.0;
2601  double value;
2602 
2603  // Create the RNG with the specified range.
2604  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2605  x->SetAttribute ("Alpha", DoubleValue (alpha));
2606 
2607  // Make this generate antithetic values.
2608  x->SetAttribute ("Antithetic", BooleanValue (true));
2609 
2610  // Calculate the mean of these values.
2611  double sum = 0.0;
2612  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2613  {
2614  value = x->GetValue ();
2615  sum += value;
2616  }
2617  double valueMean = sum / N_MEASUREMENTS;
2618 
2619  // The expected value for the mean of the values returned by a
2620  // zetaly distributed random variable is equal to
2621  //
2622  // zeta(alpha - 1)
2623  // E[value] = --------------- for alpha > 2 ,
2624  // zeta(alpha)
2625  //
2626  // where zeta(alpha) is the Riemann zeta function.
2627  //
2628  // There are no simple analytic forms for the Riemann zeta function,
2629  // which is why the gsl library is used in this test to calculate
2630  // the known mean of the values.
2631  double expectedMean =
2632  gsl_sf_zeta_int (static_cast<int> (alpha) - 1) /
2633  gsl_sf_zeta_int (static_cast<int> (alpha) );
2634 
2635  // Test that values have approximately the right mean value.
2636  double TOLERANCE = expectedMean * 1e-2;
2637  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2638 }
2639 
2640 // ===========================================================================
2641 // Test case for deterministic random variable stream generator
2642 // ===========================================================================
2644 {
2645 public:
2646  static const double TOLERANCE;
2647 
2650 
2651 private:
2652  virtual void DoRun (void);
2653 };
2654 
2656 
2658  : TestCase ("Deterministic Random Variable Stream Generator")
2659 {}
2660 
2662 {}
2663 
2664 void
2666 {
2667  SetTestSuiteSeed ();
2668 
2669  Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
2670 
2671  // The following array should give the sequence
2672  //
2673  // 4, 4, 7, 7, 10, 10 .
2674  //
2675  double array1 [] = { 4, 4, 7, 7, 10, 10};
2676  std::size_t count1 = 6;
2677  s->SetValueArray (array1, count1);
2678 
2679  double value;
2680 
2681  // Test that the first sequence is correct.
2682  value = s->GetValue ();
2683  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2684  value = s->GetValue ();
2685  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2686  value = s->GetValue ();
2687  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2688  value = s->GetValue ();
2689  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2690  value = s->GetValue ();
2691  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2692  value = s->GetValue ();
2693  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2694 
2695  // The following array should give the sequence
2696  //
2697  // 1000, 2000, 7, 7 .
2698  //
2699  double array2 [] = { 1000, 2000, 3000, 4000};
2700  std::size_t count2 = 4;
2701  s->SetValueArray (array2, count2);
2702 
2703  // Test that the second sequence is correct.
2704  value = s->GetValue ();
2705  NS_TEST_ASSERT_MSG_EQ_TOL (value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2706  value = s->GetValue ();
2707  NS_TEST_ASSERT_MSG_EQ_TOL (value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2708  value = s->GetValue ();
2709  NS_TEST_ASSERT_MSG_EQ_TOL (value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2710  value = s->GetValue ();
2711  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2712  value = s->GetValue ();
2713 }
2714 
2715 // ===========================================================================
2716 // Test case for empirical distribution random variable stream generator
2717 // ===========================================================================
2719 {
2720 public:
2721  static const uint32_t N_MEASUREMENTS = 1000000;
2722 
2725 
2726 private:
2727  virtual void DoRun (void);
2728 };
2729 
2731  : TestCase ("Empirical Random Variable Stream Generator")
2732 {}
2733 
2735 {}
2736 
2737 void
2739 {
2740  SetTestSuiteSeed ();
2741 
2742  // Create the RNG with a uniform distribution between 0 and 10.
2743  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2744  x->SetInterpolate (false);
2745  x->CDF ( 0.0, 0.0);
2746  x->CDF ( 5.0, 0.25);
2747  x->CDF (10.0, 1.0);
2748 
2749  // Check that only the correct values are returned
2750  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2751  {
2752  double value = x->GetValue ();
2753  NS_TEST_EXPECT_MSG_EQ ( (value == 5) || (value == 10), true,
2754  "Incorrect value returned, expected only 5 or 10.");
2755  }
2756 
2757  // Calculate the mean of the interpolated values.
2758  double sum = 0.0;
2759  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2760  {
2761  double value = x->Interpolate ();
2762  sum += value;
2763  }
2764  double valueMean = sum / N_MEASUREMENTS;
2765 
2766  // The expected distribution (with interpolation) is
2767  // Domain Probability
2768  // [0, 5) 25%
2769  // [5, 10) 75%
2770  //
2771  // The expected value for the mean of the values returned by this
2772  // empirical distribution is
2773  //
2774  // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2775  //
2776  double expectedMean = 6.25;
2777 
2778  // Test that values have approximately the right mean value.
2779  double TOLERANCE = expectedMean * 1e-2;
2780  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2781 
2782  // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2783  Ptr<EmpiricalRandomVariable> y = CreateObject<EmpiricalRandomVariable> ();
2784  y->SetInterpolate (false);
2785  y->CDF (-1.0, 0.0);
2786  y->CDF (0.0, 0.5);
2787  y->CDF (1.0, 1.0);
2788  NS_TEST_ASSERT_MSG_LT (y->GetValue (), 2, "Empirical variable with negative domain");
2789 }
2790 
2791 // ===========================================================================
2792 // Test case for antithetic empirical distribution random variable stream generator
2793 // ===========================================================================
2795 {
2796 public:
2797  static const uint32_t N_MEASUREMENTS = 1000000;
2798 
2801 
2802 private:
2803  virtual void DoRun (void);
2804 };
2805 
2807  : TestCase ("EmpiricalAntithetic Random Variable Stream Generator")
2808 {}
2809 
2811 {}
2812 
2813 void
2815 {
2816  SetTestSuiteSeed ();
2817 
2818  // Create the RNG with a uniform distribution between 0 and 10.
2819  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2820  x->SetInterpolate (false);
2821  x->CDF ( 0.0, 0.0);
2822  x->CDF ( 5.0, 0.25);
2823  x->CDF (10.0, 1.0);
2824 
2825  // Make this generate antithetic values.
2826  x->SetAttribute ("Antithetic", BooleanValue (true));
2827 
2828  // Check that only the correct values are returned
2829  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2830  {
2831  double value = x->GetValue ();
2832  NS_TEST_EXPECT_MSG_EQ ( (value == 5) || (value == 10), true,
2833  "Incorrect value returned, expected only 5 or 10.");
2834  }
2835 
2836  // Calculate the mean of these values.
2837  double sum = 0.0;
2838  double value;
2839  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2840  {
2841  value = x->Interpolate ();
2842  sum += value;
2843  }
2844  double valueMean = sum / N_MEASUREMENTS;
2845 
2846  // The expected value for the mean of the values returned by this
2847  // empirical distribution is
2848  //
2849  // E[value] = 2.5 * 25% + 7.5 * 75% = 6.25
2850  //
2851  double expectedMean = 6.25;
2852 
2853  // Test that values have approximately the right mean value.
2854  double TOLERANCE = expectedMean * 1e-2;
2855  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2856 }
2857 
2859 {
2860 public:
2862 };
2863 
2865  : TestSuite ("random-variable-stream-generators", UNIT)
2866 {
2883  /*
2884  AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase);
2885  */
2890  /*
2891  AddTestCase (new RandomVariableStreamGammaAntitheticTestCase);
2892  */
2902 }
2903 
virtual double GetValue(void)
Returns the next value in the empirical distribution.
double GetValue(double constant)
Get the next random value, as a double equal to the argument.
double ChiSquaredTest(Ptr< LogNormalRandomVariable > n)
void FillHistoRangeUniformly(double *array, uint32_t n, double start, double end)
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Hold variables of type string.
Definition: string.h:41
#define min(a, b)
Definition: 80211b.c:42
static RandomVariableStreamTestSuite randomVariableStreamTestSuite
#define TOLERANCE
A suite of tests to run.
Definition: test.h:1343
def start()
Definition: core.py:1855
Hold a signed integer type.
Definition: integer.h:44
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:283
double ChiSquaredTest(Ptr< NormalRandomVariable > n)
encapsulates test code
Definition: test.h:1153
double ChiSquaredTest(Ptr< ExponentialRandomVariable > e)
double ChiSquaredTest(Ptr< WeibullRandomVariable > p)
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static uint64_t GetRun(void)
Get the current run number.
void SetValueArray(double *values, std::size_t length)
Sets the array of values that holds the predetermined sequence.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual double GetValue(void)
Get the next random value as a double drawn from the distribution.
#define max(a, b)
Definition: 80211b.c:43
virtual double GetValue(void)
Returns the next value in the sequence.
double ChiSquaredTest(Ptr< ErlangRandomVariable > n)
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:166
void CDF(double v, double c)
Specifies a point in the empirical distribution.
virtual void DoRun(void)
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< GammaRandomVariable > n)
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:378
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
bool SetInterpolate(bool interpolate)
Switch the mode between sampling the CDF and interpolating.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static uint32_t GetSeed(void)
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static void SetSeed(uint32_t seed)
Set the seed.
double ChiSquaredTest(Ptr< UniformRandomVariable > u)
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:622
double ChiSquaredTest(Ptr< ParetoRandomVariable > p)
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
double GetValue(double mean, double bound)
Get the next random value, as a double from the exponential distribution with the specified mean and ...
virtual void DoRun(void)
Implementation to actually run this TestCase.
double GetValue(double scale, double shape, double bound)
Returns a random double from a Pareto distribution with the specified scale, shape, and upper bound.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:995
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:809
double GetValue(double scale, double shape, double bound)
Returns a random double from a Weibull distribution with the specified scale, shape, and upper bound.