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 }
67 
69 {
70 }
71 
72 double
74 {
75  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
76  gsl_histogram_set_ranges_uniform (h, 0., 1.);
77 
78  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
79  {
80  gsl_histogram_increment (h, u->GetValue ());
81  }
82 
83  double tmp[N_BINS];
84 
85  double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
86 
87  for (uint32_t i = 0; i < N_BINS; ++i)
88  {
89  tmp[i] = gsl_histogram_get (h, i);
90  tmp[i] -= expected;
91  tmp[i] *= tmp[i];
92  tmp[i] /= expected;
93  }
94 
95  gsl_histogram_free (h);
96 
97  double chiSquared = 0;
98 
99  for (uint32_t i = 0; i < N_BINS; ++i)
100  {
101  chiSquared += tmp[i];
102  }
103 
104  return chiSquared;
105 }
106 
107 void
109 {
110  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
111 
112  double sum = 0.;
113  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
114 
115  for (uint32_t i = 0; i < N_RUNS; ++i)
116  {
117  Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
118  double result = ChiSquaredTest (u);
119  sum += result;
120  }
121 
122  sum /= (double)N_RUNS;
123 
124  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
125 }
126 
127 // ===========================================================================
128 // Test case for normal distribution random number generator
129 // ===========================================================================
131 {
132 public:
133  static const uint32_t N_RUNS = 5;
134  static const uint32_t N_BINS = 50;
135  static const uint32_t N_MEASUREMENTS = 1000000;
136 
138  virtual ~RngNormalTestCase ();
139 
141 
142 private:
143  virtual void DoRun (void);
144 };
145 
147  : TestCase ("Normal Random Number Generator")
148 {
149 }
150 
152 {
153 }
154 
155 double
157 {
158  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
159 
160  double range[N_BINS + 1];
161  FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
162  range[0] = -std::numeric_limits<double>::max ();
164 
165  gsl_histogram_set_ranges (h, range, N_BINS + 1);
166 
167  double expected[N_BINS];
168 
169  double sigma = 1.;
170 
171  for (uint32_t i = 0; i < N_BINS; ++i)
172  {
173  expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
174  expected[i] *= N_MEASUREMENTS;
175  }
176 
177  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
178  {
179  gsl_histogram_increment (h, n->GetValue ());
180  }
181 
182  double tmp[N_BINS];
183 
184  for (uint32_t i = 0; i < N_BINS; ++i)
185  {
186  tmp[i] = gsl_histogram_get (h, i);
187  tmp[i] -= expected[i];
188  tmp[i] *= tmp[i];
189  tmp[i] /= expected[i];
190  }
191 
192  gsl_histogram_free (h);
193 
194  double chiSquared = 0;
195 
196  for (uint32_t i = 0; i < N_BINS; ++i)
197  {
198  chiSquared += tmp[i];
199  }
200 
201  return chiSquared;
202 }
203 
204 void
206 {
207  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
208 
209  double sum = 0.;
210  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
211 
212  for (uint32_t i = 0; i < N_RUNS; ++i)
213  {
214  Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
215  double result = ChiSquaredTest (n);
216  sum += result;
217  }
218 
219  sum /= (double)N_RUNS;
220 
221  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
222 }
223 
224 // ===========================================================================
225 // Test case for exponential distribution random number generator
226 // ===========================================================================
228 {
229 public:
230  static const uint32_t N_RUNS = 5;
231  static const uint32_t N_BINS = 50;
232  static const uint32_t N_MEASUREMENTS = 1000000;
233 
235  virtual ~RngExponentialTestCase ();
236 
238 
239 private:
240  virtual void DoRun (void);
241 };
242 
244  : TestCase ("Exponential Random Number Generator")
245 {
246 }
247 
249 {
250 }
251 
252 double
254 {
255  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
256 
257  double range[N_BINS + 1];
258  FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
260 
261  gsl_histogram_set_ranges (h, range, N_BINS + 1);
262 
263  double expected[N_BINS];
264 
265  double mu = 1.;
266 
267  for (uint32_t i = 0; i < N_BINS; ++i)
268  {
269  expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
270  expected[i] *= N_MEASUREMENTS;
271  }
272 
273  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
274  {
275  gsl_histogram_increment (h, e->GetValue ());
276  }
277 
278  double tmp[N_BINS];
279 
280  for (uint32_t i = 0; i < N_BINS; ++i)
281  {
282  tmp[i] = gsl_histogram_get (h, i);
283  tmp[i] -= expected[i];
284  tmp[i] *= tmp[i];
285  tmp[i] /= expected[i];
286  }
287 
288  gsl_histogram_free (h);
289 
290  double chiSquared = 0;
291 
292  for (uint32_t i = 0; i < N_BINS; ++i)
293  {
294  chiSquared += tmp[i];
295  }
296 
297  return chiSquared;
298 }
299 
300 void
302 {
303  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
304 
305  double sum = 0.;
306  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
307 
308  for (uint32_t i = 0; i < N_RUNS; ++i)
309  {
310  Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
311  double result = ChiSquaredTest (e);
312  sum += result;
313  }
314 
315  sum /= (double)N_RUNS;
316 
317  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
318 }
319 
320 // ===========================================================================
321 // Test case for pareto distribution random number generator
322 // ===========================================================================
324 {
325 public:
326  static const uint32_t N_RUNS = 5;
327  static const uint32_t N_BINS = 50;
328  static const uint32_t N_MEASUREMENTS = 1000000;
329 
331  virtual ~RngParetoTestCase ();
332 
334 
335 private:
336  virtual void DoRun (void);
337 };
338 
340  : TestCase ("Pareto Random Number Generator")
341 {
342 }
343 
345 {
346 }
347 
348 double
350 {
351  gsl_histogram * h = gsl_histogram_alloc (N_BINS);
352 
353  double range[N_BINS + 1];
354  FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
356 
357  gsl_histogram_set_ranges (h, range, N_BINS + 1);
358 
359  double expected[N_BINS];
360 
361  double a = 1.5;
362  double b = 0.33333333;
363 
364  // mean is 1 with these values
365 
366  for (uint32_t i = 0; i < N_BINS; ++i)
367  {
368  expected[i] = gsl_cdf_pareto_P (range[i + 1], a, b) - gsl_cdf_pareto_P (range[i], a, b);
369  expected[i] *= N_MEASUREMENTS;
370  }
371 
372  for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
373  {
374  gsl_histogram_increment (h, p->GetValue ());
375  }
376 
377  double tmp[N_BINS];
378 
379  for (uint32_t i = 0; i < N_BINS; ++i)
380  {
381  tmp[i] = gsl_histogram_get (h, i);
382  tmp[i] -= expected[i];
383  tmp[i] *= tmp[i];
384  tmp[i] /= expected[i];
385  }
386 
387  gsl_histogram_free (h);
388 
389  double chiSquared = 0;
390 
391  for (uint32_t i = 0; i < N_BINS; ++i)
392  {
393  chiSquared += tmp[i];
394  }
395 
396  return chiSquared;
397 }
398 
399 void
401 {
402  RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
403 
404  double sum = 0.;
405  double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
406 
407  for (uint32_t i = 0; i < N_RUNS; ++i)
408  {
409  Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
410  e->SetAttribute ("Shape", DoubleValue (1.5));
411  e->SetAttribute ("Scale", DoubleValue (0.33333333));
412  double result = ChiSquaredTest (e);
413  sum += result;
414  }
415 
416  sum /= (double)N_RUNS;
417 
418  NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
419 }
420 
421 class RngTestSuite : public TestSuite
422 {
423 public:
424  RngTestSuite ();
425 };
426 
428  : TestSuite ("random-number-generators", UNIT)
429 {
430  AddTestCase (new RngUniformTestCase, TestCase::QUICK);
431  AddTestCase (new RngNormalTestCase, TestCase::QUICK);
432  AddTestCase (new RngExponentialTestCase, TestCase::QUICK);
433  AddTestCase (new RngParetoTestCase, TestCase::QUICK);
434 }
435 
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:1342
def start()
Definition: core.py:1858
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:1155
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:811
static const uint32_t N_RUNS
virtual ~RngUniformTestCase()
static const uint32_t N_BINS