00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef GRAPHLAB_RANDOM_HPP
00019 #define GRAPHLAB_RANDOM_HPP
00020
00021 #include <cstdlib>
00022 #include <stdint.h>
00023
00024
00025 #include <vector>
00026 #include <limits>
00027 #include <algorithm>
00028
00029 #include <boost/random.hpp>
00030 #include <graphlab/util/timer.hpp>
00031 #include <graphlab/parallel/pthread_tools.hpp>
00032
00033 namespace graphlab {
00034
00035
00036
00037
00038
00039
00040
00041 namespace random {
00042
00043
00044
00045
00046
00047
00048
00049 namespace distributions {
00050
00051
00052
00053
00054
00055
00056
00057 template<typename IntType>
00058 struct uniform {
00059 typedef boost::uniform_int<IntType> distribution_type;
00060 template<typename RealRNG, typename DiscreteRNG>
00061 static inline IntType sample(RealRNG& real_rng,
00062 DiscreteRNG& discrete_rng,
00063 const IntType& min, const IntType& max) {
00064 return distribution_type(min, max)(discrete_rng);
00065 }
00066 };
00067 template<>
00068 struct uniform<double> {
00069 typedef boost::uniform_real<double> distribution_type;
00070 template<typename RealRNG, typename DiscreteRNG>
00071 static inline double sample(RealRNG& real_rng,
00072 DiscreteRNG& discrete_rng,
00073 const double& min, const double& max) {
00074 return distribution_type(min, max)(real_rng);
00075 }
00076 };
00077 template<>
00078 struct uniform<float> {
00079 typedef boost::uniform_real<float> distribution_type;
00080 template<typename RealRNG, typename DiscreteRNG>
00081 static inline float sample(RealRNG& real_rng,
00082 DiscreteRNG& discrete_rng,
00083 const float& min, const float& max) {
00084 return distribution_type(min, max)(real_rng);
00085 }
00086 };
00087
00088 };
00089
00090
00091
00092
00093
00094
00095 class generator {
00096 public:
00097
00098 typedef boost::lagged_fibonacci607 real_rng_type;
00099 typedef boost::mt11213b discrete_rng_type;
00100 typedef boost::rand48 fast_discrete_rng_type;
00101
00102
00103 inline void seed() {
00104 mut.lock();
00105 real_rng.seed();
00106 discrete_rng.seed();
00107 fast_discrete_rng.seed();
00108 mut.unlock();
00109 }
00110
00111
00112 void nondet_seed();
00113
00114
00115
00116 inline void time_seed() {
00117 seed( graphlab::timer::usec_of_day() );
00118 }
00119
00120
00121 void seed(size_t number) {
00122 mut.lock();
00123 fast_discrete_rng.seed(number);
00124 real_rng.seed(fast_discrete_rng);
00125 discrete_rng.seed(fast_discrete_rng);
00126 mut.unlock();
00127 }
00128
00129
00130 void seed(generator& other){
00131 mut.lock();
00132 real_rng.seed(other.real_rng);
00133 discrete_rng.seed(other.discrete_rng);
00134 fast_discrete_rng.seed(other.fast_discrete_rng());
00135 mut.unlock();
00136 }
00137
00138
00139
00140
00141
00142 template<typename NumType>
00143 inline NumType uniform(const NumType min, const NumType max) {
00144 mut.lock();
00145 const NumType result = distributions::uniform<NumType>::
00146 sample(real_rng, discrete_rng, min, max);
00147 mut.unlock();
00148 return result;
00149 }
00150
00151
00152
00153
00154
00155 template<typename NumType>
00156 inline NumType fast_uniform(const NumType min, const NumType max) {
00157 mut.lock();
00158 const NumType result = distributions::uniform<NumType>::
00159 sample(real_rng, fast_discrete_rng, min, max);
00160 mut.unlock();
00161 return result;
00162 }
00163
00164
00165
00166
00167
00168
00169 inline double gamma(const double alpha = double(1)) {
00170 boost::gamma_distribution<double> gamma_dist(alpha);
00171 mut.lock();
00172 const double result = gamma_dist(real_rng);
00173 mut.unlock();
00174 return result;
00175 }
00176
00177
00178
00179
00180
00181 inline double gaussian(const double mean = double(0),
00182 const double var = double(1)) {
00183 boost::normal_distribution<double> normal_dist(mean,var);
00184 mut.lock();
00185 const double result = normal_dist(real_rng);
00186 mut.unlock();
00187 return result;
00188 }
00189
00190 inline bool bernoulli(const double p = double(0.5)) {
00191 boost::bernoulli_distribution<double> dist(p);
00192 mut.lock();
00193 const double result(dist(discrete_rng));
00194 mut.unlock();
00195 return result;
00196 }
00197
00198 inline bool fast_bernoulli(const double p = double(0.5)) {
00199 boost::bernoulli_distribution<double> dist(p);
00200 mut.lock();
00201 const double result(dist(fast_discrete_rng));
00202 mut.unlock();
00203 return result;
00204 }
00205
00206
00207
00208
00209
00210 size_t multinomial(const std::vector<double>& prb) {
00211 ASSERT_GT(prb.size(),0);
00212 if (prb.size() == 1) { return 0; }
00213 double sum(0);
00214 for(size_t i = 0; i < prb.size(); ++i) {
00215 ASSERT_GE(prb[i], 0);
00216 sum += prb[i];
00217 }
00218 ASSERT_GT(sum, 0);
00219
00220 const double rnd(uniform<double>(0,1));
00221 size_t ind = 0;
00222 for(double cumsum(prb[ind]/sum);
00223 rnd > cumsum && (ind+1) < prb.size();
00224 cumsum += (prb[++ind]/sum));
00225 return ind;
00226 }
00227
00228
00229
00230
00231
00232 template<typename T>
00233 void shuffle(std::vector<T>& vec) { shuffle(vec.begin(), vec.end()); }
00234
00235
00236
00237
00238 template<typename Iterator>
00239 void shuffle(Iterator begin, Iterator end) {
00240 mut.lock();
00241 shuffle_functor functor(*this);
00242 std::random_shuffle(begin, end, functor);
00243 mut.unlock();
00244 }
00245
00246 private:
00247
00248
00249 struct shuffle_functor {
00250 generator& gen;
00251 inline shuffle_functor(generator& gen) : gen(gen) { }
00252 inline std::ptrdiff_t operator()(std::ptrdiff_t end) {
00253 return distributions::uniform<ptrdiff_t>::
00254 sample(gen.real_rng, gen.fast_discrete_rng, 0, end-1);
00255 }
00256 };
00257
00258
00259
00260 real_rng_type real_rng;
00261
00262 discrete_rng_type discrete_rng;
00263
00264 fast_discrete_rng_type fast_discrete_rng;
00265
00266 mutex mut;
00267 };
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 void seed();
00288
00289
00290
00291
00292
00293 void seed(size_t seed_value);
00294
00295
00296
00297
00298
00299 void nondet_seed();
00300
00301
00302
00303
00304
00305 void time_seed();
00306
00307
00308
00309
00310
00311
00312 generator& get_source();
00313
00314
00315
00316
00317
00318
00319 template<typename NumType>
00320 inline NumType uniform(const NumType min, const NumType max) {
00321 return get_source().uniform<NumType>(min, max);
00322 }
00323
00324
00325
00326
00327
00328
00329 template<typename NumType>
00330 inline NumType fast_uniform(const NumType min, const NumType max) {
00331 return get_source().fast_uniform<NumType>(min, max);
00332 }
00333
00334
00335
00336
00337
00338 inline double rand01() { return uniform<double>(0, 1); }
00339
00340
00341
00342
00343
00344 inline int rand() { return fast_uniform(0, RAND_MAX); }
00345
00346
00347
00348
00349
00350
00351 inline double gamma(const double alpha = double(1)) {
00352 return get_source().gamma(alpha);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362 inline double gaussian(const double mean = double(0),
00363 const double var = double(1)) {
00364 return get_source().gaussian(mean, var);
00365 }
00366
00367
00368
00369
00370
00371 inline bool bernoulli(const double p = double(0.5)) {
00372 return get_source().bernoulli(p);
00373 }
00374
00375
00376
00377
00378
00379 inline bool fast_bernoulli(const double p = double(0.5)) {
00380 return get_source().fast_bernoulli(p);
00381 }
00382
00383
00384
00385
00386
00387
00388 inline size_t multinomial(const std::vector<double>& prb) {
00389 return get_source().multinomial(prb);
00390 }
00391
00392
00393
00394
00395
00396
00397 template<typename T>
00398 void shuffle(std::vector<T>& vec) {
00399 get_source().shuffle(vec);
00400 }
00401
00402
00403
00404
00405
00406 template<typename Iterator>
00407 void shuffle(Iterator begin, Iterator end) {
00408 get_source().shuffle(begin, end);
00409 }
00410
00411 };
00412 };
00413
00414
00415 #endif
00416