randomgenerator.cpp
1 /********************************************************************************
2  * FARSA Genetic Algorithm Library *
3  * Copyright (C) 2007-2008 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #include "randomgenerator.h"
21 #include <cmath>
22 #include <cstdlib>
23 
24 #ifdef FARSA_USE_GSL
25  #include "gsl/gsl_rng.h"
26  #include "gsl/gsl_randist.h"
27 #endif
28 
29 namespace farsa {
30 
31 class FARSA_UTIL_INTERNAL RandomGeneratorPrivate {
32 public:
33 #ifdef FARSA_USE_GSL
34  gsl_rng* rng;
36  rng = gsl_rng_alloc( gsl_rng_taus2 );
37  };
39  gsl_rng_free( rng );
40  };
41 #else
43  spare(0.0),
44  isSpareReady(false)
45  {
46  }
47 
48  double spare;
49  bool isSpareReady;
50 #endif
51 };
52 
54  prive = new RandomGeneratorPrivate();
55 #ifdef FARSA_USE_GSL
56  gsl_rng_set( prive->rng, seed );
57 #else
58  srand((unsigned int)seed);
59 #endif
60 }
61 
63  delete prive;
64 }
65 
66 void RandomGenerator::setSeed( int seed ) {
67  this->seedv = seed;
68 #ifdef FARSA_USE_GSL
69  gsl_rng_set( prive->rng, seed );
70 #else
71  srand((unsigned int)seed);
72 #endif
73 }
74 
76  return seedv;
77 }
78 
79 bool RandomGenerator::getBool( double trueProbability ) {
80 #ifdef FARSA_USE_GSL
81  return ( gsl_rng_uniform( prive->rng ) < trueProbability );
82 #else
83  return ( ( double( rand() ) / double( RAND_MAX ) ) < trueProbability );
84 #endif
85 }
86 
87 int RandomGenerator::getInt( int min, int max ) {
88 #ifdef FARSA_USE_GSL
89  return ( gsl_rng_uniform_int( prive->rng, qAbs( max-min )+1 ) + min );
90 #else
91  return ( min + ( rand() % ( max-min ) ) );
92 #endif
93 }
94 
95 double RandomGenerator::getDouble( double min, double max ) {
96 #ifdef FARSA_USE_GSL
97  //--- FIXME this implementation never return max
98  return gsl_ran_flat( prive->rng, min, max );
99 #else
100  return ( min + ( double( rand() ) / double( RAND_MAX ) ) * ( max - min ) );
101 #endif
102 }
103 
104 double RandomGenerator::getGaussian( double var, double mean ) {
105 #ifdef FARSA_USE_GSL
106  return gsl_ran_gaussian( prive->rng, var ) + mean;
107 #else
108  // Using Marsaglia polar method to convert uniform random numbers to gaussian. Implementation
109  // adapted from http://en.wikipedia.org/wiki/Marsaglia_polar_method#Implementation
110 
111  const double stdDev = sqrt(var);
112  if (prive->isSpareReady) {
113  prive->isSpareReady = false;
114  return prive->spare * stdDev + mean;
115  } else {
116  double u, v, s;
117  do {
118  u = (double(rand()) / double(RAND_MAX)) * 2.0 - 1.0;
119  v = (double(rand()) / double(RAND_MAX)) * 2.0 - 1.0;
120  s = u * u + v * v;
121  } while (s >= 1.0 || s == 0.0);
122 
123  const double mul = sqrt(-2.0 * log(s) / s);
124  prive->spare = v * mul;
125  prive->isSpareReady = true;
126  return mean + stdDev * u * mul;
127  }
128 #endif
129 }
130 
131 } // end namespace farsa