A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
rng-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  */
16 
17 
18 #include <cmath>
19 #include <gsl/gsl_cdf.h>
20 #include <gsl/gsl_histogram.h>
21 #include <ctime>
22 #include <fstream>
23 
24 #include "ns3/test.h"
25 #include "ns3/random-variable.h"
26 
27 using namespace ns3;
28 
29 void
30 FillHistoRangeUniformly (double *array, uint32_t n, double start, double end)
31 {
32  double increment = (end - start) / (n - 1.);
33  double d = start;
34 
35  for (uint32_t i = 0; i < n; ++i)
36  {
37  array[i] = d;
38  d += increment;
39  }
40 }
41 
42 // ===========================================================================
43 // Test case for uniform distribution random number generator
44 // ===========================================================================
46 {
47 public:
48  static const uint32_t N_RUNS = 5;
49  static const uint32_t N_BINS = 50;
50  static const uint32_t N_MEASUREMENTS = 1000000;
51 
53  virtual ~RngUniformTestCase ();
54 
55  double ChiSquaredTest (UniformVariable &u);
56 
57 private:
58  virtual void DoRun (void);
59 };
60 
62  : TestCase ("Uniform Random Number Generator")
63 {
64 }
65 
67 {
68 }
69 
70 double
72 {
73  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
74  gsl_histogram_set_ranges_uniform (h, 0., 1.);
75 
76  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
77  {
78  gsl_histogram_increment (h, u.GetValue ());
79  }
80 
81  double tmp[N_BINS];
82 
83  double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
84 
85  for (uint32_t i = 0; i < N_BINS; ++i)
86  {
87  tmp[i] = gsl_histogram_get (h, i);
88  tmp[i] -= expected;
89  tmp[i] *= tmp[i];
90  tmp[i] /= expected;
91  }
92 
93  gsl_histogram_free (h);
94 
95  double chiSquared = 0;
96 
97  for (uint32_t i = 0; i < N_BINS; ++i)
98  {
99  chiSquared += tmp[i];
100  }
101 
102  return chiSquared;
103 }
104 
105 void
107 {
108  SeedManager::SetSeed (time (0));
109 
110  double sum = 0.;
111  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
112 
113  for (uint32_t i = 0; i < N_RUNS; ++i)
114  {
115  UniformVariable u;
116  double result = ChiSquaredTest (u);
117  sum += result;
118  }
119 
120  sum /= (double)N_RUNS;
121 
122  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
123 }
124 
125 // ===========================================================================
126 // Test case for normal distribution random number generator
127 // ===========================================================================
129 {
130 public:
131  static const uint32_t N_RUNS = 5;
132  static const uint32_t N_BINS = 50;
133  static const uint32_t N_MEASUREMENTS = 1000000;
134 
136  virtual ~RngNormalTestCase ();
137 
138  double ChiSquaredTest (NormalVariable &n);
139 
140 private:
141  virtual void DoRun (void);
142 };
143 
145  : TestCase ("Normal Random Number Generator")
146 {
147 }
148 
150 {
151 }
152 
153 double
155 {
156  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
157 
158  double range[N_BINS + 1];
159  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
160  range[0] = -std::numeric_limits<double>::max ();
161  range[N_BINS] = std::numeric_limits<double>::max ();
162 
163  gsl_histogram_set_ranges (h, range, N_BINS + 1);
164 
165  double expected[N_BINS];
166 
167  double sigma = 1.;
168 
169  for (uint32_t i = 0; i < N_BINS; ++i)
170  {
171  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
172  expected[i] *= N_MEASUREMENTS;
173  }
174 
175  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
176  {
177  gsl_histogram_increment (h, n.GetValue ());
178  }
179 
180  double tmp[N_BINS];
181 
182  for (uint32_t i = 0; i < N_BINS; ++i)
183  {
184  tmp[i] = gsl_histogram_get (h, i);
185  tmp[i] -= expected[i];
186  tmp[i] *= tmp[i];
187  tmp[i] /= expected[i];
188  }
189 
190  gsl_histogram_free (h);
191 
192  double chiSquared = 0;
193 
194  for (uint32_t i = 0; i < N_BINS; ++i)
195  {
196  chiSquared += tmp[i];
197  }
198 
199  return chiSquared;
200 }
201 
202 void
204 {
205  SeedManager::SetSeed (time (0));
206 
207  double sum = 0.;
208  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
209 
210  for (uint32_t i = 0; i < N_RUNS; ++i)
211  {
212  NormalVariable n;
213  double result = ChiSquaredTest (n);
214  sum += result;
215  }
216 
217  sum /= (double)N_RUNS;
218 
219  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
220 }
221 
222 // ===========================================================================
223 // Test case for exponential distribution random number generator
224 // ===========================================================================
226 {
227 public:
228  static const uint32_t N_RUNS = 5;
229  static const uint32_t N_BINS = 50;
230  static const uint32_t N_MEASUREMENTS = 1000000;
231 
233  virtual ~RngExponentialTestCase ();
234 
236 
237 private:
238  virtual void DoRun (void);
239 };
240 
242  : TestCase ("Exponential Random Number Generator")
243 {
244 }
245 
247 {
248 }
249 
250 double
252 {
253  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
254 
255  double range[N_BINS + 1];
256  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
257  range[N_BINS] = std::numeric_limits<double>::max ();
258 
259  gsl_histogram_set_ranges (h, range, N_BINS + 1);
260 
261  double expected[N_BINS];
262 
263  double mu = 1.;
264 
265  for (uint32_t i = 0; i < N_BINS; ++i)
266  {
267  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
268  expected[i] *= N_MEASUREMENTS;
269  }
270 
271  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
272  {
273  gsl_histogram_increment (h, e.GetValue ());
274  }
275 
276  double tmp[N_BINS];
277 
278  for (uint32_t i = 0; i < N_BINS; ++i)
279  {
280  tmp[i] = gsl_histogram_get (h, i);
281  tmp[i] -= expected[i];
282  tmp[i] *= tmp[i];
283  tmp[i] /= expected[i];
284  }
285 
286  gsl_histogram_free (h);
287 
288  double chiSquared = 0;
289 
290  for (uint32_t i = 0; i < N_BINS; ++i)
291  {
292  chiSquared += tmp[i];
293  }
294 
295  return chiSquared;
296 }
297 
298 void
300 {
301  SeedManager::SetSeed (time (0));
302 
303  double sum = 0.;
304  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
305 
306  for (uint32_t i = 0; i < N_RUNS; ++i)
307  {
309  double result = ChiSquaredTest (e);
310  sum += result;
311  }
312 
313  sum /= (double)N_RUNS;
314 
315  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
316 }
317 
318 // ===========================================================================
319 // Test case for pareto distribution random number generator
320 // ===========================================================================
322 {
323 public:
324  static const uint32_t N_RUNS = 5;
325  static const uint32_t N_BINS = 50;
326  static const uint32_t N_MEASUREMENTS = 1000000;
327 
329  virtual ~RngParetoTestCase ();
330 
331  double ChiSquaredTest (ParetoVariable &p);
332 
333 private:
334  virtual void DoRun (void);
335 };
336 
338  : TestCase ("Pareto Random Number Generator")
339 {
340 }
341 
343 {
344 }
345 
346 double
348 {
349  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
350 
351  double range[N_BINS + 1];
352  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
353  range[N_BINS] = std::numeric_limits<double>::max ();
354 
355  gsl_histogram_set_ranges (h, range, N_BINS + 1);
356 
357  double expected[N_BINS];
358 
359  double a = 1.5;
360  double b = 0.33333333;
361 
362  for (uint32_t i = 0; i < N_BINS; ++i)
363  {
364  expected[i] = gsl_cdf_pareto_P (range[i + 1], a, b) - gsl_cdf_pareto_P (range[i], a, b);
365  expected[i] *= N_MEASUREMENTS;
366  }
367 
368  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
369  {
370  gsl_histogram_increment (h, p.GetValue ());
371  }
372 
373  double tmp[N_BINS];
374 
375  for (uint32_t i = 0; i < N_BINS; ++i)
376  {
377  tmp[i] = gsl_histogram_get (h, i);
378  tmp[i] -= expected[i];
379  tmp[i] *= tmp[i];
380  tmp[i] /= expected[i];
381  }
382 
383  gsl_histogram_free (h);
384 
385  double chiSquared = 0;
386 
387  for (uint32_t i = 0; i < N_BINS; ++i)
388  {
389  chiSquared += tmp[i];
390  }
391 
392  return chiSquared;
393 }
394 
395 void
397 {
398  SeedManager::SetSeed (time (0));
399 
400  double sum = 0.;
401  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
402 
403  for (uint32_t i = 0; i < N_RUNS; ++i)
404  {
405  ParetoVariable e;
406  double result = ChiSquaredTest (e);
407  sum += result;
408  }
409 
410  sum /= (double)N_RUNS;
411 
412  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
413 }
414 
415 class RngTestSuite : public TestSuite
416 {
417 public:
418  RngTestSuite ();
419 };
420 
422  : TestSuite ("random-number-generators", UNIT)
423 {
424  AddTestCase (new RngUniformTestCase, TestCase::QUICK);
425  AddTestCase (new RngNormalTestCase, TestCase::QUICK);
426  AddTestCase (new RngExponentialTestCase, TestCase::QUICK);
427  AddTestCase (new RngParetoTestCase, TestCase::QUICK);
428 }
429 
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_RUNS
void FillHistoRangeUniformly(double *array, uint32_t n, double start, double end)
static const uint32_t N_MEASUREMENTS
A suite of tests to run.
Definition: test.h:1105
virtual void DoRun(void)
Implementation to actually run this TestCase.
ParetoVariable distributed random varThis class supports the creation of objects that return random n...
static const uint32_t N_MEASUREMENTS
static RngTestSuite rngTestSuite
encapsulates test code
Definition: test.h:929
virtual ~RngParetoTestCase()
Class NormalVariable defines a random variable with a normal (Gaussian) distribution.
double ChiSquaredTest(ExponentialVariable &n)
static const uint32_t N_RUNS
static const uint32_t N_RUNS
double GetValue(void) const
call RandomVariable::GetValue
The uniform distribution RNG for NS-3.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_MEASUREMENTS
static const uint32_t N_BINS
Exponentially Distributed random varThis class supports the creation of objects that return random nu...
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:184
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_MEASUREMENTS
static const uint32_t N_BINS
double ChiSquaredTest(NormalVariable &n)
static const uint32_t N_BINS
double ChiSquaredTest(UniformVariable &u)
virtual ~RngNormalTestCase()
double GetValue(void) const
Returns a random double from the underlying distribution.
double ChiSquaredTest(ParetoVariable &p)
#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:753
static const uint32_t N_RUNS
virtual ~RngUniformTestCase()
static const uint32_t N_BINS