A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
random-variable-stream.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006 Georgia Tech Research Corporation
4  * Copyright (c) 2011 Mathieu Lacage
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Rajib Bhattacharjea<raj.b@gatech.edu>
20  * Hadi Arbabi<marbabi@cs.odu.edu>
21  * Mathieu Lacage <mathieu.lacage@gmail.com>
22  *
23  * Modified by Mitch Watrous <watrous@u.washington.edu>
24  *
25  */
26 #include "random-variable-stream.h"
27 #include "assert.h"
28 #include "boolean.h"
29 #include "double.h"
30 #include "integer.h"
31 #include "string.h"
32 #include "pointer.h"
33 #include "log.h"
34 #include "rng-stream.h"
35 #include "rng-seed-manager.h"
36 #include <cmath>
37 #include <iostream>
38 
39 NS_LOG_COMPONENT_DEFINE ("RandomVariableStream");
40 
41 namespace ns3 {
42 
43 NS_OBJECT_ENSURE_REGISTERED (RandomVariableStream);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId ("ns3::RandomVariableStream")
49  .SetParent<Object> ()
50  .AddAttribute("Stream",
51  "The stream number for this RNG stream. -1 means \"allocate a stream automatically\". "
52  "Note that if -1 is set, Get will return -1 so that it is not possible to know which "
53  "value was automatically allocated.",
54  IntegerValue(-1),
55  MakeIntegerAccessor(&RandomVariableStream::SetStream,
57  MakeIntegerChecker<int64_t>())
58  .AddAttribute("Antithetic", "Set this RNG stream to generate antithetic values",
59  BooleanValue (false),
60  MakeBooleanAccessor(&RandomVariableStream::SetAntithetic,
62  MakeBooleanChecker())
63  ;
64  return tid;
65 }
66 
68  : m_rng (0)
69 {}
71 {
72  delete m_rng;
73 }
74 
75 void
77 {
78  m_isAntithetic = isAntithetic;
79 }
80 bool
82 {
83  return m_isAntithetic;
84 }
85 void
87 {
88  NS_LOG_FUNCTION (this << stream);
89  // negative values are not legal.
90  NS_ASSERT (stream >= -1);
91  delete m_rng;
92  if (stream == -1)
93  {
94  // The first 2^63 streams are reserved for automatic stream
95  // number assignment.
96  uint64_t nextStream = RngSeedManager::GetNextStreamIndex ();
97  NS_ASSERT(nextStream <= ((1ULL)<<63));
99  nextStream,
101  }
102  else
103  {
104  // The last 2^63 streams are reserved for deterministic stream
105  // number assignment.
106  uint64_t base = ((1ULL)<<63);
107  uint64_t target = base + stream;
109  target,
111  }
112  m_stream = stream;
113 }
114 int64_t
116 {
117  return m_stream;
118 }
119 
120 RngStream *
122 {
123  return m_rng;
124 }
125 
127 
128 TypeId
130 {
131  static TypeId tid = TypeId ("ns3::UniformRandomVariable")
133  .AddConstructor<UniformRandomVariable> ()
134  .AddAttribute("Min", "The lower bound on the values returned by this RNG stream.",
135  DoubleValue(0),
136  MakeDoubleAccessor(&UniformRandomVariable::m_min),
137  MakeDoubleChecker<double>())
138  .AddAttribute("Max", "The upper bound on the values returned by this RNG stream.",
139  DoubleValue(1.0),
140  MakeDoubleAccessor(&UniformRandomVariable::m_max),
141  MakeDoubleChecker<double>())
142  ;
143  return tid;
144 }
146 {
147  // m_min and m_max are initialized after constructor by attributes
148 }
149 
150 double
152 {
153  return m_min;
154 }
155 double
157 {
158  return m_max;
159 }
160 
161 double
162 UniformRandomVariable::GetValue (double min, double max)
163 {
164  double v = min + Peek ()->RandU01 () * (max - min);
165  if (IsAntithetic ())
166  {
167  v = min + (max - v);
168  }
169  return v;
170 }
171 uint32_t
172 UniformRandomVariable::GetInteger (uint32_t min, uint32_t max)
173 {
174  NS_ASSERT (min <= max);
175  return static_cast<uint32_t> ( GetValue (min, max + 1) );
176 }
177 
178 double
180 {
181  return GetValue (m_min, m_max);
182 }
183 uint32_t
185 {
186  return (uint32_t)GetValue (m_min, m_max + 1);
187 }
188 
190 
191 TypeId
193 {
194  static TypeId tid = TypeId ("ns3::ConstantRandomVariable")
196  .AddConstructor<ConstantRandomVariable> ()
197  .AddAttribute("Constant", "The constant value returned by this RNG stream.",
198  DoubleValue(0),
199  MakeDoubleAccessor(&ConstantRandomVariable::m_constant),
200  MakeDoubleChecker<double>())
201  ;
202  return tid;
203 }
205 {
206  // m_constant is initialized after constructor by attributes
207 }
208 
209 double
211 {
212  return m_constant;
213 }
214 
215 double
217 {
218  return constant;
219 }
220 uint32_t
222 {
223  return constant;
224 }
225 
226 double
228 {
229  return GetValue (m_constant);
230 }
231 uint32_t
233 {
234  return (uint32_t)GetValue (m_constant);
235 }
236 
238 
239 TypeId
241 {
242  static TypeId tid = TypeId ("ns3::SequentialRandomVariable")
244  .AddConstructor<SequentialRandomVariable> ()
245  .AddAttribute("Min", "The first value of the sequence.",
246  DoubleValue(0),
247  MakeDoubleAccessor(&SequentialRandomVariable::m_min),
248  MakeDoubleChecker<double>())
249  .AddAttribute("Max", "One more than the last value of the sequence.",
250  DoubleValue(0),
251  MakeDoubleAccessor(&SequentialRandomVariable::m_max),
252  MakeDoubleChecker<double>())
253  .AddAttribute("Increment", "The sequence random variable increment.",
254  StringValue("ns3::ConstantRandomVariable[Constant=1]"),
255  MakePointerAccessor (&SequentialRandomVariable::m_increment),
256  MakePointerChecker<RandomVariableStream> ())
257  .AddAttribute("Consecutive", "The number of times each member of the sequence is repeated.",
258  IntegerValue(1),
259  MakeIntegerAccessor(&SequentialRandomVariable::m_consecutive),
260  MakeIntegerChecker<uint32_t>());
261  ;
262  return tid;
263 }
265  :
266  m_current (0),
267  m_currentConsecutive (0),
268  m_isCurrentSet (false)
269 {
270  // m_min, m_max, m_increment, and m_consecutive are initialized
271  // after constructor by attributes.
272 }
273 
274 double
276 {
277  return m_min;
278 }
279 
280 double
282 {
283  return m_max;
284 }
285 
288 {
289  return m_increment;
290 }
291 
292 uint32_t
294 {
295  return m_consecutive;
296 }
297 
298 double
300 {
301  // Set the current sequence value if it hasn't been set.
302  if (!m_isCurrentSet)
303  {
304  // Start the sequence at its minimium value.
305  m_current = m_min;
306  m_isCurrentSet = true;
307  }
308 
309  // Return a sequential series of values
310  double r = m_current;
312  { // Time to advance to next
315  if (m_current >= m_max)
316  {
317  m_current = m_min + (m_current - m_max);
318  }
319  }
320  return r;
321 }
322 
323 uint32_t
325 {
326  return (uint32_t)GetValue ();
327 }
328 
330 
331 TypeId
333 {
334  static TypeId tid = TypeId ("ns3::ExponentialRandomVariable")
336  .AddConstructor<ExponentialRandomVariable> ()
337  .AddAttribute("Mean", "The mean of the values returned by this RNG stream.",
338  DoubleValue(1.0),
339  MakeDoubleAccessor(&ExponentialRandomVariable::m_mean),
340  MakeDoubleChecker<double>())
341  .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
342  DoubleValue(0.0),
343  MakeDoubleAccessor(&ExponentialRandomVariable::m_bound),
344  MakeDoubleChecker<double>())
345  ;
346  return tid;
347 }
349 {
350  // m_mean and m_bound are initialized after constructor by attributes
351 }
352 
353 double
355 {
356  return m_mean;
357 }
358 double
360 {
361  return m_bound;
362 }
363 
364 double
365 ExponentialRandomVariable::GetValue (double mean, double bound)
366 {
367  while (1)
368  {
369  // Get a uniform random variable in [0,1].
370  double v = Peek ()->RandU01 ();
371  if (IsAntithetic ())
372  {
373  v = (1 - v);
374  }
375 
376  // Calculate the exponential random variable.
377  double r = -mean*std::log (v);
378 
379  // Use this value if it's acceptable.
380  if (bound == 0 || r <= bound)
381  {
382  return r;
383  }
384  }
385 }
386 uint32_t
387 ExponentialRandomVariable::GetInteger (uint32_t mean, uint32_t bound)
388 {
389  return static_cast<uint32_t> ( GetValue (mean, bound) );
390 }
391 
392 double
394 {
395  return GetValue (m_mean, m_bound);
396 }
397 uint32_t
399 {
400  return (uint32_t)GetValue (m_mean, m_bound);
401 }
402 
404 
405 TypeId
407 {
408  static TypeId tid = TypeId ("ns3::ParetoRandomVariable")
410  .AddConstructor<ParetoRandomVariable> ()
411  .AddAttribute("Mean", "The mean parameter for the Pareto distribution returned by this RNG stream.",
412  DoubleValue(1.0),
413  MakeDoubleAccessor(&ParetoRandomVariable::m_mean),
414  MakeDoubleChecker<double>())
415  .AddAttribute("Shape", "The shape parameter for the Pareto distribution returned by this RNG stream.",
416  DoubleValue(2.0),
417  MakeDoubleAccessor(&ParetoRandomVariable::m_shape),
418  MakeDoubleChecker<double>())
419  .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
420  DoubleValue(0.0),
421  MakeDoubleAccessor(&ParetoRandomVariable::m_bound),
422  MakeDoubleChecker<double>())
423  ;
424  return tid;
425 }
427 {
428  // m_mean, m_shape, and m_bound are initialized after constructor
429  // by attributes
430 }
431 
432 double
434 {
435  return m_mean;
436 }
437 double
439 {
440  return m_shape;
441 }
442 double
444 {
445  return m_bound;
446 }
447 
448 double
449 ParetoRandomVariable::GetValue (double mean, double shape, double bound)
450 {
451  // Calculate the scale parameter.
452  double scale = mean * (shape - 1.0) / shape;
453 
454  while (1)
455  {
456  // Get a uniform random variable in [0,1].
457  double v = Peek ()->RandU01 ();
458  if (IsAntithetic ())
459  {
460  v = (1 - v);
461  }
462 
463  // Calculate the Pareto random variable.
464  double r = (scale * ( 1.0 / std::pow (v, 1.0 / shape)));
465 
466  // Use this value if it's acceptable.
467  if (bound == 0 || r <= bound)
468  {
469  return r;
470  }
471  }
472 }
473 uint32_t
474 ParetoRandomVariable::GetInteger (uint32_t mean, uint32_t shape, uint32_t bound)
475 {
476  return static_cast<uint32_t> ( GetValue (mean, shape, bound) );
477 }
478 
479 double
481 {
482  return GetValue (m_mean, m_shape, m_bound);
483 }
484 uint32_t
486 {
487  return (uint32_t)GetValue (m_mean, m_shape, m_bound);
488 }
489 
491 
492 TypeId
494 {
495  static TypeId tid = TypeId ("ns3::WeibullRandomVariable")
497  .AddConstructor<WeibullRandomVariable> ()
498  .AddAttribute("Scale", "The scale parameter for the Weibull distribution returned by this RNG stream.",
499  DoubleValue(1.0),
500  MakeDoubleAccessor(&WeibullRandomVariable::m_scale),
501  MakeDoubleChecker<double>())
502  .AddAttribute("Shape", "The shape parameter for the Weibull distribution returned by this RNG stream.",
503  DoubleValue(1),
504  MakeDoubleAccessor(&WeibullRandomVariable::m_shape),
505  MakeDoubleChecker<double>())
506  .AddAttribute("Bound", "The upper bound on the values returned by this RNG stream.",
507  DoubleValue(0.0),
508  MakeDoubleAccessor(&WeibullRandomVariable::m_bound),
509  MakeDoubleChecker<double>())
510  ;
511  return tid;
512 }
514 {
515  // m_scale, m_shape, and m_bound are initialized after constructor
516  // by attributes
517 }
518 
519 double
521 {
522  return m_scale;
523 }
524 double
526 {
527  return m_shape;
528 }
529 double
531 {
532  return m_bound;
533 }
534 
535 double
536 WeibullRandomVariable::GetValue (double scale, double shape, double bound)
537 {
538  double exponent = 1.0 / shape;
539  while (1)
540  {
541  // Get a uniform random variable in [0,1].
542  double v = Peek ()->RandU01 ();
543  if (IsAntithetic ())
544  {
545  v = (1 - v);
546  }
547 
548  // Calculate the Weibull random variable.
549  double r = scale * std::pow ( -std::log (v), exponent);
550 
551  // Use this value if it's acceptable.
552  if (bound == 0 || r <= bound)
553  {
554  return r;
555  }
556  }
557 }
558 uint32_t
559 WeibullRandomVariable::GetInteger (uint32_t scale, uint32_t shape, uint32_t bound)
560 {
561  return static_cast<uint32_t> ( GetValue (scale, shape, bound) );
562 }
563 
564 double
566 {
567  return GetValue (m_scale, m_shape, m_bound);
568 }
569 uint32_t
571 {
572  return (uint32_t)GetValue (m_scale, m_shape, m_bound);
573 }
574 
576 
577 const double NormalRandomVariable::INFINITE_VALUE = 1e307;
578 
579 TypeId
581 {
582  static TypeId tid = TypeId ("ns3::NormalRandomVariable")
584  .AddConstructor<NormalRandomVariable> ()
585  .AddAttribute("Mean", "The mean value for the normal distribution returned by this RNG stream.",
586  DoubleValue(0.0),
587  MakeDoubleAccessor(&NormalRandomVariable::m_mean),
588  MakeDoubleChecker<double>())
589  .AddAttribute("Variance", "The variance value for the normal distribution returned by this RNG stream.",
590  DoubleValue(1.0),
591  MakeDoubleAccessor(&NormalRandomVariable::m_variance),
592  MakeDoubleChecker<double>())
593  .AddAttribute("Bound", "The bound on the values returned by this RNG stream.",
595  MakeDoubleAccessor(&NormalRandomVariable::m_bound),
596  MakeDoubleChecker<double>())
597  ;
598  return tid;
599 }
601  :
602  m_nextValid (false)
603 {
604  // m_mean, m_variance, and m_bound are initialized after constructor
605  // by attributes
606 }
607 
608 double
610 {
611  return m_mean;
612 }
613 double
615 {
616  return m_variance;
617 }
618 double
620 {
621  return m_bound;
622 }
623 
624 double
625 NormalRandomVariable::GetValue (double mean, double variance, double bound)
626 {
627  if (m_nextValid)
628  { // use previously generated
629  m_nextValid = false;
630  return m_next;
631  }
632  while (1)
633  { // See Simulation Modeling and Analysis p. 466 (Averill Law)
634  // for algorithm; basically a Box-Muller transform:
635  // http://en.wikipedia.org/wiki/Box-Muller_transform
636  double u1 = Peek ()->RandU01 ();
637  double u2 = Peek ()->RandU01 ();
638  if (IsAntithetic ())
639  {
640  u1 = (1 - u1);
641  u2 = (1 - u2);
642  }
643  double v1 = 2 * u1 - 1;
644  double v2 = 2 * u2 - 1;
645  double w = v1 * v1 + v2 * v2;
646  if (w <= 1.0)
647  { // Got good pair
648  double y = sqrt ((-2 * log (w)) / w);
649  m_next = mean + v2 * y * sqrt (variance);
650  // if next is in bounds, it is valid
651  m_nextValid = fabs (m_next - mean) <= bound;
652  double x1 = mean + v1 * y * sqrt (variance);
653  // if x1 is in bounds, return it
654  if (fabs (x1 - mean) <= bound)
655  {
656  return x1;
657  }
658  // otherwise try and return m_next if it is valid
659  else if (m_nextValid)
660  {
661  m_nextValid = false;
662  return m_next;
663  }
664  // otherwise, just run this loop again
665  }
666  }
667 }
668 
669 uint32_t
670 NormalRandomVariable::GetInteger (uint32_t mean, uint32_t variance, uint32_t bound)
671 {
672  return static_cast<uint32_t> ( GetValue (mean, variance, bound) );
673 }
674 
675 double
677 {
678  return GetValue (m_mean, m_variance, m_bound);
679 }
680 uint32_t
682 {
683  return (uint32_t)GetValue (m_mean, m_variance, m_bound);
684 }
685 
687 
688 TypeId
690 {
691  static TypeId tid = TypeId ("ns3::LogNormalRandomVariable")
693  .AddConstructor<LogNormalRandomVariable> ()
694  .AddAttribute("Mu", "The mu value for the log-normal distribution returned by this RNG stream.",
695  DoubleValue(0.0),
696  MakeDoubleAccessor(&LogNormalRandomVariable::m_mu),
697  MakeDoubleChecker<double>())
698  .AddAttribute("Sigma", "The sigma value for the log-normal distribution returned by this RNG stream.",
699  DoubleValue(1.0),
700  MakeDoubleAccessor(&LogNormalRandomVariable::m_sigma),
701  MakeDoubleChecker<double>())
702  ;
703  return tid;
704 }
706 {
707  // m_mu and m_sigma are initialized after constructor by
708  // attributes
709 }
710 
711 double
713 {
714  return m_mu;
715 }
716 double
718 {
719  return m_sigma;
720 }
721 
722 // The code from this function was adapted from the GNU Scientific
723 // Library 1.8:
724 /* randist/lognormal.c
725  *
726  * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
727  *
728  * This program is free software; you can redistribute it and/or modify
729  * it under the terms of the GNU General Public License as published by
730  * the Free Software Foundation; either version 2 of the License, or (at
731  * your option) any later version.
732  *
733  * This program is distributed in the hope that it will be useful, but
734  * WITHOUT ANY WARRANTY; without even the implied warranty of
735  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
736  * General Public License for more details.
737  *
738  * You should have received a copy of the GNU General Public License
739  * along with this program; if not, write to the Free Software
740  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
741  */
742 /* The lognormal distribution has the form
743 
744  p(x) dx = 1/(x * sqrt(2 pi sigma^2)) exp(-(ln(x) - zeta)^2/2 sigma^2) dx
745 
746  for x > 0. Lognormal random numbers are the exponentials of
747  gaussian random numbers */
748 double
749 LogNormalRandomVariable::GetValue (double mu, double sigma)
750 {
751  double v1, v2, r2, normal, x;
752 
753  do
754  {
755  /* choose x,y in uniform square (-1,-1) to (+1,+1) */
756 
757  double u1 = Peek ()->RandU01 ();
758  double u2 = Peek ()->RandU01 ();
759  if (IsAntithetic ())
760  {
761  u1 = (1 - u1);
762  u2 = (1 - u2);
763  }
764 
765  v1 = -1 + 2 * u1;
766  v2 = -1 + 2 * u2;
767 
768  /* see if it is in the unit circle */
769  r2 = v1 * v1 + v2 * v2;
770  }
771  while (r2 > 1.0 || r2 == 0);
772 
773  normal = v1 * std::sqrt (-2.0 * std::log (r2) / r2);
774 
775  x = std::exp (sigma * normal + mu);
776 
777  return x;
778 }
779 
780 uint32_t
781 LogNormalRandomVariable::GetInteger (uint32_t mu, uint32_t sigma)
782 {
783  return static_cast<uint32_t> ( GetValue (mu, sigma));
784 }
785 
786 double
788 {
789  return GetValue (m_mu, m_sigma);
790 }
791 uint32_t
793 {
794  return (uint32_t)GetValue (m_mu, m_sigma);
795 }
796 
798 
799 TypeId
801 {
802  static TypeId tid = TypeId ("ns3::GammaRandomVariable")
804  .AddConstructor<GammaRandomVariable> ()
805  .AddAttribute("Alpha", "The alpha value for the gamma distribution returned by this RNG stream.",
806  DoubleValue(1.0),
807  MakeDoubleAccessor(&GammaRandomVariable::m_alpha),
808  MakeDoubleChecker<double>())
809  .AddAttribute("Beta", "The beta value for the gamma distribution returned by this RNG stream.",
810  DoubleValue(1.0),
811  MakeDoubleAccessor(&GammaRandomVariable::m_beta),
812  MakeDoubleChecker<double>())
813  ;
814  return tid;
815 }
817  :
818  m_nextValid (false)
819 {
820  // m_alpha and m_beta are initialized after constructor by
821  // attributes
822 }
823 
824 double
826 {
827  return m_alpha;
828 }
829 double
831 {
832  return m_beta;
833 }
834 
835 /*
836  The code for the following generator functions was adapted from ns-2
837  tools/ranvar.cc
838 
839  Originally the algorithm was devised by Marsaglia in 2000:
840  G. Marsaglia, W. W. Tsang: A simple method for gereating Gamma variables
841  ACM Transactions on mathematical software, Vol. 26, No. 3, Sept. 2000
842 
843  The Gamma distribution density function has the form
844 
845  x^(alpha-1) * exp(-x/beta)
846  p(x; alpha, beta) = ----------------------------
847  beta^alpha * Gamma(alpha)
848 
849  for x > 0.
850 */
851 double
852 GammaRandomVariable::GetValue (double alpha, double beta)
853 {
854  if (alpha < 1)
855  {
856  double u = Peek ()->RandU01 ();
857  if (IsAntithetic ())
858  {
859  u = (1 - u);
860  }
861  return GetValue (1.0 + alpha, beta) * std::pow (u, 1.0 / alpha);
862  }
863 
864  double x, v, u;
865  double d = alpha - 1.0 / 3.0;
866  double c = (1.0 / 3.0) / sqrt (d);
867 
868  while (1)
869  {
870  do
871  {
872  // Get a value from a normal distribution that has mean
873  // zero, variance 1, and no bound.
874  double mean = 0.0;
875  double variance = 1.0;
877  x = GetNormalValue (mean, variance, bound);
878 
879  v = 1.0 + c * x;
880  }
881  while (v <= 0);
882 
883  v = v * v * v;
884  u = Peek ()->RandU01 ();
885  if (IsAntithetic ())
886  {
887  u = (1 - u);
888  }
889  if (u < 1 - 0.0331 * x * x * x * x)
890  {
891  break;
892  }
893  if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
894  {
895  break;
896  }
897  }
898 
899  return beta * d * v;
900 }
901 
902 uint32_t
903 GammaRandomVariable::GetInteger (uint32_t alpha, uint32_t beta)
904 {
905  return static_cast<uint32_t> ( GetValue (alpha, beta));
906 }
907 
908 double
910 {
911  return GetValue (m_alpha, m_beta);
912 }
913 uint32_t
915 {
916  return (uint32_t)GetValue (m_alpha, m_beta);
917 }
918 
919 double
920 GammaRandomVariable::GetNormalValue (double mean, double variance, double bound)
921 {
922  if (m_nextValid)
923  { // use previously generated
924  m_nextValid = false;
925  return m_next;
926  }
927  while (1)
928  { // See Simulation Modeling and Analysis p. 466 (Averill Law)
929  // for algorithm; basically a Box-Muller transform:
930  // http://en.wikipedia.org/wiki/Box-Muller_transform
931  double u1 = Peek ()->RandU01 ();
932  double u2 = Peek ()->RandU01 ();
933  if (IsAntithetic ())
934  {
935  u1 = (1 - u1);
936  u2 = (1 - u2);
937  }
938  double v1 = 2 * u1 - 1;
939  double v2 = 2 * u2 - 1;
940  double w = v1 * v1 + v2 * v2;
941  if (w <= 1.0)
942  { // Got good pair
943  double y = sqrt ((-2 * log (w)) / w);
944  m_next = mean + v2 * y * sqrt (variance);
945  // if next is in bounds, it is valid
946  m_nextValid = fabs (m_next - mean) <= bound;
947  double x1 = mean + v1 * y * sqrt (variance);
948  // if x1 is in bounds, return it
949  if (fabs (x1 - mean) <= bound)
950  {
951  return x1;
952  }
953  // otherwise try and return m_next if it is valid
954  else if (m_nextValid)
955  {
956  m_nextValid = false;
957  return m_next;
958  }
959  // otherwise, just run this loop again
960  }
961  }
962 }
963 
965 
966 TypeId
968 {
969  static TypeId tid = TypeId ("ns3::ErlangRandomVariable")
971  .AddConstructor<ErlangRandomVariable> ()
972  .AddAttribute("K", "The k value for the Erlang distribution returned by this RNG stream.",
973  IntegerValue(1),
974  MakeIntegerAccessor(&ErlangRandomVariable::m_k),
975  MakeIntegerChecker<uint32_t>())
976  .AddAttribute("Lambda", "The lambda value for the Erlang distribution returned by this RNG stream.",
977  DoubleValue(1.0),
978  MakeDoubleAccessor(&ErlangRandomVariable::m_lambda),
979  MakeDoubleChecker<double>())
980  ;
981  return tid;
982 }
984 {
985  // m_k and m_lambda are initialized after constructor by attributes
986 }
987 
988 uint32_t
990 {
991  return m_k;
992 }
993 double
995 {
996  return m_lambda;
997 }
998 
999 /*
1000  The code for the following generator functions was adapted from ns-2
1001  tools/ranvar.cc
1002 
1003  The Erlang distribution density function has the form
1004 
1005  x^(k-1) * exp(-x/lambda)
1006  p(x; k, lambda) = ---------------------------
1007  lambda^k * (k-1)!
1008 
1009  for x > 0.
1010 */
1011 double
1012 ErlangRandomVariable::GetValue (uint32_t k, double lambda)
1013 {
1014  double mean = lambda;
1015  double bound = 0.0;
1016 
1017  double result = 0;
1018  for (unsigned int i = 0; i < k; ++i)
1019  {
1020  result += GetExponentialValue (mean, bound);
1021 
1022  }
1023 
1024  return result;
1025 }
1026 
1027 uint32_t
1028 ErlangRandomVariable::GetInteger (uint32_t k, uint32_t lambda)
1029 {
1030  return static_cast<uint32_t> ( GetValue (k, lambda));
1031 }
1032 
1033 double
1035 {
1036  return GetValue (m_k, m_lambda);
1037 }
1038 uint32_t
1040 {
1041  return (uint32_t)GetValue (m_k, m_lambda);
1042 }
1043 
1044 double
1046 {
1047  while (1)
1048  {
1049  // Get a uniform random variable in [0,1].
1050  double v = Peek ()->RandU01 ();
1051  if (IsAntithetic ())
1052  {
1053  v = (1 - v);
1054  }
1055 
1056  // Calculate the exponential random variable.
1057  double r = -mean*std::log (v);
1058 
1059  // Use this value if it's acceptable.
1060  if (bound == 0 || r <= bound)
1061  {
1062  return r;
1063  }
1064  }
1065 }
1066 
1068 
1069 TypeId
1071 {
1072  static TypeId tid = TypeId ("ns3::TriangularRandomVariable")
1074  .AddConstructor<TriangularRandomVariable> ()
1075  .AddAttribute("Mean", "The mean value for the triangular distribution returned by this RNG stream.",
1076  DoubleValue(0.5),
1077  MakeDoubleAccessor(&TriangularRandomVariable::m_mean),
1078  MakeDoubleChecker<double>())
1079  .AddAttribute("Min", "The lower bound on the values returned by this RNG stream.",
1080  DoubleValue(0.0),
1081  MakeDoubleAccessor(&TriangularRandomVariable::m_min),
1082  MakeDoubleChecker<double>())
1083  .AddAttribute("Max", "The upper bound on the values returned by this RNG stream.",
1084  DoubleValue(1.0),
1085  MakeDoubleAccessor(&TriangularRandomVariable::m_max),
1086  MakeDoubleChecker<double>())
1087  ;
1088  return tid;
1089 }
1091  :
1092  m_mode (0.5)
1093 {
1094  // m_mean, m_min, and m_max are initialized after constructor by
1095  // attributes
1096 }
1097 
1098 double
1100 {
1101  return m_mean;
1102 }
1103 double
1105 {
1106  return m_min;
1107 }
1108 double
1110 {
1111  return m_max;
1112 }
1113 
1114 double
1115 TriangularRandomVariable::GetValue (double mean, double min, double max)
1116 {
1117  // Calculate the mode.
1118  double mode = 3.0 * mean - min - max;
1119 
1120  // Get a uniform random variable in [0,1].
1121  double u = Peek ()->RandU01 ();
1122  if (IsAntithetic ())
1123  {
1124  u = (1 - u);
1125  }
1126 
1127  // Calculate the triangular random variable.
1128  if (u <= (mode - min) / (max - min) )
1129  {
1130  return min + sqrt (u * (max - min) * (mode - min) );
1131  }
1132  else
1133  {
1134  return max - sqrt ( (1 - u) * (max - min) * (max - mode) );
1135  }
1136 }
1137 
1138 uint32_t
1139 TriangularRandomVariable::GetInteger (uint32_t mean, uint32_t min, uint32_t max)
1140 {
1141  return static_cast<uint32_t> ( GetValue (mean, min, max) );
1142 }
1143 
1144 double
1146 {
1147  return GetValue (m_mean, m_min, m_max);
1148 }
1149 uint32_t
1151 {
1152  return (uint32_t)GetValue (m_mean, m_min, m_max);
1153 }
1154 
1156 
1157 TypeId
1159 {
1160  static TypeId tid = TypeId ("ns3::ZipfRandomVariable")
1162  .AddConstructor<ZipfRandomVariable> ()
1163  .AddAttribute("N", "The n value for the Zipf distribution returned by this RNG stream.",
1164  IntegerValue(1),
1165  MakeIntegerAccessor(&ZipfRandomVariable::m_n),
1166  MakeIntegerChecker<uint32_t>())
1167  .AddAttribute("Alpha", "The alpha value for the Zipf distribution returned by this RNG stream.",
1168  DoubleValue(0.0),
1169  MakeDoubleAccessor(&ZipfRandomVariable::m_alpha),
1170  MakeDoubleChecker<double>())
1171  ;
1172  return tid;
1173 }
1175 {
1176  // m_n and m_alpha are initialized after constructor by attributes
1177 }
1178 
1179 uint32_t
1181 {
1182  return m_n;
1183 }
1184 double
1186 {
1187  return m_alpha;
1188 }
1189 
1190 double
1191 ZipfRandomVariable::GetValue (uint32_t n, double alpha)
1192 {
1193  // Calculate the normalization constant c.
1194  m_c = 0.0;
1195  for (uint32_t i = 1; i <= n; i++)
1196  {
1197  m_c += (1.0 / std::pow ((double)i,alpha));
1198  }
1199  m_c = 1.0 / m_c;
1200 
1201  // Get a uniform random variable in [0,1].
1202  double u = Peek ()->RandU01 ();
1203  if (IsAntithetic ())
1204  {
1205  u = (1 - u);
1206  }
1207 
1208  double sum_prob = 0,zipf_value = 0;
1209  for (uint32_t i = 1; i <= m_n; i++)
1210  {
1211  sum_prob += m_c / std::pow ((double)i,m_alpha);
1212  if (sum_prob > u)
1213  {
1214  zipf_value = i;
1215  break;
1216  }
1217  }
1218  return zipf_value;
1219 }
1220 
1221 uint32_t
1222 ZipfRandomVariable::GetInteger (uint32_t n, uint32_t alpha)
1223 {
1224  return static_cast<uint32_t> ( GetValue (n, alpha));
1225 }
1226 
1227 double
1229 {
1230  return GetValue (m_n, m_alpha);
1231 }
1232 uint32_t
1234 {
1235  return (uint32_t)GetValue (m_n, m_alpha);
1236 }
1237 
1239 
1240 TypeId
1242 {
1243  static TypeId tid = TypeId ("ns3::ZetaRandomVariable")
1245  .AddConstructor<ZetaRandomVariable> ()
1246  .AddAttribute("Alpha", "The alpha value for the zeta distribution returned by this RNG stream.",
1247  DoubleValue(3.14),
1248  MakeDoubleAccessor(&ZetaRandomVariable::m_alpha),
1249  MakeDoubleChecker<double>())
1250  ;
1251  return tid;
1252 }
1254 {
1255  // m_alpha is initialized after constructor by attributes
1256 }
1257 
1258 double
1260 {
1261  return m_alpha;
1262 }
1263 
1264 double
1266 {
1267  m_b = std::pow (2.0, alpha - 1.0);
1268 
1269  double u, v;
1270  double X, T;
1271  double test;
1272 
1273  do
1274  {
1275  // Get a uniform random variable in [0,1].
1276  u = Peek ()->RandU01 ();
1277  if (IsAntithetic ())
1278  {
1279  u = (1 - u);
1280  }
1281 
1282  // Get a uniform random variable in [0,1].
1283  v = Peek ()->RandU01 ();
1284  if (IsAntithetic ())
1285  {
1286  v = (1 - v);
1287  }
1288 
1289  X = std::floor (std::pow (u, -1.0 / (m_alpha - 1.0)));
1290  T = std::pow (1.0 + 1.0 / X, m_alpha - 1.0);
1291  test = v * X * (T - 1.0) / (m_b - 1.0);
1292  }
1293  while ( test > (T / m_b) );
1294 
1295  return X;
1296 }
1297 
1298 uint32_t
1300 {
1301  return static_cast<uint32_t> ( GetValue (alpha));
1302 }
1303 
1304 double
1306 {
1307  return GetValue (m_alpha);
1308 }
1309 uint32_t
1311 {
1312  return (uint32_t)GetValue (m_alpha);
1313 }
1314 
1316 
1317 TypeId
1319 {
1320  static TypeId tid = TypeId ("ns3::DeterministicRandomVariable")
1322  .AddConstructor<DeterministicRandomVariable> ()
1323  ;
1324  return tid;
1325 }
1327  :
1328  m_count (0),
1329  m_next (0),
1330  m_data (0)
1331 {
1332 }
1334 {
1335  // Delete any values currently set.
1336  if (m_data != 0)
1337  {
1338  delete[] m_data;
1339  }
1340 }
1341 
1342 void
1343 DeterministicRandomVariable::SetValueArray (double* values, uint64_t length)
1344 {
1345  // Delete any values currently set.
1346  if (m_data != 0)
1347  {
1348  delete[] m_data;
1349  }
1350 
1351  // Make room for the values being set.
1352  m_data = new double[length];
1353  m_count = length;
1354  m_next = length;
1355 
1356  // Copy the values.
1357  for (uint64_t i = 0; i < m_count; i++)
1358  {
1359  m_data[i] = values[i];
1360  }
1361 }
1362 
1363 double
1365 {
1366  // Make sure the array has been set.
1367  NS_ASSERT (m_count > 0);
1368 
1369  if (m_next == m_count)
1370  {
1371  m_next = 0;
1372  }
1373  return m_data[m_next++];
1374 }
1375 
1376 uint32_t
1378 {
1379  return (uint32_t)GetValue ();
1380 }
1381 
1383 
1384 // ValueCDF methods
1386  : value (0.0),
1387  cdf (0.0)
1388 {
1389 }
1391  : value (v),
1392  cdf (c)
1393 {
1394 }
1396  : value (c.value),
1397  cdf (c.cdf)
1398 {
1399 }
1400 
1401 TypeId
1403 {
1404  static TypeId tid = TypeId ("ns3::EmpiricalRandomVariable")
1406  .AddConstructor<EmpiricalRandomVariable> ()
1407  ;
1408  return tid;
1409 }
1411  :
1412  validated (false)
1413 {
1414 }
1415 
1416 double
1418 {
1419  // Return a value from the empirical distribution
1420  // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
1421  if (emp.size () == 0)
1422  {
1423  return 0.0; // HuH? No empirical data
1424  }
1425  if (!validated)
1426  {
1427  Validate (); // Insure in non-decreasing
1428  }
1429 
1430  // Get a uniform random variable in [0,1].
1431  double r = Peek ()->RandU01 ();
1432  if (IsAntithetic ())
1433  {
1434  r = (1 - r);
1435  }
1436 
1437  if (r <= emp.front ().cdf)
1438  {
1439  return emp.front ().value; // Less than first
1440  }
1441  if (r >= emp.back ().cdf)
1442  {
1443  return emp.back ().value; // Greater than last
1444  }
1445  // Binary search
1446  std::vector<ValueCDF>::size_type bottom = 0;
1447  std::vector<ValueCDF>::size_type top = emp.size () - 1;
1448  while (1)
1449  {
1450  std::vector<ValueCDF>::size_type c = (top + bottom) / 2;
1451  if (r >= emp[c].cdf && r < emp[c + 1].cdf)
1452  { // Found it
1453  return Interpolate (emp[c].cdf, emp[c + 1].cdf,
1454  emp[c].value, emp[c + 1].value,
1455  r);
1456  }
1457  // Not here, adjust bounds
1458  if (r < emp[c].cdf)
1459  {
1460  top = c - 1;
1461  }
1462  else
1463  {
1464  bottom = c + 1;
1465  }
1466  }
1467 }
1468 
1469 uint32_t
1471 {
1472  return (uint32_t)GetValue ();
1473 }
1474 
1475 void EmpiricalRandomVariable::CDF (double v, double c)
1476 { // Add a new empirical datapoint to the empirical cdf
1477  // NOTE. These MUST be inserted in non-decreasing order
1478  emp.push_back (ValueCDF (v, c));
1479 }
1480 
1482 {
1483  ValueCDF prior;
1484  for (std::vector<ValueCDF>::size_type i = 0; i < emp.size (); ++i)
1485  {
1486  ValueCDF& current = emp[i];
1487  if (current.value < prior.value || current.cdf < prior.cdf)
1488  { // Error
1489  std::cerr << "Empirical Dist error,"
1490  << " current value " << current.value
1491  << " prior value " << prior.value
1492  << " current cdf " << current.cdf
1493  << " prior cdf " << prior.cdf << std::endl;
1494  NS_FATAL_ERROR ("Empirical Dist error");
1495  }
1496  prior = current;
1497  }
1498  validated = true;
1499 }
1500 
1501 double EmpiricalRandomVariable::Interpolate (double c1, double c2,
1502  double v1, double v2, double r)
1503 { // Interpolate random value in range [v1..v2) based on [c1 .. r .. c2)
1504  return (v1 + ((v2 - v1) / (c2 - c1)) * (r - c1));
1505 }
1506 
1507 } // namespace ns3