A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
166 }
167 
168 // ===========================================================================
169 // Test case for antithetic uniform distribution random variable stream generator
170 // ===========================================================================
172 {
173 public:
174  static const uint32_t N_RUNS = 5;
175  static const uint32_t N_BINS = 50;
176  static const uint32_t N_MEASUREMENTS = 1000000;
177 
180 
182 
183 private:
184  virtual void DoRun (void);
185 };
186 
188  : TestCase ("Antithetic Uniform Random Variable Stream Generator")
189 {
190 }
191 
193 {
194 }
195 
196 double
198 {
199  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
200 
201  // Note that this assumes that the range for u is [0,1], which is
202  // the default range for this distribution.
203  gsl_histogram_set_ranges_uniform (h, 0., 1.);
204 
205  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
206  {
207  gsl_histogram_increment (h, u->GetValue ());
208  }
209 
210  double tmp[N_BINS];
211 
212  double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
213 
214  for (uint32_t i = 0; i < N_BINS; ++i)
215  {
216  tmp[i] = gsl_histogram_get (h, i);
217  tmp[i] -= expected;
218  tmp[i] *= tmp[i];
219  tmp[i] /= expected;
220  }
221 
222  gsl_histogram_free (h);
223 
224  double chiSquared = 0;
225 
226  for (uint32_t i = 0; i < N_BINS; ++i)
227  {
228  chiSquared += tmp[i];
229  }
230 
231  return chiSquared;
232 }
233 
234 void
236 {
237  SeedManager::SetSeed (time (0));
238 
239  double sum = 0.;
240  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
241 
242  for (uint32_t i = 0; i < N_RUNS; ++i)
243  {
244  Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
245 
246  // Make this generate antithetic values.
247  u->SetAttribute ("Antithetic", BooleanValue (true));
248 
249  double result = ChiSquaredTest (u);
250  sum += result;
251  }
252 
253  sum /= (double)N_RUNS;
254 
255  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
256 
257  double min = 0.0;
258  double max = 10.0;
259  double value;
260 
261  // Create the RNG with the specified range.
262  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
263 
264  // Make this generate antithetic values.
265  x->SetAttribute ("Antithetic", BooleanValue (true));
266 
267  x->SetAttribute ("Min", DoubleValue (min));
268  x->SetAttribute ("Max", DoubleValue (max));
269 
270  // Test that values are always within the range:
271  //
272  // [min, max)
273  //
274  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
275  {
276  value = x->GetValue ();
277  NS_TEST_ASSERT_MSG_EQ ((value >= min), true, "Value less than minimum.");
278  NS_TEST_ASSERT_MSG_LT (value, max, "Value greater than or equal to maximum.");
279  }
280 
281 
282 }
283 
284 // ===========================================================================
285 // Test case for constant random variable stream generator
286 // ===========================================================================
288 {
289 public:
290  static const uint32_t N_MEASUREMENTS = 1000000;
291  static const double TOLERANCE = 1e-8;
292 
295 
296 private:
297  virtual void DoRun (void);
298 };
299 
301  : TestCase ("Constant Random Variable Stream Generator")
302 {
303 }
304 
306 {
307 }
308 
309 void
311 {
312  SeedManager::SetSeed (time (0));
313 
314  Ptr<ConstantRandomVariable> c = CreateObject<ConstantRandomVariable> ();
315 
316  double constant;
317 
318  // Test that the constant value can be changed using its attribute.
319  constant = 10.0;
320  c->SetAttribute ("Constant", DoubleValue (constant));
321  NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed");
322  c->SetAttribute ("Constant", DoubleValue (20.0));
323  NS_TEST_ASSERT_MSG_NE (c->GetValue (), constant, "Constant value not changed");
324 
325  // Test that the constant value does not change.
326  constant = c->GetValue ();
327  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
328  {
329  NS_TEST_ASSERT_MSG_EQ_TOL (c->GetValue (), constant, TOLERANCE, "Constant value changed in loop");
330  }
331 }
332 
333 // ===========================================================================
334 // Test case for sequential random variable stream generator
335 // ===========================================================================
337 {
338 public:
339  static const double TOLERANCE = 1e-8;
340 
343 
344 private:
345  virtual void DoRun (void);
346 };
347 
349  : TestCase ("Sequential Random Variable Stream Generator")
350 {
351 }
352 
354 {
355 }
356 
357 void
359 {
360  SeedManager::SetSeed (time (0));
361 
362  Ptr<SequentialRandomVariable> s = CreateObject<SequentialRandomVariable> ();
363 
364  // The following four attributes should give the sequence
365  //
366  // 4, 4, 7, 7, 10, 10
367  //
368  s->SetAttribute ("Min", DoubleValue (4));
369  s->SetAttribute ("Max", DoubleValue (11));
370  s->SetAttribute ("Increment", StringValue("ns3::UniformRandomVariable[Min=3.0|Max=3.0]"));
371  s->SetAttribute ("Consecutive", IntegerValue (2));
372 
373  double value;
374 
375  // Test that the sequencet is correct.
376  value = s->GetValue ();
377  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 1 wrong.");
378  value = s->GetValue ();
379  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence value 2 wrong.");
380  value = s->GetValue ();
381  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 3 wrong.");
382  value = s->GetValue ();
383  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence value 4 wrong.");
384  value = s->GetValue ();
385  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 5 wrong.");
386  value = s->GetValue ();
387  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence value 6 wrong.");
388 
389 }
390 
391 // ===========================================================================
392 // Test case for normal distribution random variable stream generator
393 // ===========================================================================
395 {
396 public:
397  static const uint32_t N_RUNS = 5;
398  static const uint32_t N_BINS = 50;
399  static const uint32_t N_MEASUREMENTS = 1000000;
400 
403 
405 
406 private:
407  virtual void DoRun (void);
408 };
409 
411  : TestCase ("Normal Random Variable Stream Generator")
412 {
413 }
414 
416 {
417 }
418 
419 double
421 {
422  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
423 
424  double range[N_BINS + 1];
425  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
426  range[0] = -std::numeric_limits<double>::max ();
427  range[N_BINS] = std::numeric_limits<double>::max ();
428 
429  gsl_histogram_set_ranges (h, range, N_BINS + 1);
430 
431  double expected[N_BINS];
432 
433  // Note that this assumes that n has mean equal to zero and standard
434  // deviation equal to one, which are their default values for this
435  // distribution.
436  double sigma = 1.;
437 
438  for (uint32_t i = 0; i < N_BINS; ++i)
439  {
440  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
441  expected[i] *= N_MEASUREMENTS;
442  }
443 
444  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
445  {
446  gsl_histogram_increment (h, n->GetValue ());
447  }
448 
449  double tmp[N_BINS];
450 
451  for (uint32_t i = 0; i < N_BINS; ++i)
452  {
453  tmp[i] = gsl_histogram_get (h, i);
454  tmp[i] -= expected[i];
455  tmp[i] *= tmp[i];
456  tmp[i] /= expected[i];
457  }
458 
459  gsl_histogram_free (h);
460 
461  double chiSquared = 0;
462 
463  for (uint32_t i = 0; i < N_BINS; ++i)
464  {
465  chiSquared += tmp[i];
466  }
467 
468  return chiSquared;
469 }
470 
471 void
473 {
474  SeedManager::SetSeed (time (0));
475 
476  double sum = 0.;
477  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
478 
479  for (uint32_t i = 0; i < N_RUNS; ++i)
480  {
481  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
482  double result = ChiSquaredTest (n);
483  sum += result;
484  }
485 
486  sum /= (double)N_RUNS;
487 
488  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
489 
490  double mean = 5.0;
491  double variance = 2.0;
492  double value;
493 
494  // Create the RNG with the specified range.
495  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
496  x->SetAttribute ("Mean", DoubleValue (mean));
497  x->SetAttribute ("Variance", DoubleValue (variance));
498 
499  // Calculate the mean of these values.
500  sum = 0.0;
501  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
502  {
503  value = x->GetValue ();
504  sum += value;
505  }
506  double valueMean = sum / N_MEASUREMENTS;
507 
508  // The expected value for the mean of the values returned by a
509  // normally distributed random variable is equal to mean.
510  double expectedMean = mean;
511 
512  // Test that values have approximately the right mean value.
513  double TOLERANCE = expectedMean * 1e-2;
514  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
515 }
516 
517 // ===========================================================================
518 // Test case for antithetic normal distribution random variable stream generator
519 // ===========================================================================
521 {
522 public:
523  static const uint32_t N_RUNS = 5;
524  static const uint32_t N_BINS = 50;
525  static const uint32_t N_MEASUREMENTS = 1000000;
526 
529 
531 
532 private:
533  virtual void DoRun (void);
534 };
535 
537  : TestCase ("Antithetic Normal Random Variable Stream Generator")
538 {
539 }
540 
542 {
543 }
544 
545 double
547 {
548  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
549 
550  double range[N_BINS + 1];
551  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
552  range[0] = -std::numeric_limits<double>::max ();
553  range[N_BINS] = std::numeric_limits<double>::max ();
554 
555  gsl_histogram_set_ranges (h, range, N_BINS + 1);
556 
557  double expected[N_BINS];
558 
559  // Note that this assumes that n has mean equal to zero and standard
560  // deviation equal to one, which are their default values for this
561  // distribution.
562  double sigma = 1.;
563 
564  for (uint32_t i = 0; i < N_BINS; ++i)
565  {
566  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
567  expected[i] *= N_MEASUREMENTS;
568  }
569 
570  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
571  {
572  gsl_histogram_increment (h, n->GetValue ());
573  }
574 
575  double tmp[N_BINS];
576 
577  for (uint32_t i = 0; i < N_BINS; ++i)
578  {
579  tmp[i] = gsl_histogram_get (h, i);
580  tmp[i] -= expected[i];
581  tmp[i] *= tmp[i];
582  tmp[i] /= expected[i];
583  }
584 
585  gsl_histogram_free (h);
586 
587  double chiSquared = 0;
588 
589  for (uint32_t i = 0; i < N_BINS; ++i)
590  {
591  chiSquared += tmp[i];
592  }
593 
594  return chiSquared;
595 }
596 
597 void
599 {
600  SeedManager::SetSeed (time (0));
601 
602  double sum = 0.;
603  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
604 
605  for (uint32_t i = 0; i < N_RUNS; ++i)
606  {
607  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
608 
609  // Make this generate antithetic values.
610  n->SetAttribute ("Antithetic", BooleanValue (true));
611 
612  double result = ChiSquaredTest (n);
613  sum += result;
614  }
615 
616  sum /= (double)N_RUNS;
617 
618  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
619 
620  double mean = 5.0;
621  double variance = 2.0;
622  double value;
623 
624  // Create the RNG with the specified range.
625  Ptr<NormalRandomVariable> x = CreateObject<NormalRandomVariable> ();
626  x->SetAttribute ("Mean", DoubleValue (mean));
627  x->SetAttribute ("Variance", DoubleValue (variance));
628 
629  // Make this generate antithetic values.
630  x->SetAttribute ("Antithetic", BooleanValue (true));
631 
632  // Calculate the mean of these values.
633  sum = 0.0;
634  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
635  {
636  value = x->GetValue ();
637  sum += value;
638  }
639  double valueMean = sum / N_MEASUREMENTS;
640 
641  // The expected value for the mean of the values returned by a
642  // normally distributed random variable is equal to mean.
643  double expectedMean = mean;
644 
645  // Test that values have approximately the right mean value.
646  double TOLERANCE = expectedMean * 1e-2;
647  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
648 }
649 
650 // ===========================================================================
651 // Test case for exponential distribution random variable stream generator
652 // ===========================================================================
654 {
655 public:
656  static const uint32_t N_RUNS = 5;
657  static const uint32_t N_BINS = 50;
658  static const uint32_t N_MEASUREMENTS = 1000000;
659 
662 
664 
665 private:
666  virtual void DoRun (void);
667 };
668 
670  : TestCase ("Exponential Random Variable Stream Generator")
671 {
672 }
673 
675 {
676 }
677 
678 double
680 {
681  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
682 
683  double range[N_BINS + 1];
684  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
685  range[N_BINS] = std::numeric_limits<double>::max ();
686 
687  gsl_histogram_set_ranges (h, range, N_BINS + 1);
688 
689  double expected[N_BINS];
690 
691  // Note that this assumes that e has mean equal to one, which is the
692  // default value for this distribution.
693  double mu = 1.;
694 
695  for (uint32_t i = 0; i < N_BINS; ++i)
696  {
697  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
698  expected[i] *= N_MEASUREMENTS;
699  }
700 
701  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
702  {
703  gsl_histogram_increment (h, e->GetValue ());
704  }
705 
706  double tmp[N_BINS];
707 
708  for (uint32_t i = 0; i < N_BINS; ++i)
709  {
710  tmp[i] = gsl_histogram_get (h, i);
711  tmp[i] -= expected[i];
712  tmp[i] *= tmp[i];
713  tmp[i] /= expected[i];
714  }
715 
716  gsl_histogram_free (h);
717 
718  double chiSquared = 0;
719 
720  for (uint32_t i = 0; i < N_BINS; ++i)
721  {
722  chiSquared += tmp[i];
723  }
724 
725  return chiSquared;
726 }
727 
728 void
730 {
731  SeedManager::SetSeed (time (0));
732 
733  double sum = 0.;
734  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
735 
736  for (uint32_t i = 0; i < N_RUNS; ++i)
737  {
738  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
739  double result = ChiSquaredTest (e);
740  sum += result;
741  }
742 
743  sum /= (double)N_RUNS;
744 
745  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
746 
747  double mean = 3.14;
748  double bound = 0.0;
749  double value;
750 
751  // Create the RNG with the specified range.
752  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
753  x->SetAttribute ("Mean", DoubleValue (mean));
754  x->SetAttribute ("Bound", DoubleValue (bound));
755 
756  // Calculate the mean of these values.
757  sum = 0.0;
758  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
759  {
760  value = x->GetValue ();
761  sum += value;
762  }
763  double valueMean = sum / N_MEASUREMENTS;
764 
765  // Test that values have approximately the right mean value.
766  double TOLERANCE = mean * 1e-2;
767  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
768 }
769 
770 // ===========================================================================
771 // Test case for antithetic exponential distribution random variable stream generator
772 // ===========================================================================
774 {
775 public:
776  static const uint32_t N_RUNS = 5;
777  static const uint32_t N_BINS = 50;
778  static const uint32_t N_MEASUREMENTS = 1000000;
779 
782 
784 
785 private:
786  virtual void DoRun (void);
787 };
788 
790  : TestCase ("Antithetic Exponential Random Variable Stream Generator")
791 {
792 }
793 
795 {
796 }
797 
798 double
800 {
801  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
802 
803  double range[N_BINS + 1];
804  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
805  range[N_BINS] = std::numeric_limits<double>::max ();
806 
807  gsl_histogram_set_ranges (h, range, N_BINS + 1);
808 
809  double expected[N_BINS];
810 
811  // Note that this assumes that e has mean equal to one, which is the
812  // default value for this distribution.
813  double mu = 1.;
814 
815  for (uint32_t i = 0; i < N_BINS; ++i)
816  {
817  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
818  expected[i] *= N_MEASUREMENTS;
819  }
820 
821  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
822  {
823  gsl_histogram_increment (h, e->GetValue ());
824  }
825 
826  double tmp[N_BINS];
827 
828  for (uint32_t i = 0; i < N_BINS; ++i)
829  {
830  tmp[i] = gsl_histogram_get (h, i);
831  tmp[i] -= expected[i];
832  tmp[i] *= tmp[i];
833  tmp[i] /= expected[i];
834  }
835 
836  gsl_histogram_free (h);
837 
838  double chiSquared = 0;
839 
840  for (uint32_t i = 0; i < N_BINS; ++i)
841  {
842  chiSquared += tmp[i];
843  }
844 
845  return chiSquared;
846 }
847 
848 void
850 {
851  SeedManager::SetSeed (time (0));
852 
853  double sum = 0.;
854  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
855 
856  for (uint32_t i = 0; i < N_RUNS; ++i)
857  {
858  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
859 
860  // Make this generate antithetic values.
861  e->SetAttribute ("Antithetic", BooleanValue (true));
862 
863  double result = ChiSquaredTest (e);
864  sum += result;
865  }
866 
867  sum /= (double)N_RUNS;
868 
869  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
870 
871  double mean = 3.14;
872  double bound = 0.0;
873  double value;
874 
875  // Create the RNG with the specified range.
876  Ptr<ExponentialRandomVariable> x = CreateObject<ExponentialRandomVariable> ();
877  x->SetAttribute ("Mean", DoubleValue (mean));
878  x->SetAttribute ("Bound", DoubleValue (bound));
879 
880  // Make this generate antithetic values.
881  x->SetAttribute ("Antithetic", BooleanValue (true));
882 
883  // Calculate the mean of these values.
884  sum = 0.0;
885  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
886  {
887  value = x->GetValue ();
888  sum += value;
889  }
890  double valueMean = sum / N_MEASUREMENTS;
891 
892  // Test that values have approximately the right mean value.
893  double TOLERANCE = mean * 1e-2;
894  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, mean, TOLERANCE, "Wrong mean value.");
895 }
896 
897 // ===========================================================================
898 // Test case for Pareto distribution random variable stream generator
899 // ===========================================================================
901 {
902 public:
903  static const uint32_t N_RUNS = 5;
904  static const uint32_t N_BINS = 50;
905  static const uint32_t N_MEASUREMENTS = 1000000;
906 
909 
911 
912 private:
913  virtual void DoRun (void);
914 };
915 
917  : TestCase ("Pareto Random Variable Stream Generator")
918 {
919 }
920 
922 {
923 }
924 
925 double
927 {
928  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
929 
930  double range[N_BINS + 1];
931  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
932  range[N_BINS] = std::numeric_limits<double>::max ();
933 
934  gsl_histogram_set_ranges (h, range, N_BINS + 1);
935 
936  double expected[N_BINS];
937 
938  // Note that this assumes that p has mean equal to 1 and shape equal
939  // to 2, which are their default values for this distribution.
940  double mean = 1.0;
941  double shape = 2.0;
942  double scale = mean * (shape - 1.0) / shape;
943 
944  for (uint32_t i = 0; i < N_BINS; ++i)
945  {
946  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
947  expected[i] *= N_MEASUREMENTS;
948  }
949 
950  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
951  {
952  gsl_histogram_increment (h, p->GetValue ());
953  }
954 
955  double tmp[N_BINS];
956 
957  for (uint32_t i = 0; i < N_BINS; ++i)
958  {
959  tmp[i] = gsl_histogram_get (h, i);
960  tmp[i] -= expected[i];
961  tmp[i] *= tmp[i];
962  tmp[i] /= expected[i];
963  }
964 
965  gsl_histogram_free (h);
966 
967  double chiSquared = 0;
968 
969  for (uint32_t i = 0; i < N_BINS; ++i)
970  {
971  chiSquared += tmp[i];
972  }
973 
974  return chiSquared;
975 }
976 
977 void
979 {
980  SeedManager::SetSeed (time (0));
981 
982  double sum = 0.;
983  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
984 
985  for (uint32_t i = 0; i < N_RUNS; ++i)
986  {
987  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
988  double result = ChiSquaredTest (e);
989  sum += result;
990  }
991 
992  sum /= (double)N_RUNS;
993 
994  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
995 
996  double mean = 5.0;
997  double shape = 2.0;
998  double scale = mean * (shape - 1.0) / shape;
999  double value;
1000 
1001  // Create the RNG with the specified range.
1002  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1003  x->SetAttribute ("Mean", DoubleValue (mean));
1004  x->SetAttribute ("Shape", DoubleValue (shape));
1005 
1006  // Calculate the mean of these values.
1007  sum = 0.0;
1008  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1009  {
1010  value = x->GetValue ();
1011  sum += value;
1012  }
1013  double valueMean = sum / N_MEASUREMENTS;
1014 
1015  // The expected value for the mean is given by
1016  //
1017  // shape * scale
1018  // E[value] = --------------- ,
1019  // shape - 1
1020  //
1021  // where
1022  //
1023  // scale = mean * (shape - 1.0) / shape .
1024  double expectedMean = (shape * scale) / (shape - 1.0);
1025 
1026  // Test that values have approximately the right mean value.
1027  double TOLERANCE = expectedMean * 1e-2;
1028  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1029 }
1030 
1031 // ===========================================================================
1032 // Test case for antithetic Pareto distribution random variable stream generator
1033 // ===========================================================================
1035 {
1036 public:
1037  static const uint32_t N_RUNS = 5;
1038  static const uint32_t N_BINS = 50;
1039  static const uint32_t N_MEASUREMENTS = 1000000;
1040 
1043 
1045 
1046 private:
1047  virtual void DoRun (void);
1048 };
1049 
1051  : TestCase ("Antithetic Pareto Random Variable Stream Generator")
1052 {
1053 }
1054 
1056 {
1057 }
1058 
1059 double
1061 {
1062  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1063 
1064  double range[N_BINS + 1];
1065  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1066  range[N_BINS] = std::numeric_limits<double>::max ();
1067 
1068  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1069 
1070  double expected[N_BINS];
1071 
1072  // Note that this assumes that p has mean equal to 1 and shape equal
1073  // to 2, which are their default values for this distribution.
1074  double mean = 1.0;
1075  double shape = 2.0;
1076  double scale = mean * (shape - 1.0) / shape;
1077 
1078  for (uint32_t i = 0; i < N_BINS; ++i)
1079  {
1080  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
1081  expected[i] *= N_MEASUREMENTS;
1082  }
1083 
1084  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1085  {
1086  gsl_histogram_increment (h, p->GetValue ());
1087  }
1088 
1089  double tmp[N_BINS];
1090 
1091  for (uint32_t i = 0; i < N_BINS; ++i)
1092  {
1093  tmp[i] = gsl_histogram_get (h, i);
1094  tmp[i] -= expected[i];
1095  tmp[i] *= tmp[i];
1096  tmp[i] /= expected[i];
1097  }
1098 
1099  gsl_histogram_free (h);
1100 
1101  double chiSquared = 0;
1102 
1103  for (uint32_t i = 0; i < N_BINS; ++i)
1104  {
1105  chiSquared += tmp[i];
1106  }
1107 
1108  return chiSquared;
1109 }
1110 
1111 void
1113 {
1114  SeedManager::SetSeed (time (0));
1115 
1116  double sum = 0.;
1117  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1118 
1119  for (uint32_t i = 0; i < N_RUNS; ++i)
1120  {
1121  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
1122 
1123  // Make this generate antithetic values.
1124  e->SetAttribute ("Antithetic", BooleanValue (true));
1125 
1126  double result = ChiSquaredTest (e);
1127  sum += result;
1128  }
1129 
1130  sum /= (double)N_RUNS;
1131 
1132  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1133 
1134  double mean = 5.0;
1135  double shape = 2.0;
1136  double scale = mean * (shape - 1.0) / shape;
1137  double value;
1138 
1139  // Create the RNG with the specified range.
1140  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1141  x->SetAttribute ("Mean", DoubleValue (mean));
1142  x->SetAttribute ("Shape", DoubleValue (shape));
1143 
1144  // Make this generate antithetic values.
1145  x->SetAttribute ("Antithetic", BooleanValue (true));
1146 
1147  // Calculate the mean of these values.
1148  sum = 0.0;
1149  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1150  {
1151  value = x->GetValue ();
1152  sum += value;
1153  }
1154  double valueMean = sum / N_MEASUREMENTS;
1155 
1156  // The expected value for the mean is given by
1157  //
1158  // shape * scale
1159  // E[value] = --------------- ,
1160  // shape - 1
1161  //
1162  // where
1163  //
1164  // scale = mean * (shape - 1.0) / shape .
1165  //
1166  double expectedMean = (shape * scale) / (shape - 1.0);
1167 
1168  // Test that values have approximately the right mean value.
1169  double TOLERANCE = expectedMean * 1e-2;
1170  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1171 }
1172 
1173 // ===========================================================================
1174 // Test case for Weibull distribution random variable stream generator
1175 // ===========================================================================
1177 {
1178 public:
1179  static const uint32_t N_RUNS = 5;
1180  static const uint32_t N_BINS = 50;
1181  static const uint32_t N_MEASUREMENTS = 1000000;
1182 
1185 
1187 
1188 private:
1189  virtual void DoRun (void);
1190 };
1191 
1193  : TestCase ("Weibull Random Variable Stream Generator")
1194 {
1195 }
1196 
1198 {
1199 }
1200 
1201 double
1203 {
1204  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1205 
1206  double range[N_BINS + 1];
1207  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1208  range[N_BINS] = std::numeric_limits<double>::max ();
1209 
1210  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1211 
1212  double expected[N_BINS];
1213 
1214  // Note that this assumes that p has shape equal to one and scale
1215  // equal to one, which are their default values for this
1216  // distribution.
1217  double a = 1.0;
1218  double b = 1.0;
1219 
1220  for (uint32_t i = 0; i < N_BINS; ++i)
1221  {
1222  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1223  expected[i] *= N_MEASUREMENTS;
1224  }
1225 
1226  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1227  {
1228  gsl_histogram_increment (h, p->GetValue ());
1229  }
1230 
1231  double tmp[N_BINS];
1232 
1233  for (uint32_t i = 0; i < N_BINS; ++i)
1234  {
1235  tmp[i] = gsl_histogram_get (h, i);
1236  tmp[i] -= expected[i];
1237  tmp[i] *= tmp[i];
1238  tmp[i] /= expected[i];
1239  }
1240 
1241  gsl_histogram_free (h);
1242 
1243  double chiSquared = 0;
1244 
1245  for (uint32_t i = 0; i < N_BINS; ++i)
1246  {
1247  chiSquared += tmp[i];
1248  }
1249 
1250  return chiSquared;
1251 }
1252 
1253 void
1255 {
1256  SeedManager::SetSeed (time (0));
1257 
1258  double sum = 0.;
1259  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1260 
1261  for (uint32_t i = 0; i < N_RUNS; ++i)
1262  {
1263  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1264  double result = ChiSquaredTest (e);
1265  sum += result;
1266  }
1267 
1268  sum /= (double)N_RUNS;
1269 
1270  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1271 
1272  double scale = 5.0;
1273  double shape = 1.0;
1274  double value;
1275 
1276  // Create the RNG with the specified range.
1277  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1278  x->SetAttribute ("Scale", DoubleValue (scale));
1279  x->SetAttribute ("Shape", DoubleValue (shape));
1280 
1281  // Calculate the mean of these values.
1282  sum = 0.0;
1283  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1284  {
1285  value = x->GetValue ();
1286  sum += value;
1287  }
1288  double valueMean = sum / N_MEASUREMENTS;
1289 
1290  // The expected value for the mean of the values returned by a
1291  // Weibull distributed random variable is
1292  //
1293  // E[value] = scale * Gamma(1 + 1 / shape) ,
1294  //
1295  // where Gamma() is the Gamma function. Note that
1296  //
1297  // Gamma(n) = (n - 1)!
1298  //
1299  // if n is a positive integer.
1300  //
1301  // For this test,
1302  //
1303  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1304  // = Gamma(2)
1305  // = (2 - 1)!
1306  // = 1
1307  //
1308  // which means
1309  //
1310  // E[value] = scale .
1311  //
1312  double expectedMean = scale;
1313 
1314  // Test that values have approximately the right mean value.
1315  double TOLERANCE = expectedMean * 1e-2;
1316  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1317 }
1318 
1319 // ===========================================================================
1320 // Test case for antithetic Weibull distribution random variable stream generator
1321 // ===========================================================================
1323 {
1324 public:
1325  static const uint32_t N_RUNS = 5;
1326  static const uint32_t N_BINS = 50;
1327  static const uint32_t N_MEASUREMENTS = 1000000;
1328 
1331 
1333 
1334 private:
1335  virtual void DoRun (void);
1336 };
1337 
1339  : TestCase ("Antithetic Weibull Random Variable Stream Generator")
1340 {
1341 }
1342 
1344 {
1345 }
1346 
1347 double
1349 {
1350  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1351 
1352  double range[N_BINS + 1];
1353  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1354  range[N_BINS] = std::numeric_limits<double>::max ();
1355 
1356  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1357 
1358  double expected[N_BINS];
1359 
1360  // Note that this assumes that p has shape equal to one and scale
1361  // equal to one, which are their default values for this
1362  // distribution.
1363  double a = 1.0;
1364  double b = 1.0;
1365 
1366  for (uint32_t i = 0; i < N_BINS; ++i)
1367  {
1368  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1369  expected[i] *= N_MEASUREMENTS;
1370  }
1371 
1372  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1373  {
1374  gsl_histogram_increment (h, p->GetValue ());
1375  }
1376 
1377  double tmp[N_BINS];
1378 
1379  for (uint32_t i = 0; i < N_BINS; ++i)
1380  {
1381  tmp[i] = gsl_histogram_get (h, i);
1382  tmp[i] -= expected[i];
1383  tmp[i] *= tmp[i];
1384  tmp[i] /= expected[i];
1385  }
1386 
1387  gsl_histogram_free (h);
1388 
1389  double chiSquared = 0;
1390 
1391  for (uint32_t i = 0; i < N_BINS; ++i)
1392  {
1393  chiSquared += tmp[i];
1394  }
1395 
1396  return chiSquared;
1397 }
1398 
1399 void
1401 {
1402  SeedManager::SetSeed (time (0));
1403 
1404  double sum = 0.;
1405  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1406 
1407  for (uint32_t i = 0; i < N_RUNS; ++i)
1408  {
1409  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1410 
1411  // Make this generate antithetic values.
1412  e->SetAttribute ("Antithetic", BooleanValue (true));
1413 
1414  double result = ChiSquaredTest (e);
1415  sum += result;
1416  }
1417 
1418  sum /= (double)N_RUNS;
1419 
1420  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1421 
1422  double scale = 5.0;
1423  double shape = 1.0;
1424  double value;
1425 
1426  // Create the RNG with the specified range.
1427  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1428  x->SetAttribute ("Scale", DoubleValue (scale));
1429  x->SetAttribute ("Shape", DoubleValue (shape));
1430 
1431  // Make this generate antithetic values.
1432  x->SetAttribute ("Antithetic", BooleanValue (true));
1433 
1434  // Calculate the mean of these values.
1435  sum = 0.0;
1436  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1437  {
1438  value = x->GetValue ();
1439  sum += value;
1440  }
1441  double valueMean = sum / N_MEASUREMENTS;
1442 
1443  // The expected value for the mean of the values returned by a
1444  // Weibull distributed random variable is
1445  //
1446  // E[value] = scale * Gamma(1 + 1 / shape) ,
1447  //
1448  // where Gamma() is the Gamma function. Note that
1449  //
1450  // Gamma(n) = (n - 1)!
1451  //
1452  // if n is a positive integer.
1453  //
1454  // For this test,
1455  //
1456  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1457  // = Gamma(2)
1458  // = (2 - 1)!
1459  // = 1
1460  //
1461  // which means
1462  //
1463  // E[value] = scale .
1464  //
1465  double expectedMean = scale;
1466 
1467  // Test that values have approximately the right mean value.
1468  double TOLERANCE = expectedMean * 1e-2;
1469  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1470 }
1471 
1472 // ===========================================================================
1473 // Test case for log-normal distribution random variable stream generator
1474 // ===========================================================================
1476 {
1477 public:
1478  static const uint32_t N_RUNS = 5;
1479  static const uint32_t N_BINS = 50;
1480  static const uint32_t N_MEASUREMENTS = 1000000;
1481 
1484 
1486 
1487 private:
1488  virtual void DoRun (void);
1489 };
1490 
1492  : TestCase ("Log-Normal Random Variable Stream Generator")
1493 {
1494 }
1495 
1497 {
1498 }
1499 
1500 double
1502 {
1503  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1504 
1505  double range[N_BINS + 1];
1506  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1507  range[N_BINS] = std::numeric_limits<double>::max ();
1508 
1509  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1510 
1511  double expected[N_BINS];
1512 
1513  // Note that this assumes that n has mu equal to zero and sigma
1514  // equal to one, which are their default values for this
1515  // distribution.
1516  double mu = 0.0;
1517  double sigma = 1.0;
1518 
1519  for (uint32_t i = 0; i < N_BINS; ++i)
1520  {
1521  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1522  expected[i] *= N_MEASUREMENTS;
1523  }
1524 
1525  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1526  {
1527  gsl_histogram_increment (h, n->GetValue ());
1528  }
1529 
1530  double tmp[N_BINS];
1531 
1532  for (uint32_t i = 0; i < N_BINS; ++i)
1533  {
1534  tmp[i] = gsl_histogram_get (h, i);
1535  tmp[i] -= expected[i];
1536  tmp[i] *= tmp[i];
1537  tmp[i] /= expected[i];
1538  }
1539 
1540  gsl_histogram_free (h);
1541 
1542  double chiSquared = 0;
1543 
1544  for (uint32_t i = 0; i < N_BINS; ++i)
1545  {
1546  chiSquared += tmp[i];
1547  }
1548 
1549  return chiSquared;
1550 }
1551 
1552 void
1554 {
1555  SeedManager::SetSeed (time (0));
1556 
1557  double sum = 0.;
1558  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1559 
1560  for (uint32_t i = 0; i < N_RUNS; ++i)
1561  {
1562  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1563  double result = ChiSquaredTest (n);
1564  sum += result;
1565  }
1566 
1567  sum /= (double)N_RUNS;
1568 
1569  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1570 
1571  double mu = 5.0;
1572  double sigma = 2.0;
1573  double value;
1574 
1575  // Create the RNG with the specified range.
1576  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1577  x->SetAttribute ("Mu", DoubleValue (mu));
1578  x->SetAttribute ("Sigma", DoubleValue (sigma));
1579 
1580  // Calculate the mean of these values.
1581  sum = 0.0;
1582  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1583  {
1584  value = x->GetValue ();
1585  sum += value;
1586  }
1587  double valueMean = sum / N_MEASUREMENTS;
1588 
1589  // The expected value for the mean of the values returned by a
1590  // log-normally distributed random variable is equal to
1591  //
1592  // 2
1593  // mu + sigma / 2
1594  // E[value] = e .
1595  //
1596  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1597 
1598  // Test that values have approximately the right mean value.
1599  //
1600  // XXX This test fails sometimes if the required tolerance is less
1601  // than 3%, which may be because there is a bug in the
1602  // implementation or that the mean of this distribution is more
1603  // senstive to its parameters than the others are.
1604  double TOLERANCE = expectedMean * 3e-2;
1605  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1606 }
1607 
1608 // ===========================================================================
1609 // Test case for antithetic log-normal distribution random variable stream generator
1610 // ===========================================================================
1612 {
1613 public:
1614  static const uint32_t N_RUNS = 5;
1615  static const uint32_t N_BINS = 50;
1616  static const uint32_t N_MEASUREMENTS = 1000000;
1617 
1620 
1622 
1623 private:
1624  virtual void DoRun (void);
1625 };
1626 
1628  : TestCase ("Antithetic Log-Normal Random Variable Stream Generator")
1629 {
1630 }
1631 
1633 {
1634 }
1635 
1636 double
1638 {
1639  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1640 
1641  double range[N_BINS + 1];
1642  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1643  range[N_BINS] = std::numeric_limits<double>::max ();
1644 
1645  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1646 
1647  double expected[N_BINS];
1648 
1649  // Note that this assumes that n has mu equal to zero and sigma
1650  // equal to one, which are their default values for this
1651  // distribution.
1652  double mu = 0.0;
1653  double sigma = 1.0;
1654 
1655  for (uint32_t i = 0; i < N_BINS; ++i)
1656  {
1657  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1658  expected[i] *= N_MEASUREMENTS;
1659  }
1660 
1661  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1662  {
1663  gsl_histogram_increment (h, n->GetValue ());
1664  }
1665 
1666  double tmp[N_BINS];
1667 
1668  for (uint32_t i = 0; i < N_BINS; ++i)
1669  {
1670  tmp[i] = gsl_histogram_get (h, i);
1671  tmp[i] -= expected[i];
1672  tmp[i] *= tmp[i];
1673  tmp[i] /= expected[i];
1674  }
1675 
1676  gsl_histogram_free (h);
1677 
1678  double chiSquared = 0;
1679 
1680  for (uint32_t i = 0; i < N_BINS; ++i)
1681  {
1682  chiSquared += tmp[i];
1683  }
1684 
1685  return chiSquared;
1686 }
1687 
1688 void
1690 {
1691  SeedManager::SetSeed (time (0));
1692 
1693  double sum = 0.;
1694  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1695 
1696  for (uint32_t i = 0; i < N_RUNS; ++i)
1697  {
1698  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1699 
1700  // Make this generate antithetic values.
1701  n->SetAttribute ("Antithetic", BooleanValue (true));
1702 
1703  double result = ChiSquaredTest (n);
1704  sum += result;
1705  }
1706 
1707  sum /= (double)N_RUNS;
1708 
1709  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1710 
1711  double mu = 5.0;
1712  double sigma = 2.0;
1713  double value;
1714 
1715  // Create the RNG with the specified range.
1716  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1717  x->SetAttribute ("Mu", DoubleValue (mu));
1718  x->SetAttribute ("Sigma", DoubleValue (sigma));
1719 
1720  // Make this generate antithetic values.
1721  x->SetAttribute ("Antithetic", BooleanValue (true));
1722 
1723  // Calculate the mean of these values.
1724  sum = 0.0;
1725  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1726  {
1727  value = x->GetValue ();
1728  sum += value;
1729  }
1730  double valueMean = sum / N_MEASUREMENTS;
1731 
1732  // The expected value for the mean of the values returned by a
1733  // log-normally distributed random variable is equal to
1734  //
1735  // 2
1736  // mu + sigma / 2
1737  // E[value] = e .
1738  //
1739  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1740 
1741  // Test that values have approximately the right mean value.
1742  //
1743  // XXX This test fails sometimes if the required tolerance is less
1744  // than 3%, which may be because there is a bug in the
1745  // implementation or that the mean of this distribution is more
1746  // senstive to its parameters than the others are.
1747  double TOLERANCE = expectedMean * 3e-2;
1748  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1749 }
1750 
1751 // ===========================================================================
1752 // Test case for gamma distribution random variable stream generator
1753 // ===========================================================================
1755 {
1756 public:
1757  static const uint32_t N_RUNS = 5;
1758  static const uint32_t N_BINS = 50;
1759  static const uint32_t N_MEASUREMENTS = 1000000;
1760 
1763 
1765 
1766 private:
1767  virtual void DoRun (void);
1768 };
1769 
1771  : TestCase ("Gamma Random Variable Stream Generator")
1772 {
1773 }
1774 
1776 {
1777 }
1778 
1779 double
1781 {
1782  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1783 
1784  double range[N_BINS + 1];
1785  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1786  range[N_BINS] = std::numeric_limits<double>::max ();
1787 
1788  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1789 
1790  double expected[N_BINS];
1791 
1792  // Note that this assumes that n has alpha equal to one and beta
1793  // equal to one, which are their default values for this
1794  // distribution.
1795  double alpha = 1.0;
1796  double beta = 1.0;
1797 
1798  for (uint32_t i = 0; i < N_BINS; ++i)
1799  {
1800  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
1801  expected[i] *= N_MEASUREMENTS;
1802  }
1803 
1804  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1805  {
1806  gsl_histogram_increment (h, n->GetValue ());
1807  }
1808 
1809  double tmp[N_BINS];
1810 
1811  for (uint32_t i = 0; i < N_BINS; ++i)
1812  {
1813  tmp[i] = gsl_histogram_get (h, i);
1814  tmp[i] -= expected[i];
1815  tmp[i] *= tmp[i];
1816  tmp[i] /= expected[i];
1817  }
1818 
1819  gsl_histogram_free (h);
1820 
1821  double chiSquared = 0;
1822 
1823  for (uint32_t i = 0; i < N_BINS; ++i)
1824  {
1825  chiSquared += tmp[i];
1826  }
1827 
1828  return chiSquared;
1829 }
1830 
1831 void
1833 {
1834  SeedManager::SetSeed (time (0));
1835 
1836  double sum = 0.;
1837  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1838 
1839  for (uint32_t i = 0; i < N_RUNS; ++i)
1840  {
1841  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
1842  double result = ChiSquaredTest (n);
1843  sum += result;
1844  }
1845 
1846  sum /= (double)N_RUNS;
1847 
1848  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1849 
1850  double alpha = 5.0;
1851  double beta = 2.0;
1852  double value;
1853 
1854  // Create the RNG with the specified range.
1855  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
1856  x->SetAttribute ("Alpha", DoubleValue (alpha));
1857  x->SetAttribute ("Beta", DoubleValue (beta));
1858 
1859  // Calculate the mean of these values.
1860  sum = 0.0;
1861  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1862  {
1863  value = x->GetValue ();
1864  sum += value;
1865  }
1866  double valueMean = sum / N_MEASUREMENTS;
1867 
1868  // The expected value for the mean of the values returned by a
1869  // gammaly distributed random variable is equal to
1870  //
1871  // E[value] = alpha * beta .
1872  //
1873  double expectedMean = alpha * beta;
1874 
1875  // Test that values have approximately the right mean value.
1876  double TOLERANCE = expectedMean * 1e-2;
1877  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1878 }
1879 
1880 // ===========================================================================
1881 // Test case for antithetic gamma distribution random variable stream generator
1882 // ===========================================================================
1884 {
1885 public:
1886  static const uint32_t N_RUNS = 5;
1887  static const uint32_t N_BINS = 50;
1888  static const uint32_t N_MEASUREMENTS = 1000000;
1889 
1892 
1894 
1895 private:
1896  virtual void DoRun (void);
1897 };
1898 
1900  : TestCase ("Antithetic Gamma Random Variable Stream Generator")
1901 {
1902 }
1903 
1905 {
1906 }
1907 
1908 double
1910 {
1911  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1912 
1913  double range[N_BINS + 1];
1914  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1915  range[N_BINS] = std::numeric_limits<double>::max ();
1916 
1917  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1918 
1919  double expected[N_BINS];
1920 
1921  // Note that this assumes that n has alpha equal to one and beta
1922  // equal to one, which are their default values for this
1923  // distribution.
1924  double alpha = 1.0;
1925  double beta = 1.0;
1926 
1927  for (uint32_t i = 0; i < N_BINS; ++i)
1928  {
1929  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
1930  expected[i] *= N_MEASUREMENTS;
1931  }
1932 
1933  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1934  {
1935  gsl_histogram_increment (h, n->GetValue ());
1936  }
1937 
1938  double tmp[N_BINS];
1939 
1940  for (uint32_t i = 0; i < N_BINS; ++i)
1941  {
1942  tmp[i] = gsl_histogram_get (h, i);
1943  tmp[i] -= expected[i];
1944  tmp[i] *= tmp[i];
1945  tmp[i] /= expected[i];
1946  }
1947 
1948  gsl_histogram_free (h);
1949 
1950  double chiSquared = 0;
1951 
1952  for (uint32_t i = 0; i < N_BINS; ++i)
1953  {
1954  chiSquared += tmp[i];
1955  }
1956 
1957  return chiSquared;
1958 }
1959 
1960 void
1962 {
1963  SeedManager::SetSeed (time (0));
1964 
1965  double sum = 0.;
1966  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1967 
1968  for (uint32_t i = 0; i < N_RUNS; ++i)
1969  {
1970  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
1971 
1972  // Make this generate antithetic values.
1973  n->SetAttribute ("Antithetic", BooleanValue (true));
1974 
1975  double result = ChiSquaredTest (n);
1976  sum += result;
1977  }
1978 
1979  sum /= (double)N_RUNS;
1980 
1981  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1982 
1983  double alpha = 5.0;
1984  double beta = 2.0;
1985  double value;
1986 
1987  // Create the RNG with the specified range.
1988  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
1989 
1990  // Make this generate antithetic values.
1991  x->SetAttribute ("Antithetic", BooleanValue (true));
1992 
1993  x->SetAttribute ("Alpha", DoubleValue (alpha));
1994  x->SetAttribute ("Beta", DoubleValue (beta));
1995 
1996  // Calculate the mean of these values.
1997  sum = 0.0;
1998  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1999  {
2000  value = x->GetValue ();
2001  sum += value;
2002  }
2003  double valueMean = sum / N_MEASUREMENTS;
2004 
2005  // The expected value for the mean of the values returned by a
2006  // gammaly distributed random variable is equal to
2007  //
2008  // E[value] = alpha * beta .
2009  //
2010  double expectedMean = alpha * beta;
2011 
2012  // Test that values have approximately the right mean value.
2013  double TOLERANCE = expectedMean * 1e-2;
2014  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2015 }
2016 
2017 // ===========================================================================
2018 // Test case for Erlang distribution random variable stream generator
2019 // ===========================================================================
2021 {
2022 public:
2023  static const uint32_t N_RUNS = 5;
2024  static const uint32_t N_BINS = 50;
2025  static const uint32_t N_MEASUREMENTS = 1000000;
2026 
2029 
2031 
2032 private:
2033  virtual void DoRun (void);
2034 };
2035 
2037  : TestCase ("Erlang Random Variable Stream Generator")
2038 {
2039 }
2040 
2042 {
2043 }
2044 
2045 double
2047 {
2048  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2049 
2050  double range[N_BINS + 1];
2051  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2052  range[N_BINS] = std::numeric_limits<double>::max ();
2053 
2054  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2055 
2056  double expected[N_BINS];
2057 
2058  // Note that this assumes that n has k equal to one and lambda
2059  // equal to one, which are their default values for this
2060  // distribution.
2061  uint32_t k = 1;
2062  double lambda = 1.0;
2063 
2064  // Note that Erlang distribution is equal to the gamma distribution
2065  // when k is an iteger, which is why the gamma distribution's cdf
2066  // function can be used here.
2067  for (uint32_t i = 0; i < N_BINS; ++i)
2068  {
2069  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2070  expected[i] *= N_MEASUREMENTS;
2071  }
2072 
2073  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2074  {
2075  gsl_histogram_increment (h, n->GetValue ());
2076  }
2077 
2078  double tmp[N_BINS];
2079 
2080  for (uint32_t i = 0; i < N_BINS; ++i)
2081  {
2082  tmp[i] = gsl_histogram_get (h, i);
2083  tmp[i] -= expected[i];
2084  tmp[i] *= tmp[i];
2085  tmp[i] /= expected[i];
2086  }
2087 
2088  gsl_histogram_free (h);
2089 
2090  double chiSquared = 0;
2091 
2092  for (uint32_t i = 0; i < N_BINS; ++i)
2093  {
2094  chiSquared += tmp[i];
2095  }
2096 
2097  return chiSquared;
2098 }
2099 
2100 void
2102 {
2103  SeedManager::SetSeed (time (0));
2104 
2105  double sum = 0.;
2106  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2107 
2108  for (uint32_t i = 0; i < N_RUNS; ++i)
2109  {
2110  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2111  double result = ChiSquaredTest (n);
2112  sum += result;
2113  }
2114 
2115  sum /= (double)N_RUNS;
2116 
2117  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2118 
2119  uint32_t k = 5;
2120  double lambda = 2.0;
2121  double value;
2122 
2123  // Create the RNG with the specified range.
2124  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2125  x->SetAttribute ("K", IntegerValue (k));
2126  x->SetAttribute ("Lambda", DoubleValue (lambda));
2127 
2128  // Calculate the mean of these values.
2129  sum = 0.0;
2130  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2131  {
2132  value = x->GetValue ();
2133  sum += value;
2134  }
2135  double valueMean = sum / N_MEASUREMENTS;
2136 
2137  // The expected value for the mean of the values returned by a
2138  // Erlangly distributed random variable is equal to
2139  //
2140  // E[value] = k * lambda .
2141  //
2142  double expectedMean = k * lambda;
2143 
2144  // Test that values have approximately the right mean value.
2145  double TOLERANCE = expectedMean * 1e-2;
2146  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2147 }
2148 
2149 // ===========================================================================
2150 // Test case for antithetic Erlang distribution random variable stream generator
2151 // ===========================================================================
2153 {
2154 public:
2155  static const uint32_t N_RUNS = 5;
2156  static const uint32_t N_BINS = 50;
2157  static const uint32_t N_MEASUREMENTS = 1000000;
2158 
2161 
2163 
2164 private:
2165  virtual void DoRun (void);
2166 };
2167 
2169  : TestCase ("Antithetic Erlang Random Variable Stream Generator")
2170 {
2171 }
2172 
2174 {
2175 }
2176 
2177 double
2179 {
2180  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2181 
2182  double range[N_BINS + 1];
2183  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2184  range[N_BINS] = std::numeric_limits<double>::max ();
2185 
2186  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2187 
2188  double expected[N_BINS];
2189 
2190  // Note that this assumes that n has k equal to one and lambda
2191  // equal to one, which are their default values for this
2192  // distribution.
2193  uint32_t k = 1;
2194  double lambda = 1.0;
2195 
2196  // Note that Erlang distribution is equal to the gamma distribution
2197  // when k is an iteger, which is why the gamma distribution's cdf
2198  // function can be used here.
2199  for (uint32_t i = 0; i < N_BINS; ++i)
2200  {
2201  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2202  expected[i] *= N_MEASUREMENTS;
2203  }
2204 
2205  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2206  {
2207  gsl_histogram_increment (h, n->GetValue ());
2208  }
2209 
2210  double tmp[N_BINS];
2211 
2212  for (uint32_t i = 0; i < N_BINS; ++i)
2213  {
2214  tmp[i] = gsl_histogram_get (h, i);
2215  tmp[i] -= expected[i];
2216  tmp[i] *= tmp[i];
2217  tmp[i] /= expected[i];
2218  }
2219 
2220  gsl_histogram_free (h);
2221 
2222  double chiSquared = 0;
2223 
2224  for (uint32_t i = 0; i < N_BINS; ++i)
2225  {
2226  chiSquared += tmp[i];
2227  }
2228 
2229  return chiSquared;
2230 }
2231 
2232 void
2234 {
2235  SeedManager::SetSeed (time (0));
2236 
2237  double sum = 0.;
2238  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2239 
2240  for (uint32_t i = 0; i < N_RUNS; ++i)
2241  {
2242  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2243 
2244  // Make this generate antithetic values.
2245  n->SetAttribute ("Antithetic", BooleanValue (true));
2246 
2247  double result = ChiSquaredTest (n);
2248  sum += result;
2249  }
2250 
2251  sum /= (double)N_RUNS;
2252 
2253  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2254 
2255  uint32_t k = 5;
2256  double lambda = 2.0;
2257  double value;
2258 
2259  // Create the RNG with the specified range.
2260  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2261 
2262  // Make this generate antithetic values.
2263  x->SetAttribute ("Antithetic", BooleanValue (true));
2264 
2265  x->SetAttribute ("K", IntegerValue (k));
2266  x->SetAttribute ("Lambda", DoubleValue (lambda));
2267 
2268  // Calculate the mean of these values.
2269  sum = 0.0;
2270  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2271  {
2272  value = x->GetValue ();
2273  sum += value;
2274  }
2275  double valueMean = sum / N_MEASUREMENTS;
2276 
2277  // The expected value for the mean of the values returned by a
2278  // Erlangly distributed random variable is equal to
2279  //
2280  // E[value] = k * lambda .
2281  //
2282  double expectedMean = k * lambda;
2283 
2284  // Test that values have approximately the right mean value.
2285  double TOLERANCE = expectedMean * 1e-2;
2286  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2287 }
2288 
2289 // ===========================================================================
2290 // Test case for Zipf distribution random variable stream generator
2291 // ===========================================================================
2293 {
2294 public:
2295  static const uint32_t N_MEASUREMENTS = 1000000;
2296 
2299 
2300 private:
2301  virtual void DoRun (void);
2302 };
2303 
2305  : TestCase ("Zipf Random Variable Stream Generator")
2306 {
2307 }
2308 
2310 {
2311 }
2312 
2313 void
2315 {
2316  SeedManager::SetSeed (time (0));
2317 
2318  uint32_t n = 1;
2319  double alpha = 2.0;
2320  double value;
2321 
2322  // Create the RNG with the specified range.
2323  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2324  x->SetAttribute ("N", IntegerValue (n));
2325  x->SetAttribute ("Alpha", DoubleValue (alpha));
2326 
2327  // Calculate the mean of these values.
2328  double sum = 0.0;
2329  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2330  {
2331  value = x->GetValue ();
2332  sum += value;
2333  }
2334  double valueMean = sum / N_MEASUREMENTS;
2335 
2336  // The expected value for the mean of the values returned by a
2337  // Zipfly distributed random variable is equal to
2338  //
2339  // H
2340  // N, alpha - 1
2341  // E[value] = ---------------
2342  // H
2343  // N, alpha
2344  //
2345  // where
2346  //
2347  // N
2348  // ---
2349  // \ -alpha
2350  // H = / m .
2351  // N, alpha ---
2352  // m=1
2353  //
2354  // For this test,
2355  //
2356  // -(alpha - 1)
2357  // 1
2358  // E[value] = ---------------
2359  // -alpha
2360  // 1
2361  //
2362  // = 1 .
2363  //
2364  double expectedMean = 1.0;
2365 
2366  // Test that values have approximately the right mean value.
2367  double TOLERANCE = expectedMean * 1e-2;
2368  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2369 }
2370 
2371 // ===========================================================================
2372 // Test case for antithetic Zipf distribution random variable stream generator
2373 // ===========================================================================
2375 {
2376 public:
2377  static const uint32_t N_MEASUREMENTS = 1000000;
2378 
2381 
2382 private:
2383  virtual void DoRun (void);
2384 };
2385 
2387  : TestCase ("Antithetic Zipf Random Variable Stream Generator")
2388 {
2389 }
2390 
2392 {
2393 }
2394 
2395 void
2397 {
2398  SeedManager::SetSeed (time (0));
2399 
2400  uint32_t n = 1;
2401  double alpha = 2.0;
2402  double value;
2403 
2404  // Create the RNG with the specified range.
2405  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2406  x->SetAttribute ("N", IntegerValue (n));
2407  x->SetAttribute ("Alpha", DoubleValue (alpha));
2408 
2409  // Make this generate antithetic values.
2410  x->SetAttribute ("Antithetic", BooleanValue (true));
2411 
2412  // Calculate the mean of these values.
2413  double sum = 0.0;
2414  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2415  {
2416  value = x->GetValue ();
2417  sum += value;
2418  }
2419  double valueMean = sum / N_MEASUREMENTS;
2420 
2421  // The expected value for the mean of the values returned by a
2422  // Zipfly distributed random variable is equal to
2423  //
2424  // H
2425  // N, alpha - 1
2426  // E[value] = ---------------
2427  // H
2428  // N, alpha
2429  //
2430  // where
2431  //
2432  // N
2433  // ---
2434  // \ -alpha
2435  // H = / m .
2436  // N, alpha ---
2437  // m=1
2438  //
2439  // For this test,
2440  //
2441  // -(alpha - 1)
2442  // 1
2443  // E[value] = ---------------
2444  // -alpha
2445  // 1
2446  //
2447  // = 1 .
2448  //
2449  double expectedMean = 1.0;
2450 
2451  // Test that values have approximately the right mean value.
2452  double TOLERANCE = expectedMean * 1e-2;
2453  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2454 }
2455 
2456 // ===========================================================================
2457 // Test case for Zeta distribution random variable stream generator
2458 // ===========================================================================
2460 {
2461 public:
2462  static const uint32_t N_MEASUREMENTS = 1000000;
2463 
2466 
2467 private:
2468  virtual void DoRun (void);
2469 };
2470 
2472  : TestCase ("Zeta Random Variable Stream Generator")
2473 {
2474 }
2475 
2477 {
2478 }
2479 
2480 void
2482 {
2483  SeedManager::SetSeed (time (0));
2484 
2485  double alpha = 5.0;
2486  double value;
2487 
2488  // Create the RNG with the specified range.
2489  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2490  x->SetAttribute ("Alpha", DoubleValue (alpha));
2491 
2492  // Calculate the mean of these values.
2493  double sum = 0.0;
2494  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2495  {
2496  value = x->GetValue ();
2497  sum += value;
2498  }
2499  double valueMean = sum / N_MEASUREMENTS;
2500 
2501  // The expected value for the mean of the values returned by a
2502  // zetaly distributed random variable is equal to
2503  //
2504  // zeta(alpha - 1)
2505  // E[value] = --------------- for alpha > 2 ,
2506  // zeta(alpha)
2507  //
2508  // where zeta(alpha) is the Riemann zeta function.
2509  //
2510  // There are no simple analytic forms for the Riemann zeta function,
2511  // which is why the gsl library is used in this test to calculate
2512  // the known mean of the values.
2513  double expectedMean = gsl_sf_zeta_int (alpha - 1) / gsl_sf_zeta_int (alpha);
2514 
2515  // Test that values have approximately the right mean value.
2516  double TOLERANCE = expectedMean * 1e-2;
2517  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2518 }
2519 
2520 // ===========================================================================
2521 // Test case for antithetic Zeta distribution random variable stream generator
2522 // ===========================================================================
2524 {
2525 public:
2526  static const uint32_t N_MEASUREMENTS = 1000000;
2527 
2530 
2531 private:
2532  virtual void DoRun (void);
2533 };
2534 
2536  : TestCase ("Antithetic Zeta Random Variable Stream Generator")
2537 {
2538 }
2539 
2541 {
2542 }
2543 
2544 void
2546 {
2547  SeedManager::SetSeed (time (0));
2548 
2549  double alpha = 5.0;
2550  double value;
2551 
2552  // Create the RNG with the specified range.
2553  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2554  x->SetAttribute ("Alpha", DoubleValue (alpha));
2555 
2556  // Make this generate antithetic values.
2557  x->SetAttribute ("Antithetic", BooleanValue (true));
2558 
2559  // Calculate the mean of these values.
2560  double sum = 0.0;
2561  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2562  {
2563  value = x->GetValue ();
2564  sum += value;
2565  }
2566  double valueMean = sum / N_MEASUREMENTS;
2567 
2568  // The expected value for the mean of the values returned by a
2569  // zetaly distributed random variable is equal to
2570  //
2571  // zeta(alpha - 1)
2572  // E[value] = --------------- for alpha > 2 ,
2573  // zeta(alpha)
2574  //
2575  // where zeta(alpha) is the Riemann zeta function.
2576  //
2577  // There are no simple analytic forms for the Riemann zeta function,
2578  // which is why the gsl library is used in this test to calculate
2579  // the known mean of the values.
2580  double expectedMean = gsl_sf_zeta_int (alpha - 1) / gsl_sf_zeta_int (alpha);
2581 
2582  // Test that values have approximately the right mean value.
2583  double TOLERANCE = expectedMean * 1e-2;
2584  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2585 }
2586 
2587 // ===========================================================================
2588 // Test case for deterministic random variable stream generator
2589 // ===========================================================================
2591 {
2592 public:
2593  static const double TOLERANCE = 1e-8;
2594 
2597 
2598 private:
2599  virtual void DoRun (void);
2600 };
2601 
2603  : TestCase ("Deterministic Random Variable Stream Generator")
2604 {
2605 }
2606 
2608 {
2609 }
2610 
2611 void
2613 {
2614  SeedManager::SetSeed (time (0));
2615 
2616  Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
2617 
2618  // The following array should give the sequence
2619  //
2620  // 4, 4, 7, 7, 10, 10 .
2621  //
2622  double array1 [] = { 4, 4, 7, 7, 10, 10};
2623  uint64_t count1 = 6;
2624  s->SetValueArray (array1, count1);
2625 
2626  double value;
2627 
2628  // Test that the first sequence is correct.
2629  value = s->GetValue ();
2630  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2631  value = s->GetValue ();
2632  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2633  value = s->GetValue ();
2634  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2635  value = s->GetValue ();
2636  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2637  value = s->GetValue ();
2638  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2639  value = s->GetValue ();
2640  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2641 
2642  // The following array should give the sequence
2643  //
2644  // 1000, 2000, 7, 7 .
2645  //
2646  double array2 [] = { 1000, 2000, 3000, 4000};
2647  uint64_t count2 = 4;
2648  s->SetValueArray (array2, count2);
2649 
2650  // Test that the second sequence is correct.
2651  value = s->GetValue ();
2652  NS_TEST_ASSERT_MSG_EQ_TOL (value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2653  value = s->GetValue ();
2654  NS_TEST_ASSERT_MSG_EQ_TOL (value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2655  value = s->GetValue ();
2656  NS_TEST_ASSERT_MSG_EQ_TOL (value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2657  value = s->GetValue ();
2658  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2659  value = s->GetValue ();
2660 }
2661 
2662 // ===========================================================================
2663 // Test case for empirical distribution random variable stream generator
2664 // ===========================================================================
2666 {
2667 public:
2668  static const uint32_t N_MEASUREMENTS = 1000000;
2669 
2672 
2673 private:
2674  virtual void DoRun (void);
2675 };
2676 
2678  : TestCase ("Empirical Random Variable Stream Generator")
2679 {
2680 }
2681 
2683 {
2684 }
2685 
2686 void
2688 {
2689  SeedManager::SetSeed (time (0));
2690 
2691  // Create the RNG with a uniform distribution between 0 and 10.
2692  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2693  x->CDF ( 0.0, 0.0);
2694  x->CDF ( 5.0, 0.5);
2695  x->CDF (10.0, 1.0);
2696 
2697  // Calculate the mean of these values.
2698  double sum = 0.0;
2699  double value;
2700  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2701  {
2702  value = x->GetValue ();
2703  sum += value;
2704  }
2705  double valueMean = sum / N_MEASUREMENTS;
2706 
2707  // The expected value for the mean of the values returned by this
2708  // empirical distribution is the midpoint of the distribution
2709  //
2710  // E[value] = 5 .
2711  //
2712  double expectedMean = 5.0;
2713 
2714  // Test that values have approximately the right mean value.
2715  double TOLERANCE = expectedMean * 1e-2;
2716  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2717 }
2718 
2719 // ===========================================================================
2720 // Test case for antithetic empirical distribution random variable stream generator
2721 // ===========================================================================
2723 {
2724 public:
2725  static const uint32_t N_MEASUREMENTS = 1000000;
2726 
2729 
2730 private:
2731  virtual void DoRun (void);
2732 };
2733 
2735  : TestCase ("EmpiricalAntithetic Random Variable Stream Generator")
2736 {
2737 }
2738 
2740 {
2741 }
2742 
2743 void
2745 {
2746  SeedManager::SetSeed (time (0));
2747 
2748  // Create the RNG with a uniform distribution between 0 and 10.
2749  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2750  x->CDF ( 0.0, 0.0);
2751  x->CDF ( 5.0, 0.5);
2752  x->CDF (10.0, 1.0);
2753 
2754  // Make this generate antithetic values.
2755  x->SetAttribute ("Antithetic", BooleanValue (true));
2756 
2757  // Calculate the mean of these values.
2758  double sum = 0.0;
2759  double value;
2760  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2761  {
2762  value = x->GetValue ();
2763  sum += value;
2764  }
2765  double valueMean = sum / N_MEASUREMENTS;
2766 
2767  // The expected value for the mean of the values returned by this
2768  // empirical distribution is the midpoint of the distribution
2769  //
2770  // E[value] = 5 .
2771  //
2772  double expectedMean = 5.0;
2773 
2774  // Test that values have approximately the right mean value.
2775  double TOLERANCE = expectedMean * 1e-2;
2776  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2777 }
2778 
2780 {
2781 public:
2783 };
2784 
2786  : TestSuite ("random-variable-stream-generators", UNIT)
2787 {
2801  // XXX This test is currently disabled because it fails sometimes.
2802  // A possible reason for the failure is that the antithetic code is
2803  // not implemented properly for this log-normal case.
2804  /*
2805  AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase);
2806  */
2808  // XXX This test is currently disabled because it fails sometimes.
2809  // A possible reason for the failure is that the antithetic code is
2810  // not implemented properly for this gamma case.
2811  /*
2812  AddTestCase (new RandomVariableStreamGammaAntitheticTestCase);
2813  */
2823 }
2824