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