A Discrete-Event Network Simulator
API
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/double.h"
26 #include "ns3/random-variable-stream.h"
27 #include "ns3/rng-seed-manager.h"
28 
29 using namespace ns3;
30 
31 void
32 FillHistoRangeUniformly (double *array, uint32_t n, double start, double end)
33 {
34  double increment = (end - start) / (n - 1.);
35  double d = start;
36 
37  for (uint32_t i = 0; i < n; ++i)
38  {
39  array[i] = d;
40  d += increment;
41  }
42 }
43 
44 // ===========================================================================
45 // Test case for uniform distribution random number generator
46 // ===========================================================================
48 {
49 public:
50  static const uint32_t N_RUNS = 5;
51  static const uint32_t N_BINS = 50;
52  static const uint32_t N_MEASUREMENTS = 1000000;
53 
55  virtual ~RngUniformTestCase ();
56 
57  double ChiSquaredTest (Ptr<UniformRandomVariable> u);
58 
59 private:
60  virtual void DoRun (void);
61 };
62 
64  : TestCase ("Uniform Random Number Generator")
65 {}
66 
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  RngSeedManager::SetSeed (static_cast<uint32_t> (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  Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
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 
139 
140 private:
141  virtual void DoRun (void);
142 };
143 
145  : TestCase ("Normal Random Number Generator")
146 {}
147 
149 {}
150 
151 double
153 {
154  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
155 
156  double range[N_BINS + 1];
157  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
158  range[0] = -std::numeric_limits<double>::max ();
160 
161  gsl_histogram_set_ranges (h, range, N_BINS + 1);
162 
163  double expected[N_BINS];
164 
165  double sigma = 1.;
166 
167  for (uint32_t i = 0; i < N_BINS; ++i)
168  {
169  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
170  expected[i] *= N_MEASUREMENTS;
171  }
172 
173  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
174  {
175  gsl_histogram_increment (h, n->GetValue ());
176  }
177 
178  double tmp[N_BINS];
179 
180  for (uint32_t i = 0; i < N_BINS; ++i)
181  {
182  tmp[i] = gsl_histogram_get (h, i);
183  tmp[i] -= expected[i];
184  tmp[i] *= tmp[i];
185  tmp[i] /= expected[i];
186  }
187 
188  gsl_histogram_free (h);
189 
190  double chiSquared = 0;
191 
192  for (uint32_t i = 0; i < N_BINS; ++i)
193  {
194  chiSquared += tmp[i];
195  }
196 
197  return chiSquared;
198 }
199 
200 void
202 {
203  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
204 
205  double sum = 0.;
206  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
207 
208  for (uint32_t i = 0; i < N_RUNS; ++i)
209  {
210  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
211  double result = ChiSquaredTest (n);
212  sum += result;
213  }
214 
215  sum /= (double)N_RUNS;
216 
217  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
218 }
219 
220 // ===========================================================================
221 // Test case for exponential distribution random number generator
222 // ===========================================================================
224 {
225 public:
226  static const uint32_t N_RUNS = 5;
227  static const uint32_t N_BINS = 50;
228  static const uint32_t N_MEASUREMENTS = 1000000;
229 
231  virtual ~RngExponentialTestCase ();
232 
234 
235 private:
236  virtual void DoRun (void);
237 };
238 
240  : TestCase ("Exponential Random Number Generator")
241 {}
242 
244 {}
245 
246 double
248 {
249  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
250 
251  double range[N_BINS + 1];
252  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
254 
255  gsl_histogram_set_ranges (h, range, N_BINS + 1);
256 
257  double expected[N_BINS];
258 
259  double mu = 1.;
260 
261  for (uint32_t i = 0; i < N_BINS; ++i)
262  {
263  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
264  expected[i] *= N_MEASUREMENTS;
265  }
266 
267  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
268  {
269  gsl_histogram_increment (h, e->GetValue ());
270  }
271 
272  double tmp[N_BINS];
273 
274  for (uint32_t i = 0; i < N_BINS; ++i)
275  {
276  tmp[i] = gsl_histogram_get (h, i);
277  tmp[i] -= expected[i];
278  tmp[i] *= tmp[i];
279  tmp[i] /= expected[i];
280  }
281 
282  gsl_histogram_free (h);
283 
284  double chiSquared = 0;
285 
286  for (uint32_t i = 0; i < N_BINS; ++i)
287  {
288  chiSquared += tmp[i];
289  }
290 
291  return chiSquared;
292 }
293 
294 void
296 {
297  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
298 
299  double sum = 0.;
300  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
301 
302  for (uint32_t i = 0; i < N_RUNS; ++i)
303  {
304  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
305  double result = ChiSquaredTest (e);
306  sum += result;
307  }
308 
309  sum /= (double)N_RUNS;
310 
311  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
312 }
313 
314 // ===========================================================================
315 // Test case for pareto distribution random number generator
316 // ===========================================================================
318 {
319 public:
320  static const uint32_t N_RUNS = 5;
321  static const uint32_t N_BINS = 50;
322  static const uint32_t N_MEASUREMENTS = 1000000;
323 
325  virtual ~RngParetoTestCase ();
326 
328 
329 private:
330  virtual void DoRun (void);
331 };
332 
334  : TestCase ("Pareto Random Number Generator")
335 {}
336 
338 {}
339 
340 double
342 {
343  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
344 
345  double range[N_BINS + 1];
346  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
348 
349  gsl_histogram_set_ranges (h, range, N_BINS + 1);
350 
351  double expected[N_BINS];
352 
353  double a = 1.5;
354  double b = 0.33333333;
355 
356  // mean is 1 with these values
357 
358  for (uint32_t i = 0; i < N_BINS; ++i)
359  {
360  expected[i] = gsl_cdf_pareto_P (range[i + 1], a, b) - gsl_cdf_pareto_P (range[i], a, b);
361  expected[i] *= N_MEASUREMENTS;
362  }
363 
364  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
365  {
366  gsl_histogram_increment (h, p->GetValue ());
367  }
368 
369  double tmp[N_BINS];
370 
371  for (uint32_t i = 0; i < N_BINS; ++i)
372  {
373  tmp[i] = gsl_histogram_get (h, i);
374  tmp[i] -= expected[i];
375  tmp[i] *= tmp[i];
376  tmp[i] /= expected[i];
377  }
378 
379  gsl_histogram_free (h);
380 
381  double chiSquared = 0;
382 
383  for (uint32_t i = 0; i < N_BINS; ++i)
384  {
385  chiSquared += tmp[i];
386  }
387 
388  return chiSquared;
389 }
390 
391 void
393 {
394  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
395 
396  double sum = 0.;
397  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
398 
399  for (uint32_t i = 0; i < N_RUNS; ++i)
400  {
401  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
402  e->SetAttribute ("Shape", DoubleValue (1.5));
403  e->SetAttribute ("Scale", DoubleValue (0.33333333));
404  double result = ChiSquaredTest (e);
405  sum += result;
406  }
407 
408  sum /= (double)N_RUNS;
409 
410  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
411 }
412 
413 class RngTestSuite : public TestSuite
414 {
415 public:
416  RngTestSuite ();
417 };
418 
420  : TestSuite ("random-number-generators", UNIT)
421 {
422  AddTestCase (new RngUniformTestCase, TestCase::QUICK);
423  AddTestCase (new RngNormalTestCase, TestCase::QUICK);
424  AddTestCase (new RngExponentialTestCase, TestCase::QUICK);
425  AddTestCase (new RngParetoTestCase, TestCase::QUICK);
426 }
427 
virtual void DoRun(void)
Implementation to actually run this TestCase.
double ChiSquaredTest(Ptr< NormalRandomVariable > n)
double ChiSquaredTest(Ptr< UniformRandomVariable > u)
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:1343
def start()
Definition: core.py:1855
double ChiSquaredTest(Ptr< ParetoRandomVariable > p)
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_MEASUREMENTS
static RngTestSuite rngTestSuite
encapsulates test code
Definition: test.h:1153
virtual ~RngParetoTestCase()
static const uint32_t N_RUNS
#define max(a, b)
Definition: 80211b.c:43
static const uint32_t N_RUNS
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.
static const uint32_t N_MEASUREMENTS
static const uint32_t N_BINS
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double ChiSquaredTest(Ptr< ExponentialRandomVariable > n)
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.
static const uint32_t N_MEASUREMENTS
static const uint32_t N_BINS
static const uint32_t N_BINS
double GetValue(double mean, double bound)
Get the next random value, as a double from the exponential distribution with the specified mean and ...
double GetValue(double scale, double shape, double bound)
Returns a random double from a Pareto distribution with the specified scale, shape, and upper bound.
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
virtual ~RngNormalTestCase()
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
#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:809
static const uint32_t N_RUNS
virtual ~RngUniformTestCase()
static const uint32_t N_BINS