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  double shape = 2.0;
1040  double scale = 1.0;
1041 
1042  for (uint32_t i = 0; i < N_BINS; ++i)
1043  {
1044  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
1045  expected[i] *= N_MEASUREMENTS;
1046  }
1047 
1048  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1049  {
1050  gsl_histogram_increment (h, p->GetValue ());
1051  }
1052 
1053  double tmp[N_BINS];
1054 
1055  for (uint32_t i = 0; i < N_BINS; ++i)
1056  {
1057  tmp[i] = gsl_histogram_get (h, i);
1058  tmp[i] -= expected[i];
1059  tmp[i] *= tmp[i];
1060  tmp[i] /= expected[i];
1061  }
1062 
1063  gsl_histogram_free (h);
1064 
1065  double chiSquared = 0;
1066 
1067  for (uint32_t i = 0; i < N_BINS; ++i)
1068  {
1069  chiSquared += tmp[i];
1070  }
1071 
1072  return chiSquared;
1073 }
1074 
1075 void
1077 {
1078  SetTestSuiteSeed ();
1079 
1080  double sum = 0.;
1081  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1082 
1083  for (uint32_t i = 0; i < N_RUNS; ++i)
1084  {
1085  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
1086  double result = ChiSquaredTest (e);
1087  sum += result;
1088  }
1089 
1090  sum /= (double)N_RUNS;
1091 
1092  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1093 
1094  double shape = 2.0;
1095  double scale = 1.0;
1096  double value;
1097 
1098  // Create the RNG with the specified range.
1099  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1100  x->SetAttribute ("Shape", DoubleValue (shape));
1101  x->SetAttribute ("Scale", DoubleValue (scale));
1102 
1103  // Calculate the mean of these values.
1104  sum = 0.0;
1105  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1106  {
1107  value = x->GetValue ();
1108  sum += value;
1109  }
1110  double valueMean = sum / N_MEASUREMENTS;
1111 
1112  // The expected value for the mean is given by
1113  //
1114  // shape * scale
1115  // E[value] = --------------- ,
1116  // shape - 1
1117  //
1118  // where
1119  //
1120  // scale = mean * (shape - 1.0) / shape .
1121  double expectedMean = (shape * scale) / (shape - 1.0);
1122 
1123  // Test that values have approximately the right mean value.
1124  double TOLERANCE = expectedMean * 1e-2;
1125  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1126 }
1127 
1128 // ===========================================================================
1129 // Test case for antithetic Pareto distribution random variable stream generator
1130 // ===========================================================================
1132 {
1133 public:
1134  static const uint32_t N_RUNS = 5;
1135  static const uint32_t N_BINS = 50;
1136  static const uint32_t N_MEASUREMENTS = 1000000;
1137 
1140 
1142 
1143 private:
1144  virtual void DoRun (void);
1145 };
1146 
1148  : TestCase ("Antithetic Pareto Random Variable Stream Generator")
1149 {
1150 }
1151 
1153 {
1154 }
1155 
1156 double
1158 {
1159  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1160 
1161  double range[N_BINS + 1];
1162  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1164 
1165  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1166 
1167  double expected[N_BINS];
1168 
1169  double shape = 2.0;
1170  double scale = 1.0;
1171 
1172  for (uint32_t i = 0; i < N_BINS; ++i)
1173  {
1174  expected[i] = gsl_cdf_pareto_P (range[i + 1], shape, scale) - gsl_cdf_pareto_P (range[i], shape, scale);
1175  expected[i] *= N_MEASUREMENTS;
1176  }
1177 
1178  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1179  {
1180  gsl_histogram_increment (h, p->GetValue ());
1181  }
1182 
1183  double tmp[N_BINS];
1184 
1185  for (uint32_t i = 0; i < N_BINS; ++i)
1186  {
1187  tmp[i] = gsl_histogram_get (h, i);
1188  tmp[i] -= expected[i];
1189  tmp[i] *= tmp[i];
1190  tmp[i] /= expected[i];
1191  }
1192 
1193  gsl_histogram_free (h);
1194 
1195  double chiSquared = 0;
1196 
1197  for (uint32_t i = 0; i < N_BINS; ++i)
1198  {
1199  chiSquared += tmp[i];
1200  }
1201 
1202  return chiSquared;
1203 }
1204 
1205 void
1207 {
1208  SetTestSuiteSeed ();
1209 
1210  double sum = 0.;
1211  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1212 
1213  for (uint32_t i = 0; i < N_RUNS; ++i)
1214  {
1215  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
1216 
1217  // Make this generate antithetic values.
1218  e->SetAttribute ("Antithetic", BooleanValue (true));
1219 
1220  double result = ChiSquaredTest (e);
1221  sum += result;
1222  }
1223 
1224  sum /= (double)N_RUNS;
1225 
1226  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1227 
1228  double shape = 2.0;
1229  double scale = 1.0;
1230  double value;
1231 
1232  // Create the RNG with the specified range.
1233  Ptr<ParetoRandomVariable> x = CreateObject<ParetoRandomVariable> ();
1234  x->SetAttribute ("Shape", DoubleValue (shape));
1235  x->SetAttribute ("Scale", DoubleValue (scale));
1236 
1237  // Make this generate antithetic values.
1238  x->SetAttribute ("Antithetic", BooleanValue (true));
1239 
1240  // Calculate the mean of these values.
1241  sum = 0.0;
1242  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1243  {
1244  value = x->GetValue ();
1245  sum += value;
1246  }
1247  double valueMean = sum / N_MEASUREMENTS;
1248 
1249  // The expected value for the mean is given by
1250  //
1251  // shape * scale
1252  // E[value] = --------------- ,
1253  // shape - 1
1254  //
1255  // where
1256  //
1257  // scale = mean * (shape - 1.0) / shape .
1258  //
1259  double expectedMean = (shape * scale) / (shape - 1.0);
1260 
1261  // Test that values have approximately the right mean value.
1262  double TOLERANCE = expectedMean * 1e-2;
1263  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1264 }
1265 
1266 // ===========================================================================
1267 // Test case for Weibull distribution random variable stream generator
1268 // ===========================================================================
1270 {
1271 public:
1272  static const uint32_t N_RUNS = 5;
1273  static const uint32_t N_BINS = 50;
1274  static const uint32_t N_MEASUREMENTS = 1000000;
1275 
1278 
1280 
1281 private:
1282  virtual void DoRun (void);
1283 };
1284 
1286  : TestCase ("Weibull Random Variable Stream Generator")
1287 {
1288 }
1289 
1291 {
1292 }
1293 
1294 double
1296 {
1297  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1298 
1299  double range[N_BINS + 1];
1300  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1302 
1303  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1304 
1305  double expected[N_BINS];
1306 
1307  // Note that this assumes that p has shape equal to one and scale
1308  // equal to one, which are their default values for this
1309  // distribution.
1310  double a = 1.0;
1311  double b = 1.0;
1312 
1313  for (uint32_t i = 0; i < N_BINS; ++i)
1314  {
1315  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1316  expected[i] *= N_MEASUREMENTS;
1317  }
1318 
1319  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1320  {
1321  gsl_histogram_increment (h, p->GetValue ());
1322  }
1323 
1324  double tmp[N_BINS];
1325 
1326  for (uint32_t i = 0; i < N_BINS; ++i)
1327  {
1328  tmp[i] = gsl_histogram_get (h, i);
1329  tmp[i] -= expected[i];
1330  tmp[i] *= tmp[i];
1331  tmp[i] /= expected[i];
1332  }
1333 
1334  gsl_histogram_free (h);
1335 
1336  double chiSquared = 0;
1337 
1338  for (uint32_t i = 0; i < N_BINS; ++i)
1339  {
1340  chiSquared += tmp[i];
1341  }
1342 
1343  return chiSquared;
1344 }
1345 
1346 void
1348 {
1349  SetTestSuiteSeed ();
1350 
1351  double sum = 0.;
1352  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1353 
1354  for (uint32_t i = 0; i < N_RUNS; ++i)
1355  {
1356  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1357  double result = ChiSquaredTest (e);
1358  sum += result;
1359  }
1360 
1361  sum /= (double)N_RUNS;
1362 
1363  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1364 
1365  double scale = 5.0;
1366  double shape = 1.0;
1367  double value;
1368 
1369  // Create the RNG with the specified range.
1370  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1371  x->SetAttribute ("Scale", DoubleValue (scale));
1372  x->SetAttribute ("Shape", DoubleValue (shape));
1373 
1374  // Calculate the mean of these values.
1375  sum = 0.0;
1376  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1377  {
1378  value = x->GetValue ();
1379  sum += value;
1380  }
1381  double valueMean = sum / N_MEASUREMENTS;
1382 
1383  // The expected value for the mean of the values returned by a
1384  // Weibull distributed random variable is
1385  //
1386  // E[value] = scale * Gamma(1 + 1 / shape) ,
1387  //
1388  // where Gamma() is the Gamma function. Note that
1389  //
1390  // Gamma(n) = (n - 1)!
1391  //
1392  // if n is a positive integer.
1393  //
1394  // For this test,
1395  //
1396  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1397  // = Gamma(2)
1398  // = (2 - 1)!
1399  // = 1
1400  //
1401  // which means
1402  //
1403  // E[value] = scale .
1404  //
1405  double expectedMean = scale;
1406 
1407  // Test that values have approximately the right mean value.
1408  double TOLERANCE = expectedMean * 1e-2;
1409  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1410 }
1411 
1412 // ===========================================================================
1413 // Test case for antithetic Weibull distribution random variable stream generator
1414 // ===========================================================================
1416 {
1417 public:
1418  static const uint32_t N_RUNS = 5;
1419  static const uint32_t N_BINS = 50;
1420  static const uint32_t N_MEASUREMENTS = 1000000;
1421 
1424 
1426 
1427 private:
1428  virtual void DoRun (void);
1429 };
1430 
1432  : TestCase ("Antithetic Weibull Random Variable Stream Generator")
1433 {
1434 }
1435 
1437 {
1438 }
1439 
1440 double
1442 {
1443  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1444 
1445  double range[N_BINS + 1];
1446  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
1448 
1449  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1450 
1451  double expected[N_BINS];
1452 
1453  // Note that this assumes that p has shape equal to one and scale
1454  // equal to one, which are their default values for this
1455  // distribution.
1456  double a = 1.0;
1457  double b = 1.0;
1458 
1459  for (uint32_t i = 0; i < N_BINS; ++i)
1460  {
1461  expected[i] = gsl_cdf_weibull_P (range[i + 1], a, b) - gsl_cdf_weibull_P (range[i], a, b);
1462  expected[i] *= N_MEASUREMENTS;
1463  }
1464 
1465  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1466  {
1467  gsl_histogram_increment (h, p->GetValue ());
1468  }
1469 
1470  double tmp[N_BINS];
1471 
1472  for (uint32_t i = 0; i < N_BINS; ++i)
1473  {
1474  tmp[i] = gsl_histogram_get (h, i);
1475  tmp[i] -= expected[i];
1476  tmp[i] *= tmp[i];
1477  tmp[i] /= expected[i];
1478  }
1479 
1480  gsl_histogram_free (h);
1481 
1482  double chiSquared = 0;
1483 
1484  for (uint32_t i = 0; i < N_BINS; ++i)
1485  {
1486  chiSquared += tmp[i];
1487  }
1488 
1489  return chiSquared;
1490 }
1491 
1492 void
1494 {
1495  SetTestSuiteSeed ();
1496 
1497  double sum = 0.;
1498  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1499 
1500  for (uint32_t i = 0; i < N_RUNS; ++i)
1501  {
1502  Ptr<WeibullRandomVariable> e = CreateObject<WeibullRandomVariable> ();
1503 
1504  // Make this generate antithetic values.
1505  e->SetAttribute ("Antithetic", BooleanValue (true));
1506 
1507  double result = ChiSquaredTest (e);
1508  sum += result;
1509  }
1510 
1511  sum /= (double)N_RUNS;
1512 
1513  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1514 
1515  double scale = 5.0;
1516  double shape = 1.0;
1517  double value;
1518 
1519  // Create the RNG with the specified range.
1520  Ptr<WeibullRandomVariable> x = CreateObject<WeibullRandomVariable> ();
1521  x->SetAttribute ("Scale", DoubleValue (scale));
1522  x->SetAttribute ("Shape", DoubleValue (shape));
1523 
1524  // Make this generate antithetic values.
1525  x->SetAttribute ("Antithetic", BooleanValue (true));
1526 
1527  // Calculate the mean of these values.
1528  sum = 0.0;
1529  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1530  {
1531  value = x->GetValue ();
1532  sum += value;
1533  }
1534  double valueMean = sum / N_MEASUREMENTS;
1535 
1536  // The expected value for the mean of the values returned by a
1537  // Weibull distributed random variable is
1538  //
1539  // E[value] = scale * Gamma(1 + 1 / shape) ,
1540  //
1541  // where Gamma() is the Gamma function. Note that
1542  //
1543  // Gamma(n) = (n - 1)!
1544  //
1545  // if n is a positive integer.
1546  //
1547  // For this test,
1548  //
1549  // Gamma(1 + 1 / shape) = Gamma(1 + 1 / 1)
1550  // = Gamma(2)
1551  // = (2 - 1)!
1552  // = 1
1553  //
1554  // which means
1555  //
1556  // E[value] = scale .
1557  //
1558  double expectedMean = scale;
1559 
1560  // Test that values have approximately the right mean value.
1561  double TOLERANCE = expectedMean * 1e-2;
1562  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1563 }
1564 
1565 // ===========================================================================
1566 // Test case for log-normal distribution random variable stream generator
1567 // ===========================================================================
1569 {
1570 public:
1571  static const uint32_t N_RUNS = 5;
1572  static const uint32_t N_BINS = 50;
1573  static const uint32_t N_MEASUREMENTS = 1000000;
1574 
1577 
1579 
1580 private:
1581  virtual void DoRun (void);
1582 };
1583 
1585  : TestCase ("Log-Normal Random Variable Stream Generator")
1586 {
1587 }
1588 
1590 {
1591 }
1592 
1593 double
1595 {
1596  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1597 
1598  double range[N_BINS + 1];
1599  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1601 
1602  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1603 
1604  double expected[N_BINS];
1605 
1606  // Note that this assumes that n has mu equal to zero and sigma
1607  // equal to one, which are their default values for this
1608  // distribution.
1609  double mu = 0.0;
1610  double sigma = 1.0;
1611 
1612  for (uint32_t i = 0; i < N_BINS; ++i)
1613  {
1614  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1615  expected[i] *= N_MEASUREMENTS;
1616  }
1617 
1618  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1619  {
1620  gsl_histogram_increment (h, n->GetValue ());
1621  }
1622 
1623  double tmp[N_BINS];
1624 
1625  for (uint32_t i = 0; i < N_BINS; ++i)
1626  {
1627  tmp[i] = gsl_histogram_get (h, i);
1628  tmp[i] -= expected[i];
1629  tmp[i] *= tmp[i];
1630  tmp[i] /= expected[i];
1631  }
1632 
1633  gsl_histogram_free (h);
1634 
1635  double chiSquared = 0;
1636 
1637  for (uint32_t i = 0; i < N_BINS; ++i)
1638  {
1639  chiSquared += tmp[i];
1640  }
1641 
1642  return chiSquared;
1643 }
1644 
1645 void
1647 {
1648  SetTestSuiteSeed ();
1649 
1650  double sum = 0.;
1651  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1652 
1653  for (uint32_t i = 0; i < N_RUNS; ++i)
1654  {
1655  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1656  double result = ChiSquaredTest (n);
1657  sum += result;
1658  }
1659 
1660  sum /= (double)N_RUNS;
1661 
1662  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1663 
1664  double mu = 5.0;
1665  double sigma = 2.0;
1666  double value;
1667 
1668  // Create the RNG with the specified range.
1669  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1670  x->SetAttribute ("Mu", DoubleValue (mu));
1671  x->SetAttribute ("Sigma", DoubleValue (sigma));
1672 
1673  // Calculate the mean of these values.
1674  sum = 0.0;
1675  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1676  {
1677  value = x->GetValue ();
1678  sum += value;
1679  }
1680  double valueMean = sum / N_MEASUREMENTS;
1681 
1682  // The expected value for the mean of the values returned by a
1683  // log-normally distributed random variable is equal to
1684  //
1685  // 2
1686  // mu + sigma / 2
1687  // E[value] = e .
1688  //
1689  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1690 
1691  // Test that values have approximately the right mean value.
1692  //
1697  double TOLERANCE = expectedMean * 3e-2;
1698  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1699 }
1700 
1701 // ===========================================================================
1702 // Test case for antithetic log-normal distribution random variable stream generator
1703 // ===========================================================================
1705 {
1706 public:
1707  static const uint32_t N_RUNS = 5;
1708  static const uint32_t N_BINS = 50;
1709  static const uint32_t N_MEASUREMENTS = 1000000;
1710 
1713 
1715 
1716 private:
1717  virtual void DoRun (void);
1718 };
1719 
1721  : TestCase ("Antithetic Log-Normal Random Variable Stream Generator")
1722 {
1723 }
1724 
1726 {
1727 }
1728 
1729 double
1731 {
1732  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1733 
1734  double range[N_BINS + 1];
1735  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1737 
1738  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1739 
1740  double expected[N_BINS];
1741 
1742  // Note that this assumes that n has mu equal to zero and sigma
1743  // equal to one, which are their default values for this
1744  // distribution.
1745  double mu = 0.0;
1746  double sigma = 1.0;
1747 
1748  for (uint32_t i = 0; i < N_BINS; ++i)
1749  {
1750  expected[i] = gsl_cdf_lognormal_P (range[i + 1], mu, sigma) - gsl_cdf_lognormal_P (range[i], mu, sigma);
1751  expected[i] *= N_MEASUREMENTS;
1752  }
1753 
1754  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1755  {
1756  gsl_histogram_increment (h, n->GetValue ());
1757  }
1758 
1759  double tmp[N_BINS];
1760 
1761  for (uint32_t i = 0; i < N_BINS; ++i)
1762  {
1763  tmp[i] = gsl_histogram_get (h, i);
1764  tmp[i] -= expected[i];
1765  tmp[i] *= tmp[i];
1766  tmp[i] /= expected[i];
1767  }
1768 
1769  gsl_histogram_free (h);
1770 
1771  double chiSquared = 0;
1772 
1773  for (uint32_t i = 0; i < N_BINS; ++i)
1774  {
1775  chiSquared += tmp[i];
1776  }
1777 
1778  return chiSquared;
1779 }
1780 
1781 void
1783 {
1784  SetTestSuiteSeed ();
1785 
1786  double sum = 0.;
1787  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1788 
1789  for (uint32_t i = 0; i < N_RUNS; ++i)
1790  {
1791  Ptr<LogNormalRandomVariable> n = CreateObject<LogNormalRandomVariable> ();
1792 
1793  // Make this generate antithetic values.
1794  n->SetAttribute ("Antithetic", BooleanValue (true));
1795 
1796  double result = ChiSquaredTest (n);
1797  sum += result;
1798  }
1799 
1800  sum /= (double)N_RUNS;
1801 
1802  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1803 
1804  double mu = 5.0;
1805  double sigma = 2.0;
1806  double value;
1807 
1808  // Create the RNG with the specified range.
1809  Ptr<LogNormalRandomVariable> x = CreateObject<LogNormalRandomVariable> ();
1810  x->SetAttribute ("Mu", DoubleValue (mu));
1811  x->SetAttribute ("Sigma", DoubleValue (sigma));
1812 
1813  // Make this generate antithetic values.
1814  x->SetAttribute ("Antithetic", BooleanValue (true));
1815 
1816  // Calculate the mean of these values.
1817  sum = 0.0;
1818  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1819  {
1820  value = x->GetValue ();
1821  sum += value;
1822  }
1823  double valueMean = sum / N_MEASUREMENTS;
1824 
1825  // The expected value for the mean of the values returned by a
1826  // log-normally distributed random variable is equal to
1827  //
1828  // 2
1829  // mu + sigma / 2
1830  // E[value] = e .
1831  //
1832  double expectedMean = std::exp(mu + sigma * sigma / 2.0);
1833 
1834  // Test that values have approximately the right mean value.
1835  //
1840  double TOLERANCE = expectedMean * 3e-2;
1841  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1842 }
1843 
1844 // ===========================================================================
1845 // Test case for gamma distribution random variable stream generator
1846 // ===========================================================================
1848 {
1849 public:
1850  static const uint32_t N_RUNS = 5;
1851  static const uint32_t N_BINS = 50;
1852  static const uint32_t N_MEASUREMENTS = 1000000;
1853 
1856 
1858 
1859 private:
1860  virtual void DoRun (void);
1861 };
1862 
1864  : TestCase ("Gamma Random Variable Stream Generator")
1865 {
1866 }
1867 
1869 {
1870 }
1871 
1872 double
1874 {
1875  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
1876 
1877  double range[N_BINS + 1];
1878  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
1880 
1881  gsl_histogram_set_ranges (h, range, N_BINS + 1);
1882 
1883  double expected[N_BINS];
1884 
1885  // Note that this assumes that n has alpha equal to one and beta
1886  // equal to one, which are their default values for this
1887  // distribution.
1888  double alpha = 1.0;
1889  double beta = 1.0;
1890 
1891  for (uint32_t i = 0; i < N_BINS; ++i)
1892  {
1893  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
1894  expected[i] *= N_MEASUREMENTS;
1895  }
1896 
1897  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1898  {
1899  gsl_histogram_increment (h, n->GetValue ());
1900  }
1901 
1902  double tmp[N_BINS];
1903 
1904  for (uint32_t i = 0; i < N_BINS; ++i)
1905  {
1906  tmp[i] = gsl_histogram_get (h, i);
1907  tmp[i] -= expected[i];
1908  tmp[i] *= tmp[i];
1909  tmp[i] /= expected[i];
1910  }
1911 
1912  gsl_histogram_free (h);
1913 
1914  double chiSquared = 0;
1915 
1916  for (uint32_t i = 0; i < N_BINS; ++i)
1917  {
1918  chiSquared += tmp[i];
1919  }
1920 
1921  return chiSquared;
1922 }
1923 
1924 void
1926 {
1927  SetTestSuiteSeed ();
1928 
1929  double sum = 0.;
1930  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
1931 
1932  for (uint32_t i = 0; i < N_RUNS; ++i)
1933  {
1934  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
1935  double result = ChiSquaredTest (n);
1936  sum += result;
1937  }
1938 
1939  sum /= (double)N_RUNS;
1940 
1941  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
1942 
1943  double alpha = 5.0;
1944  double beta = 2.0;
1945  double value;
1946 
1947  // Create the RNG with the specified range.
1948  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
1949  x->SetAttribute ("Alpha", DoubleValue (alpha));
1950  x->SetAttribute ("Beta", DoubleValue (beta));
1951 
1952  // Calculate the mean of these values.
1953  sum = 0.0;
1954  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
1955  {
1956  value = x->GetValue ();
1957  sum += value;
1958  }
1959  double valueMean = sum / N_MEASUREMENTS;
1960 
1961  // The expected value for the mean of the values returned by a
1962  // gammaly distributed random variable is equal to
1963  //
1964  // E[value] = alpha * beta .
1965  //
1966  double expectedMean = alpha * beta;
1967 
1968  // Test that values have approximately the right mean value.
1969  double TOLERANCE = expectedMean * 1e-2;
1970  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
1971 }
1972 
1973 // ===========================================================================
1974 // Test case for antithetic gamma distribution random variable stream generator
1975 // ===========================================================================
1977 {
1978 public:
1979  static const uint32_t N_RUNS = 5;
1980  static const uint32_t N_BINS = 50;
1981  static const uint32_t N_MEASUREMENTS = 1000000;
1982 
1985 
1987 
1988 private:
1989  virtual void DoRun (void);
1990 };
1991 
1993  : TestCase ("Antithetic Gamma Random Variable Stream Generator")
1994 {
1995 }
1996 
1998 {
1999 }
2000 
2001 double
2003 {
2004  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2005 
2006  double range[N_BINS + 1];
2007  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2009 
2010  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2011 
2012  double expected[N_BINS];
2013 
2014  // Note that this assumes that n has alpha equal to one and beta
2015  // equal to one, which are their default values for this
2016  // distribution.
2017  double alpha = 1.0;
2018  double beta = 1.0;
2019 
2020  for (uint32_t i = 0; i < N_BINS; ++i)
2021  {
2022  expected[i] = gsl_cdf_gamma_P (range[i + 1], alpha, beta) - gsl_cdf_gamma_P (range[i], alpha, beta);
2023  expected[i] *= N_MEASUREMENTS;
2024  }
2025 
2026  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2027  {
2028  gsl_histogram_increment (h, n->GetValue ());
2029  }
2030 
2031  double tmp[N_BINS];
2032 
2033  for (uint32_t i = 0; i < N_BINS; ++i)
2034  {
2035  tmp[i] = gsl_histogram_get (h, i);
2036  tmp[i] -= expected[i];
2037  tmp[i] *= tmp[i];
2038  tmp[i] /= expected[i];
2039  }
2040 
2041  gsl_histogram_free (h);
2042 
2043  double chiSquared = 0;
2044 
2045  for (uint32_t i = 0; i < N_BINS; ++i)
2046  {
2047  chiSquared += tmp[i];
2048  }
2049 
2050  return chiSquared;
2051 }
2052 
2053 void
2055 {
2056  SetTestSuiteSeed ();
2057 
2058  double sum = 0.;
2059  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2060 
2061  for (uint32_t i = 0; i < N_RUNS; ++i)
2062  {
2063  Ptr<GammaRandomVariable> n = CreateObject<GammaRandomVariable> ();
2064 
2065  // Make this generate antithetic values.
2066  n->SetAttribute ("Antithetic", BooleanValue (true));
2067 
2068  double result = ChiSquaredTest (n);
2069  sum += result;
2070  }
2071 
2072  sum /= (double)N_RUNS;
2073 
2074  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2075 
2076  double alpha = 5.0;
2077  double beta = 2.0;
2078  double value;
2079 
2080  // Create the RNG with the specified range.
2081  Ptr<GammaRandomVariable> x = CreateObject<GammaRandomVariable> ();
2082 
2083  // Make this generate antithetic values.
2084  x->SetAttribute ("Antithetic", BooleanValue (true));
2085 
2086  x->SetAttribute ("Alpha", DoubleValue (alpha));
2087  x->SetAttribute ("Beta", DoubleValue (beta));
2088 
2089  // Calculate the mean of these values.
2090  sum = 0.0;
2091  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2092  {
2093  value = x->GetValue ();
2094  sum += value;
2095  }
2096  double valueMean = sum / N_MEASUREMENTS;
2097 
2098  // The expected value for the mean of the values returned by a
2099  // gammaly distributed random variable is equal to
2100  //
2101  // E[value] = alpha * beta .
2102  //
2103  double expectedMean = alpha * beta;
2104 
2105  // Test that values have approximately the right mean value.
2106  double TOLERANCE = expectedMean * 1e-2;
2107  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2108 }
2109 
2110 // ===========================================================================
2111 // Test case for Erlang distribution random variable stream generator
2112 // ===========================================================================
2114 {
2115 public:
2116  static const uint32_t N_RUNS = 5;
2117  static const uint32_t N_BINS = 50;
2118  static const uint32_t N_MEASUREMENTS = 1000000;
2119 
2122 
2124 
2125 private:
2126  virtual void DoRun (void);
2127 };
2128 
2130  : TestCase ("Erlang Random Variable Stream Generator")
2131 {
2132 }
2133 
2135 {
2136 }
2137 
2138 double
2140 {
2141  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2142 
2143  double range[N_BINS + 1];
2144  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2146 
2147  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2148 
2149  double expected[N_BINS];
2150 
2151  // Note that this assumes that n has k equal to one and lambda
2152  // equal to one, which are their default values for this
2153  // distribution.
2154  uint32_t k = 1;
2155  double lambda = 1.0;
2156 
2157  // Note that Erlang distribution is equal to the gamma distribution
2158  // when k is an iteger, which is why the gamma distribution's cdf
2159  // function can be used here.
2160  for (uint32_t i = 0; i < N_BINS; ++i)
2161  {
2162  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2163  expected[i] *= N_MEASUREMENTS;
2164  }
2165 
2166  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2167  {
2168  gsl_histogram_increment (h, n->GetValue ());
2169  }
2170 
2171  double tmp[N_BINS];
2172 
2173  for (uint32_t i = 0; i < N_BINS; ++i)
2174  {
2175  tmp[i] = gsl_histogram_get (h, i);
2176  tmp[i] -= expected[i];
2177  tmp[i] *= tmp[i];
2178  tmp[i] /= expected[i];
2179  }
2180 
2181  gsl_histogram_free (h);
2182 
2183  double chiSquared = 0;
2184 
2185  for (uint32_t i = 0; i < N_BINS; ++i)
2186  {
2187  chiSquared += tmp[i];
2188  }
2189 
2190  return chiSquared;
2191 }
2192 
2193 void
2195 {
2196  SetTestSuiteSeed ();
2197 
2198  double sum = 0.;
2199  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2200 
2201  for (uint32_t i = 0; i < N_RUNS; ++i)
2202  {
2203  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2204  double result = ChiSquaredTest (n);
2205  sum += result;
2206  }
2207 
2208  sum /= (double)N_RUNS;
2209 
2210  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2211 
2212  uint32_t k = 5;
2213  double lambda = 2.0;
2214  double value;
2215 
2216  // Create the RNG with the specified range.
2217  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2218  x->SetAttribute ("K", IntegerValue (k));
2219  x->SetAttribute ("Lambda", DoubleValue (lambda));
2220 
2221  // Calculate the mean of these values.
2222  sum = 0.0;
2223  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2224  {
2225  value = x->GetValue ();
2226  sum += value;
2227  }
2228  double valueMean = sum / N_MEASUREMENTS;
2229 
2230  // The expected value for the mean of the values returned by a
2231  // Erlangly distributed random variable is equal to
2232  //
2233  // E[value] = k * lambda .
2234  //
2235  double expectedMean = k * lambda;
2236 
2237  // Test that values have approximately the right mean value.
2238  double TOLERANCE = expectedMean * 1e-2;
2239  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2240 }
2241 
2242 // ===========================================================================
2243 // Test case for antithetic Erlang distribution random variable stream generator
2244 // ===========================================================================
2246 {
2247 public:
2248  static const uint32_t N_RUNS = 5;
2249  static const uint32_t N_BINS = 50;
2250  static const uint32_t N_MEASUREMENTS = 1000000;
2251 
2254 
2256 
2257 private:
2258  virtual void DoRun (void);
2259 };
2260 
2262  : TestCase ("Antithetic Erlang Random Variable Stream Generator")
2263 {
2264 }
2265 
2267 {
2268 }
2269 
2270 double
2272 {
2273  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
2274 
2275  double range[N_BINS + 1];
2276  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
2278 
2279  gsl_histogram_set_ranges (h, range, N_BINS + 1);
2280 
2281  double expected[N_BINS];
2282 
2283  // Note that this assumes that n has k equal to one and lambda
2284  // equal to one, which are their default values for this
2285  // distribution.
2286  uint32_t k = 1;
2287  double lambda = 1.0;
2288 
2289  // Note that Erlang distribution is equal to the gamma distribution
2290  // when k is an iteger, which is why the gamma distribution's cdf
2291  // function can be used here.
2292  for (uint32_t i = 0; i < N_BINS; ++i)
2293  {
2294  expected[i] = gsl_cdf_gamma_P (range[i + 1], k, lambda) - gsl_cdf_gamma_P (range[i], k, lambda);
2295  expected[i] *= N_MEASUREMENTS;
2296  }
2297 
2298  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2299  {
2300  gsl_histogram_increment (h, n->GetValue ());
2301  }
2302 
2303  double tmp[N_BINS];
2304 
2305  for (uint32_t i = 0; i < N_BINS; ++i)
2306  {
2307  tmp[i] = gsl_histogram_get (h, i);
2308  tmp[i] -= expected[i];
2309  tmp[i] *= tmp[i];
2310  tmp[i] /= expected[i];
2311  }
2312 
2313  gsl_histogram_free (h);
2314 
2315  double chiSquared = 0;
2316 
2317  for (uint32_t i = 0; i < N_BINS; ++i)
2318  {
2319  chiSquared += tmp[i];
2320  }
2321 
2322  return chiSquared;
2323 }
2324 
2325 void
2327 {
2328  SetTestSuiteSeed ();
2329 
2330  double sum = 0.;
2331  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
2332 
2333  for (uint32_t i = 0; i < N_RUNS; ++i)
2334  {
2335  Ptr<ErlangRandomVariable> n = CreateObject<ErlangRandomVariable> ();
2336 
2337  // Make this generate antithetic values.
2338  n->SetAttribute ("Antithetic", BooleanValue (true));
2339 
2340  double result = ChiSquaredTest (n);
2341  sum += result;
2342  }
2343 
2344  sum /= (double)N_RUNS;
2345 
2346  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
2347 
2348  uint32_t k = 5;
2349  double lambda = 2.0;
2350  double value;
2351 
2352  // Create the RNG with the specified range.
2353  Ptr<ErlangRandomVariable> x = CreateObject<ErlangRandomVariable> ();
2354 
2355  // Make this generate antithetic values.
2356  x->SetAttribute ("Antithetic", BooleanValue (true));
2357 
2358  x->SetAttribute ("K", IntegerValue (k));
2359  x->SetAttribute ("Lambda", DoubleValue (lambda));
2360 
2361  // Calculate the mean of these values.
2362  sum = 0.0;
2363  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2364  {
2365  value = x->GetValue ();
2366  sum += value;
2367  }
2368  double valueMean = sum / N_MEASUREMENTS;
2369 
2370  // The expected value for the mean of the values returned by a
2371  // Erlangly distributed random variable is equal to
2372  //
2373  // E[value] = k * lambda .
2374  //
2375  double expectedMean = k * lambda;
2376 
2377  // Test that values have approximately the right mean value.
2378  double TOLERANCE = expectedMean * 1e-2;
2379  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2380 }
2381 
2382 // ===========================================================================
2383 // Test case for Zipf distribution random variable stream generator
2384 // ===========================================================================
2386 {
2387 public:
2388  static const uint32_t N_MEASUREMENTS = 1000000;
2389 
2392 
2393 private:
2394  virtual void DoRun (void);
2395 };
2396 
2398  : TestCase ("Zipf Random Variable Stream Generator")
2399 {
2400 }
2401 
2403 {
2404 }
2405 
2406 void
2408 {
2409  SetTestSuiteSeed ();
2410 
2411  uint32_t n = 1;
2412  double alpha = 2.0;
2413  double value;
2414 
2415  // Create the RNG with the specified range.
2416  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2417  x->SetAttribute ("N", IntegerValue (n));
2418  x->SetAttribute ("Alpha", DoubleValue (alpha));
2419 
2420  // Calculate the mean of these values.
2421  double sum = 0.0;
2422  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2423  {
2424  value = x->GetValue ();
2425  sum += value;
2426  }
2427  double valueMean = sum / N_MEASUREMENTS;
2428 
2429  // The expected value for the mean of the values returned by a
2430  // Zipfly distributed random variable is equal to
2431  //
2432  // H
2433  // N, alpha - 1
2434  // E[value] = ---------------
2435  // H
2436  // N, alpha
2437  //
2438  // where
2439  //
2440  // N
2441  // ---
2442  // \ -alpha
2443  // H = / m .
2444  // N, alpha ---
2445  // m=1
2446  //
2447  // For this test,
2448  //
2449  // -(alpha - 1)
2450  // 1
2451  // E[value] = ---------------
2452  // -alpha
2453  // 1
2454  //
2455  // = 1 .
2456  //
2457  double expectedMean = 1.0;
2458 
2459  // Test that values have approximately the right mean value.
2460  double TOLERANCE = expectedMean * 1e-2;
2461  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2462 }
2463 
2464 // ===========================================================================
2465 // Test case for antithetic Zipf distribution random variable stream generator
2466 // ===========================================================================
2468 {
2469 public:
2470  static const uint32_t N_MEASUREMENTS = 1000000;
2471 
2474 
2475 private:
2476  virtual void DoRun (void);
2477 };
2478 
2480  : TestCase ("Antithetic Zipf Random Variable Stream Generator")
2481 {
2482 }
2483 
2485 {
2486 }
2487 
2488 void
2490 {
2491  SetTestSuiteSeed ();
2492 
2493  uint32_t n = 1;
2494  double alpha = 2.0;
2495  double value;
2496 
2497  // Create the RNG with the specified range.
2498  Ptr<ZipfRandomVariable> x = CreateObject<ZipfRandomVariable> ();
2499  x->SetAttribute ("N", IntegerValue (n));
2500  x->SetAttribute ("Alpha", DoubleValue (alpha));
2501 
2502  // Make this generate antithetic values.
2503  x->SetAttribute ("Antithetic", BooleanValue (true));
2504 
2505  // Calculate the mean of these values.
2506  double sum = 0.0;
2507  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2508  {
2509  value = x->GetValue ();
2510  sum += value;
2511  }
2512  double valueMean = sum / N_MEASUREMENTS;
2513 
2514  // The expected value for the mean of the values returned by a
2515  // Zipfly distributed random variable is equal to
2516  //
2517  // H
2518  // N, alpha - 1
2519  // E[value] = ---------------
2520  // H
2521  // N, alpha
2522  //
2523  // where
2524  //
2525  // N
2526  // ---
2527  // \ -alpha
2528  // H = / m .
2529  // N, alpha ---
2530  // m=1
2531  //
2532  // For this test,
2533  //
2534  // -(alpha - 1)
2535  // 1
2536  // E[value] = ---------------
2537  // -alpha
2538  // 1
2539  //
2540  // = 1 .
2541  //
2542  double expectedMean = 1.0;
2543 
2544  // Test that values have approximately the right mean value.
2545  double TOLERANCE = expectedMean * 1e-2;
2546  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2547 }
2548 
2549 // ===========================================================================
2550 // Test case for Zeta distribution random variable stream generator
2551 // ===========================================================================
2553 {
2554 public:
2555  static const uint32_t N_MEASUREMENTS = 1000000;
2556 
2559 
2560 private:
2561  virtual void DoRun (void);
2562 };
2563 
2565  : TestCase ("Zeta Random Variable Stream Generator")
2566 {
2567 }
2568 
2570 {
2571 }
2572 
2573 void
2575 {
2576  SetTestSuiteSeed ();
2577 
2578  double alpha = 5.0;
2579  double value;
2580 
2581  // Create the RNG with the specified range.
2582  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2583  x->SetAttribute ("Alpha", DoubleValue (alpha));
2584 
2585  // Calculate the mean of these values.
2586  double sum = 0.0;
2587  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2588  {
2589  value = x->GetValue ();
2590  sum += value;
2591  }
2592  double valueMean = sum / N_MEASUREMENTS;
2593 
2594  // The expected value for the mean of the values returned by a
2595  // zetaly distributed random variable is equal to
2596  //
2597  // zeta(alpha - 1)
2598  // E[value] = --------------- for alpha > 2 ,
2599  // zeta(alpha)
2600  //
2601  // where zeta(alpha) is the Riemann zeta function.
2602  //
2603  // There are no simple analytic forms for the Riemann zeta function,
2604  // which is why the gsl library is used in this test to calculate
2605  // the known mean of the values.
2606  double expectedMean =
2607  gsl_sf_zeta_int (static_cast<int> (alpha - 1)) /
2608  gsl_sf_zeta_int (static_cast<int> (alpha) );
2609 
2610  // Test that values have approximately the right mean value.
2611  double TOLERANCE = expectedMean * 1e-2;
2612  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2613 }
2614 
2615 // ===========================================================================
2616 // Test case for antithetic Zeta distribution random variable stream generator
2617 // ===========================================================================
2619 {
2620 public:
2621  static const uint32_t N_MEASUREMENTS = 1000000;
2622 
2625 
2626 private:
2627  virtual void DoRun (void);
2628 };
2629 
2631  : TestCase ("Antithetic Zeta Random Variable Stream Generator")
2632 {
2633 }
2634 
2636 {
2637 }
2638 
2639 void
2641 {
2642  SetTestSuiteSeed ();
2643 
2644  double alpha = 5.0;
2645  double value;
2646 
2647  // Create the RNG with the specified range.
2648  Ptr<ZetaRandomVariable> x = CreateObject<ZetaRandomVariable> ();
2649  x->SetAttribute ("Alpha", DoubleValue (alpha));
2650 
2651  // Make this generate antithetic values.
2652  x->SetAttribute ("Antithetic", BooleanValue (true));
2653 
2654  // Calculate the mean of these values.
2655  double sum = 0.0;
2656  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2657  {
2658  value = x->GetValue ();
2659  sum += value;
2660  }
2661  double valueMean = sum / N_MEASUREMENTS;
2662 
2663  // The expected value for the mean of the values returned by a
2664  // zetaly distributed random variable is equal to
2665  //
2666  // zeta(alpha - 1)
2667  // E[value] = --------------- for alpha > 2 ,
2668  // zeta(alpha)
2669  //
2670  // where zeta(alpha) is the Riemann zeta function.
2671  //
2672  // There are no simple analytic forms for the Riemann zeta function,
2673  // which is why the gsl library is used in this test to calculate
2674  // the known mean of the values.
2675  double expectedMean =
2676  gsl_sf_zeta_int (static_cast<int> (alpha) - 1) /
2677  gsl_sf_zeta_int (static_cast<int> (alpha) );
2678 
2679  // Test that values have approximately the right mean value.
2680  double TOLERANCE = expectedMean * 1e-2;
2681  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2682 }
2683 
2684 // ===========================================================================
2685 // Test case for deterministic random variable stream generator
2686 // ===========================================================================
2688 {
2689 public:
2690  static const double TOLERANCE;
2691 
2694 
2695 private:
2696  virtual void DoRun (void);
2697 };
2698 
2700 
2702  : TestCase ("Deterministic Random Variable Stream Generator")
2703 {
2704 }
2705 
2707 {
2708 }
2709 
2710 void
2712 {
2713  SetTestSuiteSeed ();
2714 
2715  Ptr<DeterministicRandomVariable> s = CreateObject<DeterministicRandomVariable> ();
2716 
2717  // The following array should give the sequence
2718  //
2719  // 4, 4, 7, 7, 10, 10 .
2720  //
2721  double array1 [] = { 4, 4, 7, 7, 10, 10};
2722  std::size_t count1 = 6;
2723  s->SetValueArray (array1, count1);
2724 
2725  double value;
2726 
2727  // Test that the first sequence is correct.
2728  value = s->GetValue ();
2729  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 1 wrong.");
2730  value = s->GetValue ();
2731  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4, TOLERANCE, "Sequence 1 value 2 wrong.");
2732  value = s->GetValue ();
2733  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 3 wrong.");
2734  value = s->GetValue ();
2735  NS_TEST_ASSERT_MSG_EQ_TOL (value, 7, TOLERANCE, "Sequence 1 value 4 wrong.");
2736  value = s->GetValue ();
2737  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 5 wrong.");
2738  value = s->GetValue ();
2739  NS_TEST_ASSERT_MSG_EQ_TOL (value, 10, TOLERANCE, "Sequence 1 value 6 wrong.");
2740 
2741  // The following array should give the sequence
2742  //
2743  // 1000, 2000, 7, 7 .
2744  //
2745  double array2 [] = { 1000, 2000, 3000, 4000};
2746  std::size_t count2 = 4;
2747  s->SetValueArray (array2, count2);
2748 
2749  // Test that the second sequence is correct.
2750  value = s->GetValue ();
2751  NS_TEST_ASSERT_MSG_EQ_TOL (value, 1000, TOLERANCE, "Sequence 2 value 1 wrong.");
2752  value = s->GetValue ();
2753  NS_TEST_ASSERT_MSG_EQ_TOL (value, 2000, TOLERANCE, "Sequence 2 value 2 wrong.");
2754  value = s->GetValue ();
2755  NS_TEST_ASSERT_MSG_EQ_TOL (value, 3000, TOLERANCE, "Sequence 2 value 3 wrong.");
2756  value = s->GetValue ();
2757  NS_TEST_ASSERT_MSG_EQ_TOL (value, 4000, TOLERANCE, "Sequence 2 value 4 wrong.");
2758  value = s->GetValue ();
2759 }
2760 
2761 // ===========================================================================
2762 // Test case for empirical distribution random variable stream generator
2763 // ===========================================================================
2765 {
2766 public:
2767  static const uint32_t N_MEASUREMENTS = 1000000;
2768 
2771 
2772 private:
2773  virtual void DoRun (void);
2774 };
2775 
2777  : TestCase ("Empirical Random Variable Stream Generator")
2778 {
2779 }
2780 
2782 {
2783 }
2784 
2785 void
2787 {
2788  SetTestSuiteSeed ();
2789 
2790  // Create the RNG with a uniform distribution between 0 and 10.
2791  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2792  x->CDF ( 0.0, 0.0);
2793  x->CDF ( 5.0, 0.5);
2794  x->CDF (10.0, 1.0);
2795 
2796  // Calculate the mean of these values.
2797  double sum = 0.0;
2798  double value;
2799  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2800  {
2801  value = x->GetValue ();
2802  sum += value;
2803  }
2804  double valueMean = sum / N_MEASUREMENTS;
2805 
2806  // The expected value for the mean of the values returned by this
2807  // empirical distribution is the midpoint of the distribution
2808  //
2809  // E[value] = 5 .
2810  //
2811  double expectedMean = 5.0;
2812 
2813  // Test that values have approximately the right mean value.
2814  double TOLERANCE = expectedMean * 1e-2;
2815  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2816 
2817  // Bug 2082: Create the RNG with a uniform distribution between -1 and 1.
2818  Ptr<EmpiricalRandomVariable> y = CreateObject<EmpiricalRandomVariable> ();
2819  y->CDF (-1.0, 0.0);
2820  y->CDF (0.0, 0.5);
2821  y->CDF (1.0, 1.0);
2822  NS_TEST_ASSERT_MSG_LT (y->GetValue (), 2, "Empirical variable with negative domain");
2823 }
2824 
2825 // ===========================================================================
2826 // Test case for antithetic empirical distribution random variable stream generator
2827 // ===========================================================================
2829 {
2830 public:
2831  static const uint32_t N_MEASUREMENTS = 1000000;
2832 
2835 
2836 private:
2837  virtual void DoRun (void);
2838 };
2839 
2841  : TestCase ("EmpiricalAntithetic Random Variable Stream Generator")
2842 {
2843 }
2844 
2846 {
2847 }
2848 
2849 void
2851 {
2852  SetTestSuiteSeed ();
2853 
2854  // Create the RNG with a uniform distribution between 0 and 10.
2855  Ptr<EmpiricalRandomVariable> x = CreateObject<EmpiricalRandomVariable> ();
2856  x->CDF ( 0.0, 0.0);
2857  x->CDF ( 5.0, 0.5);
2858  x->CDF (10.0, 1.0);
2859 
2860  // Make this generate antithetic values.
2861  x->SetAttribute ("Antithetic", BooleanValue (true));
2862 
2863  // Calculate the mean of these values.
2864  double sum = 0.0;
2865  double value;
2866  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
2867  {
2868  value = x->GetValue ();
2869  sum += value;
2870  }
2871  double valueMean = sum / N_MEASUREMENTS;
2872 
2873  // The expected value for the mean of the values returned by this
2874  // empirical distribution is the midpoint of the distribution
2875  //
2876  // E[value] = 5 .
2877  //
2878  double expectedMean = 5.0;
2879 
2880  // Test that values have approximately the right mean value.
2881  double TOLERANCE = expectedMean * 1e-2;
2882  NS_TEST_ASSERT_MSG_EQ_TOL (valueMean, expectedMean, TOLERANCE, "Wrong mean value.");
2883 }
2884 
2886 {
2887 public:
2889 };
2890 
2892  : TestSuite ("random-variable-stream-generators", UNIT)
2893 {
2894  AddTestCase (new RandomVariableStreamUniformTestCase, TestCase::QUICK);
2896  AddTestCase (new RandomVariableStreamConstantTestCase, TestCase::QUICK);
2897  AddTestCase (new RandomVariableStreamSequentialTestCase, TestCase::QUICK);
2898  AddTestCase (new RandomVariableStreamNormalTestCase, TestCase::QUICK);
2902  AddTestCase (new RandomVariableStreamParetoTestCase, TestCase::QUICK);
2904  AddTestCase (new RandomVariableStreamWeibullTestCase, TestCase::QUICK);
2906  AddTestCase (new RandomVariableStreamLogNormalTestCase, TestCase::QUICK);
2910  /*
2911  AddTestCase (new RandomVariableStreamLogNormalAntitheticTestCase, TestCase::QUICK);
2912  */
2913  AddTestCase (new RandomVariableStreamGammaTestCase, TestCase::QUICK);
2917  /*
2918  AddTestCase (new RandomVariableStreamGammaAntitheticTestCase, TestCase::QUICK);
2919  */
2920  AddTestCase (new RandomVariableStreamErlangTestCase, TestCase::QUICK);
2922  AddTestCase (new RandomVariableStreamZipfTestCase, TestCase::QUICK);
2924  AddTestCase (new RandomVariableStreamZetaTestCase, TestCase::QUICK);
2927  AddTestCase (new RandomVariableStreamEmpiricalTestCase, TestCase::QUICK);
2929 }
2930 
virtual double GetValue(void)
Returns the next value in the empirical distribution.
double GetValue(double constant)
Get the next random value, as a double equal to the argument.
double ChiSquaredTest(Ptr< LogNormalRandomVariable > n)
void FillHistoRangeUniformly(double *array, uint32_t n, double start, double end)
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Hold variables of type string.
Definition: string.h:41
#define min(a, b)
Definition: 80211b.c:42
static RandomVariableStreamTestSuite randomVariableStreamTestSuite
#define TOLERANCE
A suite of tests to run.
Definition: test.h:1342
def start()
Definition: core.py:1858
Hold a signed integer type.
Definition: integer.h:44
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:204
virtual void DoRun(void)
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< NormalRandomVariable > n)
encapsulates test code
Definition: test.h:1155
double ChiSquaredTest(Ptr< ExponentialRandomVariable > e)
double ChiSquaredTest(Ptr< WeibullRandomVariable > p)
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static uint64_t GetRun(void)
Get the current run number.
void SetValueArray(double *values, std::size_t length)
Sets the array of values that holds the predetermined sequence.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual double GetValue(void)
Get the next random value as a double drawn from the distribution.
#define max(a, b)
Definition: 80211b.c:43
virtual double GetValue(void)
Returns the next value in the sequence.
double ChiSquaredTest(Ptr< ErlangRandomVariable > n)
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:168
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:380
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static uint32_t GetSeed(void)
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static void SetSeed(uint32_t seed)
Set the seed.
double ChiSquaredTest(Ptr< UniformRandomVariable > u)
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not...
Definition: test.h:624
double ChiSquaredTest(Ptr< ParetoRandomVariable > p)
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:272
double GetValue(double mean, double bound)
Get the next random value, as a double from the exponential distribution with the specified mean and ...
virtual void DoRun(void)
Implementation to actually run this TestCase.
double GetValue(double scale, double shape, double bound)
Returns a random double from a Pareto distribution with the specified scale, shape, and upper bound.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition: test.h:997
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
Definition: test.h:811
double GetValue(double scale, double shape, double bound)
Returns a random double from a Weibull distribution with the specified scale, shape, and upper bound.