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
29using namespace ns3;
30
51void
52FillHistoRangeUniformly (double *array, uint32_t n, double start, double end)
53{
54 double increment = (end - start) / (n - 1.);
55 double d = start;
56
57 for (uint32_t i = 0; i < n; ++i)
58 {
59 array[i] = d;
60 d += increment;
61 }
62}
63
70{
71public:
73 static const uint32_t N_RUNS = 5;
75 static const uint32_t N_BINS = 50;
77 static const uint32_t N_MEASUREMENTS = 1000000;
78
80 virtual ~RngUniformTestCase ();
81
88
89private:
90 virtual void DoRun (void);
91};
92
94 : TestCase ("Uniform Random Number Generator")
95{}
96
98{}
99
100double
102{
103 gsl_histogram * h = gsl_histogram_alloc (N_BINS);
104 gsl_histogram_set_ranges_uniform (h, 0., 1.);
105
106 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
107 {
108 gsl_histogram_increment (h, u->GetValue ());
109 }
110
111 double tmp[N_BINS];
112
113 double expected = ((double)N_MEASUREMENTS / (double)N_BINS);
114
115 for (uint32_t i = 0; i < N_BINS; ++i)
116 {
117 tmp[i] = gsl_histogram_get (h, i);
118 tmp[i] -= expected;
119 tmp[i] *= tmp[i];
120 tmp[i] /= expected;
121 }
122
123 gsl_histogram_free (h);
124
125 double chiSquared = 0;
126
127 for (uint32_t i = 0; i < N_BINS; ++i)
128 {
129 chiSquared += tmp[i];
130 }
131
132 return chiSquared;
133}
134
135void
137{
138 RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
139
140 double sum = 0.;
141 double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
142
143 for (uint32_t i = 0; i < N_RUNS; ++i)
144 {
145 Ptr<UniformRandomVariable> u = CreateObject<UniformRandomVariable> ();
146 double result = ChiSquaredTest (u);
147 sum += result;
148 }
149
150 sum /= (double)N_RUNS;
151
152 NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
153}
154
161{
162public:
164 static const uint32_t N_RUNS = 5;
166 static const uint32_t N_BINS = 50;
168 static const uint32_t N_MEASUREMENTS = 1000000;
169
171 virtual ~RngNormalTestCase ();
172
179
180private:
181 virtual void DoRun (void);
182};
183
185 : TestCase ("Normal Random Number Generator")
186{}
187
189{}
190
191double
193{
194 gsl_histogram * h = gsl_histogram_alloc (N_BINS);
195
196 double range[N_BINS + 1];
197 FillHistoRangeUniformly (range, N_BINS + 1, -4., 4.);
200
201 gsl_histogram_set_ranges (h, range, N_BINS + 1);
202
203 double expected[N_BINS];
204
205 double sigma = 1.;
206
207 for (uint32_t i = 0; i < N_BINS; ++i)
208 {
209 expected[i] = gsl_cdf_gaussian_P (range[i + 1], sigma) - gsl_cdf_gaussian_P (range[i], sigma);
210 expected[i] *= N_MEASUREMENTS;
211 }
212
213 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
214 {
215 gsl_histogram_increment (h, n->GetValue ());
216 }
217
218 double tmp[N_BINS];
219
220 for (uint32_t i = 0; i < N_BINS; ++i)
221 {
222 tmp[i] = gsl_histogram_get (h, i);
223 tmp[i] -= expected[i];
224 tmp[i] *= tmp[i];
225 tmp[i] /= expected[i];
226 }
227
228 gsl_histogram_free (h);
229
230 double chiSquared = 0;
231
232 for (uint32_t i = 0; i < N_BINS; ++i)
233 {
234 chiSquared += tmp[i];
235 }
236
237 return chiSquared;
238}
239
240void
242{
243 RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
244
245 double sum = 0.;
246 double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
247
248 for (uint32_t i = 0; i < N_RUNS; ++i)
249 {
250 Ptr<NormalRandomVariable> n = CreateObject<NormalRandomVariable> ();
251 double result = ChiSquaredTest (n);
252 sum += result;
253 }
254
255 sum /= (double)N_RUNS;
256
257 NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
258}
259
266{
267public:
269 static const uint32_t N_RUNS = 5;
271 static const uint32_t N_BINS = 50;
273 static const uint32_t N_MEASUREMENTS = 1000000;
274
276 virtual ~RngExponentialTestCase ();
277
284
285private:
286 virtual void DoRun (void);
287};
288
290 : TestCase ("Exponential Random Number Generator")
291{}
292
294{}
295
296double
298{
299 gsl_histogram * h = gsl_histogram_alloc (N_BINS);
300
301 double range[N_BINS + 1];
302 FillHistoRangeUniformly (range, N_BINS + 1, 0., 10.);
304
305 gsl_histogram_set_ranges (h, range, N_BINS + 1);
306
307 double expected[N_BINS];
308
309 double mu = 1.;
310
311 for (uint32_t i = 0; i < N_BINS; ++i)
312 {
313 expected[i] = gsl_cdf_exponential_P (range[i + 1], mu) - gsl_cdf_exponential_P (range[i], mu);
314 expected[i] *= N_MEASUREMENTS;
315 }
316
317 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
318 {
319 gsl_histogram_increment (h, e->GetValue ());
320 }
321
322 double tmp[N_BINS];
323
324 for (uint32_t i = 0; i < N_BINS; ++i)
325 {
326 tmp[i] = gsl_histogram_get (h, i);
327 tmp[i] -= expected[i];
328 tmp[i] *= tmp[i];
329 tmp[i] /= expected[i];
330 }
331
332 gsl_histogram_free (h);
333
334 double chiSquared = 0;
335
336 for (uint32_t i = 0; i < N_BINS; ++i)
337 {
338 chiSquared += tmp[i];
339 }
340
341 return chiSquared;
342}
343
344void
346{
347 RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
348
349 double sum = 0.;
350 double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
351
352 for (uint32_t i = 0; i < N_RUNS; ++i)
353 {
354 Ptr<ExponentialRandomVariable> e = CreateObject<ExponentialRandomVariable> ();
355 double result = ChiSquaredTest (e);
356 sum += result;
357 }
358
359 sum /= (double)N_RUNS;
360
361 NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
362}
363
370{
371public:
373 static const uint32_t N_RUNS = 5;
375 static const uint32_t N_BINS = 50;
377 static const uint32_t N_MEASUREMENTS = 1000000;
378
380 virtual ~RngParetoTestCase ();
381
388
389private:
390 virtual void DoRun (void);
391};
392
394 : TestCase ("Pareto Random Number Generator")
395{}
396
398{}
399
400double
402{
403 gsl_histogram * h = gsl_histogram_alloc (N_BINS);
404
405 double range[N_BINS + 1];
406 FillHistoRangeUniformly (range, N_BINS + 1, 1., 10.);
408
409 gsl_histogram_set_ranges (h, range, N_BINS + 1);
410
411 double expected[N_BINS];
412
413 double a = 1.5;
414 double b = 0.33333333;
415
416 // mean is 1 with these values
417
418 for (uint32_t i = 0; i < N_BINS; ++i)
419 {
420 expected[i] = gsl_cdf_pareto_P (range[i + 1], a, b) - gsl_cdf_pareto_P (range[i], a, b);
421 expected[i] *= N_MEASUREMENTS;
422 }
423
424 for (uint32_t i = 0; i < N_MEASUREMENTS; ++i)
425 {
426 gsl_histogram_increment (h, p->GetValue ());
427 }
428
429 double tmp[N_BINS];
430
431 for (uint32_t i = 0; i < N_BINS; ++i)
432 {
433 tmp[i] = gsl_histogram_get (h, i);
434 tmp[i] -= expected[i];
435 tmp[i] *= tmp[i];
436 tmp[i] /= expected[i];
437 }
438
439 gsl_histogram_free (h);
440
441 double chiSquared = 0;
442
443 for (uint32_t i = 0; i < N_BINS; ++i)
444 {
445 chiSquared += tmp[i];
446 }
447
448 return chiSquared;
449}
450
451void
453{
454 RngSeedManager::SetSeed (static_cast<uint32_t> (time (0)));
455
456 double sum = 0.;
457 double maxStatistic = gsl_cdf_chisq_Qinv (0.05, N_BINS);
458
459 for (uint32_t i = 0; i < N_RUNS; ++i)
460 {
461 Ptr<ParetoRandomVariable> e = CreateObject<ParetoRandomVariable> ();
462 e->SetAttribute ("Shape", DoubleValue (1.5));
463 e->SetAttribute ("Scale", DoubleValue (0.33333333));
464 double result = ChiSquaredTest (e);
465 sum += result;
466 }
467
468 sum /= (double)N_RUNS;
469
470 NS_TEST_ASSERT_MSG_LT (sum, maxStatistic, "Chi-squared statistic out of range");
471}
472
479{
480public:
481 RngTestSuite ();
482};
483
485 : TestSuite ("random-number-generators", UNIT)
486{
487 AddTestCase (new RngUniformTestCase, TestCase::QUICK);
488 AddTestCase (new RngNormalTestCase, TestCase::QUICK);
489 AddTestCase (new RngExponentialTestCase, TestCase::QUICK);
490 AddTestCase (new RngParetoTestCase, TestCase::QUICK);
491}
492
#define max(a, b)
Definition: 80211b.c:43
Test case for exponential distribution random number generator.
static const uint32_t N_BINS
Number of bins.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_MEASUREMENTS
Number of measurements.
double ChiSquaredTest(Ptr< ExponentialRandomVariable > n)
Run a chi-squared test on the results of the random number generator.
static const uint32_t N_RUNS
Number of runs.
Test case for normal distribution random number generator.
double ChiSquaredTest(Ptr< NormalRandomVariable > n)
Run a chi-squared test on the results of the random number generator.
static const uint32_t N_MEASUREMENTS
Number of measurements.
virtual ~RngNormalTestCase()
static const uint32_t N_RUNS
Number of runs.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_BINS
Number of bins.
Test case for pareto distribution random number generator.
static const uint32_t N_RUNS
Number of runs.
double ChiSquaredTest(Ptr< ParetoRandomVariable > p)
Run a chi-squared test on the results of the random number generator.
static const uint32_t N_BINS
Number of bins.
static const uint32_t N_MEASUREMENTS
Number of measurements.
virtual ~RngParetoTestCase()
virtual void DoRun(void)
Implementation to actually run this TestCase.
The random number generators Test Suite.
Test case for uniform distribution random number generator.
double ChiSquaredTest(Ptr< UniformRandomVariable > u)
Run a chi-squared test on the results of the random number generator.
static const uint32_t N_MEASUREMENTS
Number of measurements.
virtual void DoRun(void)
Implementation to actually run this TestCase.
static const uint32_t N_BINS
Number of bins.
static const uint32_t N_RUNS
Number of runs.
virtual ~RngUniformTestCase()
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
double GetValue(double mean, double bound)
Get the next random value, as a double from the exponential distribution with the specified mean and ...
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
void FillHistoRangeUniformly(double *array, uint32_t n, double start, double end)
Fill an array with increasing values, in the [start, end] range.
#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:675
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1852
static RngTestSuite g_rngTestSuite
Static variable for test initialization.