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