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