Virtual Belgium  2.0
A micro-simulation platform for the Belgian population
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
Random.hpp
Go to the documentation of this file.
1 /****************************************************************
2  * RANDOM.HPP
3  *
4  * This file contains random number generators related functions.
5  *
6  * Authors: J. Barthelemy
7  * Date : 17 july 2012
8  ****************************************************************/
9 
14 #ifndef RANDOM_HPP_
15 #define RANDOM_HPP_
16 
17 #include <iostream>
18 #include <vector>
19 #include <cmath>
20 #include <stdexcept>
21 
22 
24 typedef struct draw_2d draw_2d;
25 struct draw_2d {
26 
27  float x1;
28  float x2;
29 
31  draw_2d(float aX1, float aX2) : x1(aX1), x2(aX2) {};
32 
33 };
34 
35 
37 
41 typedef struct dist_param dist_param;
42 struct dist_param {
43  float mu;
44  float sigma;
45  float max;
46 };
47 
48 
50 
56  std::vector<float> mu;
57  std::vector<float> sigma;
58  std::vector<float> p;
59  float max;
60  float min;
61 };
62 
63 
65 
70 struct dist_param_2d {
71  float mu[2];
72  float sigma[3];
73 };
74 
75 
77 
84  std::vector<dist_param_2d > components;
85  std::vector<float> p;
86  float min[2];
87  float max[2];
88 };
89 
91 
94 struct Ranq1 {
95 
96  unsigned long long v;
97 
99 
102  Ranq1( unsigned long long j) : v(4101842887655102017LL) {
103  v ^= j;
104  v = int64();
105  }
106 
108 
111  inline unsigned long long int64() {
112  v ^= v >> 21;
113  v ^= v << 35;
114  v ^= 4;
115  return v * 2685821657736338717LL;
116  }
117 
119 
122  inline double doub() {
123  return 5.42101086242752217E-20 * int64();
124  }
125 
127 
130  inline float fl() {
131  return (float)doub();
132  }
133 
135 
138  inline unsigned int int32() {
139  return (unsigned int)int64();
140  }
141 
142 };
143 
144 
146 
150 struct Ranfib {
151 
152  double dtab[55];
153  double dd;
154  int inext;
155  int inextp;
156 
158 
161  Ranfib( unsigned long j ) : inext(0), inextp(31) {
162 
163  dd = 0.0;
164 
165  // Using Ranq1 for initialization.
166  Ranq1 init(j);
167 
168  for( int k = 0; k < 55; k++) {
169  dtab[k] = init.doub();
170  }
171 
172  }
173 
175 
178  inline double doub() {
179 
180  if( ++inext == 55 ) inext = 0;
181  if( ++inextp == 55 ) inextp = 0;
182  dd = dtab[inext] - dtab[inextp];
183  if( dd < 0 ) dd += 1.0;
184  return ( dtab[inext] = dd );
185 
186  }
187 
189 
192  inline float fl() {
193  return (float)doub();
194  }
195 
196 };
197 
199 struct Normaldev : Ranfib {
200 
202 
205  Normaldev(unsigned long long i) : Ranfib(i) {};
206 
208 
214  inline float dev(double mu, double sigma) {
215 
216  float u, v, x, y, q;
217 
218  do {
219  u = fl();
220  v = 1.7156 * ( fl() - 0.5 );
221  x = u - 0.449871;
222  y = abs(v) + 0.386595;
223  q = x * x + y * ( 0.19600 * y - 0.25472 * x );
224  } while ( q > 0.27597 && ( q > 0.27846 || v * v > -4.0 * log(u) * u * u ) );
225 
226  return mu + sigma * v / u;
227 
228  }
229 
231 
238  inline float dev(double mu, double sigma, float max) {
239 
240  float result;
241 
242  do {
243  result = dev(mu, sigma);
244  } while ( result > max );
245  return result;
246 
247  }
248 
250 
258  inline float dev(double mu, double sigma, float min, float max) {
259 
260  float result;
261 
262  do {
263  result = dev(mu, sigma);
264  } while ( result > max || result < min );
265  return result;
266 
267  }
268 
269 
270 };
271 
274 
276 
279  LogNormaldev(unsigned long long i) : Ranfib(i) {};
280 
282 
288  inline float dev(double mu, double sigma) {
289 
290  float u, v, x, y, q;
291 
292  // normal draw
293  do {
294  u = fl();
295  v = 1.7156 * ( fl() - 0.5 );
296  x = u - 0.449871;
297  y = abs(v) + 0.386595;
298  q = x * x + y * ( 0.19600 * y - 0.25472 * x );
299  } while ( q > 0.27597 && ( q > 0.27846 || v * v > -4.0 * log(u) * u * u ) );
300 
301  return exp(mu + sigma * v / u);
302 
303  }
304 
306 
313  inline float dev(double mu, double sigma, float max) {
314 
315  float result;
316 
317  do {
318  result = dev(mu, sigma);
319  } while ( result > max );
320  return result;
321 
322  }
323 
325 
333  inline float dev(double mu, double sigma, float min, float max) {
334 
335  float result;
336 
337  do {
338  result = dev(mu, sigma);
339  } while ( result > max || result < min );
340  return result;
341 
342  }
343 
344 
345 };
346 
349 
351  MixtureNormal(unsigned long long i) : Normaldev(i) {};
352 
354 
361  inline float dev(std::vector<float> mu, std::vector<float> sigma, std::vector<float> p) {
362 
363  float a_p, prop_cum;
364  int comp;
365  float u, v, x, y, q;
366 
367  // looking for the right component of the mixture
368  a_p = fl();
369  comp = 0;
370  prop_cum = p[comp];
371  while( prop_cum < a_p ) {
372  comp++; // moving to the next component
373  prop_cum = prop_cum + p[comp]; // computation of the cumulative proportion
374  }
375 
376  // normal draw
377  do {
378  u = fl();
379  v = 1.7156 * ( fl() - 0.5 );
380  x = u - 0.449871;
381  y = abs(v) + 0.386595;
382  q = x * x + y * ( 0.19600 * y - 0.25472 * x );
383  } while ( q > 0.27597 && ( q > 0.27846 || v * v > -4.0 * log(u) * u * u ) );
384 
385  return (mu[comp] + sigma[comp] * v / u);
386 
387  }
388 
390 
398  inline float dev( std::vector<float> mu, std::vector<float> sigma, std::vector<float> p, float max) {
399 
400  float result;
401 
402  do {
403  result = dev(mu, sigma, p);
404  std::cout << "TEST MIXTURE NORM " << result << std::endl;
405  } while ( result > max );
406  return result;
407 
408  }
409 
411 
420  inline float dev( std::vector<float> mu, std::vector<float> sigma, std::vector<float> p, float min, float max) {
421 
422  float result;
423 
424  do {
425  result = dev(mu, sigma, p);
426  //std::cout << "TEST MIXTURE NORM " << result << " MIN "<< min << " MAX " << max << std::endl;
427  } while ( result > max || result < min );
428  return result;
429 
430  }
431 
432 };
433 
436 
438  MixtureLogNormal(unsigned long long i) : LogNormaldev(i) {};
439 
441 
448  inline float dev(std::vector<float> mu, std::vector<float> sigma, std::vector<float> p) {
449 
450  float a_p, prop_cum;
451  int comp;
452  float u, v, x, y, q;
453 
454  // looking for the right component of the mixture
455  a_p = fl();
456  comp = 0;
457  prop_cum = p[comp];
458  while( prop_cum < a_p ) {
459  comp++; // moving to the next component
460  prop_cum = prop_cum + p[comp]; // computation of the cumulative proportion
461  }
462 
463  // log-normal draw
464  do {
465  u = doub();
466  v = 1.7156 * ( fl() - 0.5 );
467  x = u - 0.449871;
468  y = abs(v) + 0.386595;
469  q = x * x + y * ( 0.19600 * y - 0.25472 * x );
470  } while ( q > 0.27597 && ( q > 0.27846 || v * v > -4.0 * log(u) * u * u ) );
471 
472  return exp(mu[comp] + sigma[comp] * v / u);
473 
474  }
475 
477 
485  inline float dev( std::vector<float> mu, std::vector<float> sigma, std::vector<float> p, float max) {
486 
487  float result;
488 
489  do {
490  result = dev(mu, sigma, p);
491  } while ( result > max );
492  return result;
493 
494  }
495 
497 
506  inline float dev( std::vector<float> mu, std::vector<float> sigma, std::vector<float> p, float min, float max) {
507 
508  float result;
509 
510  do {
511  result = dev(mu, sigma, p);
512  } while ( result > max || result < min );
513  return result;
514 
515  }
516 
517 };
518 
519 
522 
524  MixtureLogNormal2D(unsigned long long i) : Normaldev(i) {};
525 
528 
529  float a_p, prop_cum;
530  int comp;
531  draw_2d result(0.0,0.0);
532 
533  // looking for the right component of the mixture
534  a_p = fl();
535  comp = 0;
536  prop_cum = distrib.p[comp];
537  while( prop_cum < a_p ) {
538  comp++; // moving to the next component
539  prop_cum = prop_cum + distrib.p[comp]; // computation of the cumulative proportion
540  }
541 
542  do {
543 
544  result.x1 = Normaldev::dev(0,1);
545  result.x2 = Normaldev::dev(0,1);
546 
547  // generating the draws
548  result.x1 = exp(distrib.components[comp].mu[0] + distrib.components[comp].sigma[0] * result.x1 + distrib.components[comp].sigma[1] * result.x2);
549  result.x2 = exp(distrib.components[comp].mu[1] + distrib.components[comp].sigma[2] * result.x2);
550 
551  } while (result.x1 > distrib.max[0] || result.x2 > distrib.max[1] );
552 
553  return result;
554 
555  }
556 
557 };
558 
560 template <typename T>
562 
563 protected:
564 
567 
570 
571 public:
572 
574 
577  static void makeInstance ( unsigned long long i ) {
578  if (nullptr == _singleton) {
579  _singleton = new T(i);
580  }
581  }
582 
584 
587  static T *getInstance () {
588  if (nullptr == _singleton) {
589  std::cerr << "No instance already created!" << std::endl;
590  }
591  return (static_cast<T*> (_singleton));
592  }
593 
595  static void kill () {
596  if (nullptr != _singleton) {
597  delete _singleton;
598  _singleton = nullptr;
599  }
600  }
601 
602 private:
603 
604  static T *_singleton;
605 
606 };
607 
609 template <typename T>
610 T *SingletonRnd<T>::_singleton = nullptr;
611 
613 
616 class RandomGenerators : public SingletonRnd<RandomGenerators> {
617 
619 
620 public:
621 
629 
631 
634  RandomGenerators(unsigned long long i) : unif(i + 10000), fast_unif(i+10), norm_dev(i + 100), lognorm_dev(i + 1000),
635  mixt_norm_dev(i + 10000), mixt_lognorm_dev(i + 100000), mixt_lognorm_dev_2d(i + 1000000) {};
636 
638  virtual ~RandomGenerators() {};
639 
640 };
641 
643 
647 template <typename T> int draw_discrete(std::vector<T> freq) {
648 
649  if( freq.size() < 1 ) throw std::logic_error( "draw_discrete: empty vector!" );
650 
651  int N = freq.size(); // size of freq
652  double cumfreq [N]; // cumulative distribution
653  double draw; // random draw
654  double icum; // cumulative total
655  double low; // lower bound
656  int i;
657 
658  // Build the cumulative distribution.
659 
660  icum = 0.0;
661  for( i = 0; i < N; i++ ) {
662  icum=icum+freq[i];
663  cumfreq[i]=icum;
664  }
665 
666  // ... distribution is non-trivial
667  if(icum>0.0) {
668  for(i=0;i<N;i++) {
669  cumfreq[i]=cumfreq[i]/icum;
670  }
671  }
672  // ... distribution is trivial
673  else {
674  for(i=0;i<N;i++) {
675  cumfreq[i]=(i+1.0)/(N+1.0);
676  }
677  }
678 
679  // Draw a random number between 0 and 1.
680 
682 
683  // Find the interval in which this number falls
684  // and return the associated class identifier.
685 
686  low = 0.0;
687  for ( i = 0; i < N; i++ ) {
688  if ( (low <= draw) && (draw <= cumfreq[i]) ) {
689  return i;
690  }
691  low = cumfreq[i];
692  }
693 
694  std::cerr << "Could not find a class identifier!" << std::endl;
695  return -1;
696 
697 }
698 
699 
701 
708 template <typename T> int draw_discrete( std::vector<T> freq, int lo_bound, int up_bound ) {
709 
710  int N = ( up_bound - lo_bound ) + 1; // compute the size of the interval
711  double cumfreq [N]; // cumulative distribution
712  double draw; // random draw
713  double icum;
714  double low;
715  int i, j;
716 
717  // Build the cumulative distribution.
718 
719  icum = 0;
720  j = 0;
721  for( i = lo_bound; i <= up_bound; i++ ) {
722  icum=icum+freq[i];
723  cumfreq[j]=icum;
724  j++;
725  }
726 
727  // ... distribution is non-trivial
728  if(icum>0) {
729  for(i = 0; i < N; i++ ) {
730  cumfreq[i]=cumfreq[i]/icum;
731  }
732  }
733  // ... distribution is trivial
734  else {
735  std::cout << "Error: trivial distribution" << std::endl;
736  for( i = 0; i < N; i++ ) {
737  cumfreq[i]=(i+1)/(N+1);
738  }
739  }
740 
741  // Draw a random number between 0 and 1.
742 
744 
745  // Find the interval in which this number falls
746  // and return the associated class identifier.
747 
748  low = 0.0;
749  for ( i = 0; i < N; i++ ) {
750  if ( (low <= draw) && (draw <= cumfreq[i]) ) {
751  return i + lo_bound;
752  }
753  low = cumfreq[i];
754  }
755 
756  std::cerr << "Could not find a class identifier!" << std::endl;
757  return -1;
758 
759 }
760 
762 // Functions below are depreciated!
764 
766 /*
767  \param mu mean of the distribution
768  \param sigma standard deviation of the distribution
769 
770  \return a float randomly generated
771  */
772 float norm_rand( float mu, float sigma );
773 
775 /*
776  \param mu mean of the distribution
777  \param sigma standard deviation of the distribution
778  \param max the upper bound of the distribution
779 
780  \return a float randomly generated
781  */
782 
783 float norm_rand( float mu, float sigma, float max );
784 
786 /*
787  \param mu mean of the distribution
788  \param sigma standard deviation of the distribution
789 
790  \return a float randomly generated
791  */
792 float log_rand( float mu, float sigma );
793 
795 /*
796  \param mu mean of the distribution
797  \param sigma standard deviation of the distribution
798  \param max the upper bound of the distribution
799 
800  \return a float randomly generated
801  */
802 float log_rand( float mu, float sigma, float max );
803 
805 
806 #endif /* RANDOM_HPP_ */
Simplest and fastest random number generator recommended by Numerical Recipes.
Definition: Random.hpp:94
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p, float max)
Returns a draw from the mixture distribution.
Definition: Random.hpp:398
RandomGenerators(unsigned long long i)
Constructor, initialize every random number generators.
Definition: Random.hpp:634
float x2
second component
Definition: Random.hpp:28
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p, float min, float max)
Returns a draw from the mixture distribution.
Definition: Random.hpp:420
Definition: Random.hpp:83
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p, float max)
Returns a draw from the mixture distribution.
Definition: Random.hpp:485
draw_2d(float aX1, float aX2)
Constructor.
Definition: Random.hpp:31
double doub()
Returns random double-precision floating point value in [0,1].
Definition: Random.hpp:178
SingletonRnd class for the RandomGenerators class.
Definition: Random.hpp:561
LogNormaldev lognorm_dev
log-normal random draws
Definition: Random.hpp:625
static T * getInstance()
Return the instance of SingletonRnd if already generated.
Definition: Random.hpp:587
double doub()
Generates a double.
Definition: Random.hpp:122
Ranq1 unif
uniform random draws
Definition: Random.hpp:622
draw_2d dev(dist_param_mixture_2d distrib)
Returns 2 draws from a bounded mixture distribution.
Definition: Random.hpp:527
SingletonRnd()
Constructor.
Definition: Random.hpp:566
float mu[2]
mean of the distribution
Definition: Random.hpp:71
Ranfib fast_unif
fast uniform random draws
Definition: Random.hpp:623
static void makeInstance(unsigned long long i)
Create a singleton instance of a T object.
Definition: Random.hpp:577
MixtureLogNormal2D(unsigned long long i)
Constructor.
Definition: Random.hpp:524
Normaldev norm_dev
normal random draws
Definition: Random.hpp:624
float sigma[3]
covariance matrix or its choleski decomposition
Definition: Random.hpp:72
int inext
part of the generator state
Definition: Random.hpp:154
int draw_discrete(std::vector< T > freq)
Randomly draws a class identifier within an empirical density function.
Definition: Random.hpp:647
float min[2]
vector of lower bounds
Definition: Random.hpp:86
MixtureLogNormal mixt_lognorm_dev
mixture of univariate log-normal random draws
Definition: Random.hpp:627
float max
upper bound of the distribution
Definition: Random.hpp:45
float dev(double mu, double sigma)
Returns a normal random draw with mean mu and standart deviation sigma.
Definition: Random.hpp:214
Ranfib(unsigned long j)
Constructor.
Definition: Random.hpp:161
float dev(double mu, double sigma, float max)
Returns a upper bounded normal random draw.
Definition: Random.hpp:238
float x1
first component
Definition: Random.hpp:27
MixtureLogNormal2D mixt_lognorm_dev_2d
mixture of bivariate log-normal random draws
Definition: Random.hpp:628
float dev(double mu, double sigma)
Returns a Log-normal random draw.
Definition: Random.hpp:288
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p, float min, float max)
Returns a draw from the mixture distribution.
Definition: Random.hpp:506
unsigned int int32()
Generates an unsigned 32 bits integer.
Definition: Random.hpp:138
float mu
mean of the distribution
Definition: Random.hpp:43
Fast and good random number generator (see Numerical Recipes).
Definition: Random.hpp:150
float fl()
Generates a float.
Definition: Random.hpp:130
float norm_rand(float mu, float sigma)
Random number generator following a normal distribution (DEPRECIATED)
Definition: Random.cpp:14
float dev(double mu, double sigma, float min, float max)
Returns a bounded Log-normal random draw.
Definition: Random.hpp:333
float max
upper bound of the distribution
Definition: Random.hpp:59
Fast Random number generator for log-normal distribution (Numerical Recipes).
Definition: Random.hpp:273
MixtureLogNormal(unsigned long long i)
Constructor.
Definition: Random.hpp:438
Definition: Random.hpp:55
Fast Random number generator for normal distribution (Numerical Recipes).
Definition: Random.hpp:199
unsigned long long v
state of the random number generator
Definition: Random.hpp:96
Fast Random number generator for mixture of bivariate log-normal distribution (Numerical Recipes)...
Definition: Random.hpp:521
double dd
part of the generator state
Definition: Random.hpp:153
float fl()
Returns random simple-precision floating point value in [0,1].
Definition: Random.hpp:192
Definition: Random.hpp:70
std::vector< float > p
mixing proportions of each components
Definition: Random.hpp:85
Random generators.
Definition: Random.hpp:616
static T * _singleton
unique instance of the RandomGenerators class
Definition: Random.hpp:604
MixtureNormal mixt_norm_dev
mixture of univariate normal random draws
Definition: Random.hpp:626
LogNormaldev(unsigned long long i)
Constructor.
Definition: Random.hpp:279
std::vector< float > p
proportions of each components
Definition: Random.hpp:58
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p)
Returns a draw from the mixture distribution.
Definition: Random.hpp:448
unsigned long long int64()
Generates an unsigned 64 bits integer.
Definition: Random.hpp:111
Definition: Random.hpp:25
virtual ~RandomGenerators()
Destructor.
Definition: Random.hpp:638
std::vector< dist_param_2d > components
vector storing the mixture's components
Definition: Random.hpp:84
~SingletonRnd()
Destructor.
Definition: Random.hpp:569
std::vector< float > sigma
vector storing the standard error of each component
Definition: Random.hpp:57
int inextp
part of the generator state
Definition: Random.hpp:155
float dev(double mu, double sigma, float max)
Returns a bounded Log-normal random draw.
Definition: Random.hpp:313
float dev(double mu, double sigma, float min, float max)
Returns a bounded normal random draw.
Definition: Random.hpp:258
Normaldev(unsigned long long i)
Constructor.
Definition: Random.hpp:205
std::vector< float > mu
vector storing the mean of each component
Definition: Random.hpp:56
float sigma
standard error of the distribution
Definition: Random.hpp:44
float log_rand(float mu, float sigma)
Random number generator following a log-normal distribution (DEPRECIATED)
Definition: Random.cpp:43
Fast Random number generator for mixture of log-normal distribution (Numerical Recipes).
Definition: Random.hpp:435
Fast Random number generator for mixture of normal distribution (Numerical Recipes).
Definition: Random.hpp:348
Ranq1(unsigned long long j)
Constructor j is the seed.
Definition: Random.hpp:102
static void kill()
Killing the instance and freeing memory.
Definition: Random.hpp:595
Definition: Random.hpp:42
double dtab[55]
part of the generator state
Definition: Random.hpp:152
float max[2]
vector of upper bounds
Definition: Random.hpp:87
MixtureNormal(unsigned long long i)
Constructor.
Definition: Random.hpp:351
float dev(std::vector< float > mu, std::vector< float > sigma, std::vector< float > p)
Returns a draw from the mixture distribution.
Definition: Random.hpp:361
float min
lower bound of the distribution
Definition: Random.hpp:60