00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef RandomGenerator_H
00029 #define RandomGenerator_H
00030
00031 #include <mrpt/utils/utils_defs.h>
00032 #include <mrpt/math/CMatrixTemplateNumeric.h>
00033 #include <mrpt/math/ops_matrices.h>
00034
00035 namespace mrpt
00036 {
00037
00038
00039 namespace random
00040 {
00041 using namespace mrpt::utils;
00042 using namespace mrpt::math;
00043
00044
00045
00046
00047
00048
00049
00050
00051 class BASE_IMPEXP CRandomGenerator
00052 {
00053 protected:
00054
00055 struct TMT19937_data
00056 {
00057 TMT19937_data() : index(0), seed_initialized(false)
00058 {}
00059 uint32_t MT[624];
00060 uint32_t index;
00061 bool seed_initialized;
00062 } m_MT19937_data;
00063
00064 void MT19937_generateNumbers();
00065 void MT19937_initializeGenerator(const uint32_t &seed);
00066
00067 public:
00068
00069
00070
00071
00072
00073 CRandomGenerator() : m_MT19937_data() { randomize(); }
00074
00075
00076 CRandomGenerator(const uint32_t seed) : m_MT19937_data() { randomize(seed); }
00077
00078 void randomize(const uint32_t seed);
00079 void randomize();
00080
00081
00082
00083
00084
00085
00086
00087
00088 uint32_t drawUniform32bit();
00089
00090
00091 double drawUniform( const double Min, const double Max) {
00092 return Min + (Max-Min)* drawUniform32bit() * 2.3283064370807973754314699618685e-10;
00093 }
00094
00095
00096
00097
00098
00099 template <class MAT>
00100 void drawUniformMatrix(
00101 MAT &matrix,
00102 const double unif_min = 0,
00103 const double unif_max = 1 )
00104 {
00105 for (size_t r=0;r<matrix.getRowCount();r++)
00106 for (size_t c=0;c<matrix.getColCount();c++)
00107 matrix.get_unsafe(r,c) = static_cast<typename MAT::value_type>( drawUniform(unif_min,unif_max) );
00108 }
00109
00110
00111
00112
00113 template <class T>
00114 void drawUniformVector(
00115 std::vector<T> & v,
00116 const double unif_min = 0,
00117 const double unif_max = 1 )
00118 {
00119 const size_t N = v.size();
00120 for (size_t c=0;c<N;c++)
00121 v[c] = static_cast<T>( drawUniform(unif_min,unif_max) );
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 double drawGaussian1D_normalized( double *likelihood = NULL);
00133
00134
00135
00136
00137
00138 double drawGaussian1D( const double mean, const double std ) {
00139 return mean+std*drawGaussian1D_normalized();
00140 }
00141
00142
00143
00144
00145
00146 template <class MAT>
00147 void drawGaussian1DMatrix(
00148 MAT &matrix,
00149 const double mean = 0,
00150 const double std = 1 )
00151 {
00152 for (size_t r=0;r<matrix.getRowCount();r++)
00153 for (size_t c=0;c<matrix.getColCount();c++)
00154 matrix.get_unsafe(r,c) = static_cast<typename MAT::value_type>( drawGaussian1D(mean,std) );
00155 }
00156
00157
00158
00159
00160 template <class T>
00161 void drawGaussian1DVector(
00162 std::vector<T> & v,
00163 const double mean = 0,
00164 const double std = 1 )
00165 {
00166 const size_t N = v.size();
00167 for (size_t c=0;c<N;c++)
00168 v[c] = static_cast<T>( drawGaussian1D(mean,std) );
00169 }
00170
00171
00172
00173
00174
00175
00176 template <typename T>
00177 void drawGaussianMultivariate(
00178 std::vector<T> &out_result,
00179 const CMatrixTemplateNumeric<T> &cov,
00180 const std::vector<T>* mean = NULL
00181 );
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 template <typename VECTORLIKE, typename MATRIXLIKE>
00195 void drawGaussianMultivariateMany(
00196 std::vector< VECTORLIKE > &ret,
00197 size_t desiredSamples,
00198 const MATRIXLIKE &cov,
00199 const VECTORLIKE* mean = NULL,
00200 VECTORLIKE *samplesLikelihoods = NULL)
00201 {
00202 typename VECTORLIKE::iterator liks_it = samplesLikelihoods ? samplesLikelihoods->begin() : typename VECTORLIKE::iterator();
00203 const size_t dim = cov.getColCount();
00204 MATRIXLIKE Z,D;
00205
00206 MRPT_START;
00207
00208 if (samplesLikelihoods)
00209 samplesLikelihoods->assign(desiredSamples, 0);
00210
00211 ret.resize(desiredSamples);
00212 ASSERT_(cov.getRowCount() == cov.getColCount() )
00213
00214 if (mean) ASSERT_(mean->size() == dim )
00215
00216
00217
00218
00219
00220
00221
00222 cov.eigenVectors( Z, D );
00223
00224
00225
00226 for (size_t i=0;i<dim;i++)
00227 {
00228 const typename VECTORLIKE::value_type eig_sqrt = std::sqrt(D.get_unsafe(i,i));
00229 for (size_t j=0;j<dim;j++)
00230 Z.get_unsafe(j,i)*=eig_sqrt;
00231 }
00232
00233 for (typename std::vector<VECTORLIKE>::iterator ret_it=ret.begin();ret_it!=ret.end();ret_it++)
00234 {
00235 size_t i;
00236 double likelihood_1, likelihood_all;
00237
00238
00239 ret_it->assign(dim,0);
00240 likelihood_all = 1.0;
00241
00242 if (samplesLikelihoods)
00243 {
00244
00245
00246 for (i=0;i<dim;i++)
00247 {
00248 const typename VECTORLIKE::value_type rnd = this->drawGaussian1D_normalized(&likelihood_1);
00249 for (size_t d=0;d<dim;d++) (*ret_it)[d]+=Z.get_unsafe(d,i)*rnd;
00250
00251
00252 likelihood_all *= likelihood_1;
00253 }
00254 if (mean)
00255 for (size_t d=0;d<dim;d++) (*ret_it)[d]+=(*mean)[d];
00256
00257
00258 *liks_it = static_cast<typename VECTORLIKE::value_type>(likelihood_all);
00259 liks_it++;
00260 }
00261 else
00262 {
00263
00264
00265 for (i=0;i<dim;i++)
00266 {
00267 const typename VECTORLIKE::value_type rnd = this->drawGaussian1D_normalized();
00268 for (size_t d=0;d<dim;d++) (*ret_it)[d]+=Z.get_unsafe(d,i)*rnd;
00269 }
00270 if (mean)
00271 for (size_t d=0;d<dim;d++) (*ret_it)[d]+=(*mean)[d];
00272 }
00273
00274 }
00275
00276 MRPT_END_WITH_CLEAN_UP( \
00277 printf("\nEXCEPTION: Dumping variables for debuging:\n"); \
00278 std::cout << "Z:\n" << Z << "D:\n" << D << "Cov:\n" << cov; \
00279 try \
00280 {
00281 cov.eigenVectors(Z,D); \
00282 std::cout << "Original Z:" << Z << "Original D:" << D; \
00283 } \
00284 catch(...) {}; \
00285 );
00286
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 template <class VECTORLIKE,typename T,size_t N>
00296 void drawGaussianMultivariate(
00297 VECTORLIKE &out_result,
00298 const CMatrixFixedNumeric<T,N,N> &cov,
00299 const VECTORLIKE* mean = NULL
00300 )
00301 {
00302 if (mean) ASSERT_(mean->size()==N)
00303
00304 CMatrixFixedNumeric<T,N,N> Z,D;
00305
00306
00307 out_result.assign(N,0);
00308
00309
00310
00311
00312
00313
00314 cov.eigenVectors( Z, D );
00315
00316
00317
00318 for (size_t i=0;i<N;i++)
00319 {
00320 const T eig_sqrt = std::sqrt(D.get_unsafe(i,i));
00321 for (size_t j=0;j<N;j++)
00322 Z.get_unsafe(j,i)*=eig_sqrt;
00323 }
00324
00325
00326 for (size_t i=0;i<N;i++)
00327 {
00328 T rnd = drawGaussian1D_normalized();
00329 for (size_t d=0;d<N;d++)
00330 out_result[d]+= ( Z(d,i)* rnd );
00331 }
00332 if (mean)
00333 for (size_t d=0;d<N;d++)
00334 out_result[d]+= (*mean)[d];
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 template <typename T,size_t N>
00344 void drawGaussianMultivariateMany(
00345 std::vector< std::vector<T> > &ret,
00346 size_t desiredSamples,
00347 const CMatrixFixedNumeric<T,N,N> &cov,
00348 const std::vector<T>* mean = NULL )
00349 {
00350 if (mean) ASSERT_(mean->size()==N)
00351
00352 CMatrixFixedNumeric<T,N,N> Z,D;
00353
00354
00355
00356
00357
00358
00359 cov.eigenVectors( Z, D );
00360
00361
00362
00363 for (size_t i=0;i<N;i++)
00364 {
00365 const T eig_sqrt = std::sqrt(D.get_unsafe(i,i));
00366 for (size_t j=0;j<N;j++)
00367 Z.get_unsafe(j,i)*=eig_sqrt;
00368 }
00369
00370
00371 ret.resize(desiredSamples);
00372
00373 for (size_t k=0;k<desiredSamples;k++)
00374 {
00375 ret[k].assign(N,0);
00376 for (size_t i=0;i<N;i++)
00377 {
00378 T rnd = drawGaussian1D_normalized();
00379 for (size_t d=0;d<N;d++)
00380 ret[k][d]+= ( Z.get_unsafe(d,i)* rnd );
00381 }
00382 if (mean)
00383 for (size_t d=0;d<N;d++)
00384 ret[k][d]+= (*mean)[d];
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 template <class T>
00398 void permuteVector(
00399 const std::vector<T> &in_vector,
00400 std::vector<T> &out_result)
00401 {
00402 out_result = in_vector;
00403 std::random_shuffle( out_result.begin(),out_result.end() );
00404 }
00405
00406
00407
00408 };
00409
00410
00411
00412 extern BASE_IMPEXP CRandomGenerator randomGenerator;
00413
00414
00415
00416
00417 inline ptrdiff_t random_generator_for_STL(ptrdiff_t i)
00418 {
00419 return randomGenerator.drawUniform32bit() % i;
00420 }
00421
00422
00423
00424
00425 MRPT_DECLARE_DEPRECATED_FUNCTION("** deprecated **: Use mrpt::random::randomGenerator instead",
00426 double normalizedGaussian( double *likelihood = NULL) );
00427
00428
00429
00430
00431
00432 MRPT_DECLARE_DEPRECATED_FUNCTION("** deprecated **: Use mrpt::random::randomGenerator instead",
00433 double RandomNormal( double mean = 0, double std = 1) );
00434
00435
00436
00437
00438
00439 MRPT_DECLARE_DEPRECATED_FUNCTION("** deprecated **: Use mrpt::random::randomGenerator instead",
00440 uint32_t RandomUniInt() );
00441
00442
00443
00444
00445
00446
00447
00448 MRPT_DECLARE_DEPRECATED_FUNCTION("** deprecated **: Use mrpt::random::randomGenerator instead",
00449 double RandomUni( const double min, const double max) );
00450
00451
00452
00453
00454
00455 template <class MAT>
00456 void matrixRandomUni(
00457 MAT &matrix,
00458 const double unif_min = 0,
00459 const double unif_max = 1 )
00460 {
00461 for (size_t r=0;r<matrix.getRowCount();r++)
00462 for (size_t c=0;c<matrix.getColCount();c++)
00463 matrix.get_unsafe(r,c) = static_cast<typename MAT::value_type>( randomGenerator.drawUniform(unif_min,unif_max) );
00464 }
00465
00466
00467
00468
00469 template <class T>
00470 void vectorRandomUni(
00471 std::vector<T> &v_out,
00472 const T& unif_min = 0,
00473 const T& unif_max = 1 )
00474 {
00475 size_t n = v_out.size();
00476 for (size_t r=0;r<n;r++)
00477 v_out[r] = randomGenerator.drawUniform(unif_min,unif_max);
00478 }
00479
00480
00481
00482
00483
00484 template <class MAT>
00485 void matrixRandomNormal(
00486 MAT &matrix,
00487 const double mean = 0,
00488 const double std = 1 )
00489 {
00490 for (size_t r=0;r<matrix.getRowCount();r++)
00491 for (size_t c=0;c<matrix.getColCount();c++)
00492 matrix.get_unsafe(r,c) = static_cast<typename MAT::value_type>( mean + std*randomGenerator.drawGaussian1D_normalized() );
00493 }
00494
00495
00496
00497
00498 template <class T>
00499 void vectorRandomNormal(
00500 std::vector<T> &v_out,
00501 const T& mean = 0,
00502 const T& std = 1 )
00503 {
00504 size_t n = v_out.size();
00505 for (size_t r=0;r<n;r++)
00506 v_out[r] = mean + std*randomGenerator.drawGaussian1D_normalized();
00507 }
00508
00509
00510
00511
00512 inline void Randomize(const uint32_t seed) {
00513 randomGenerator.randomize(seed);
00514 }
00515 inline void Randomize() {
00516 randomGenerator.randomize();
00517 }
00518
00519
00520
00521 template <class T>
00522 void randomPermutation(
00523 const std::vector<T> &in_vector,
00524 std::vector<T> &out_result)
00525 {
00526 randomGenerator.permuteVector(in_vector,out_result);
00527 }
00528
00529
00530
00531
00532
00533
00534 template <typename T>
00535 void randomNormalMultiDimensional(
00536 const CMatrixTemplateNumeric<T> &cov,
00537 std::vector<T> &out_result)
00538 {
00539 randomGenerator.drawGaussianMultivariate(out_result,cov);
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 template <typename T>
00553 void randomNormalMultiDimensionalMany(
00554 const CMatrixTemplateNumeric<T> &cov,
00555 size_t desiredSamples,
00556 std::vector< std::vector<T> > &ret,
00557 std::vector<T> *samplesLikelihoods = NULL)
00558 {
00559 randomGenerator.drawGaussianMultivariateMany(ret,desiredSamples,cov,static_cast<const std::vector<T>*>(NULL),samplesLikelihoods);
00560 }
00561
00562
00563
00564
00565
00566 template <typename T,size_t N>
00567 void randomNormalMultiDimensionalMany(
00568 const CMatrixFixedNumeric<T,N,N> &cov,
00569 size_t desiredSamples,
00570 std::vector< std::vector<T> > &ret )
00571 {
00572 randomGenerator.drawGaussianMultivariateMany(ret,desiredSamples,cov);
00573 }
00574
00575
00576
00577
00578
00579 template <typename T,size_t N>
00580 void randomNormalMultiDimensional(
00581 const CMatrixFixedNumeric<T,N,N> &cov,
00582 std::vector<T> &out_result)
00583 {
00584 randomGenerator.drawGaussianMultivariate(out_result,cov);
00585 }
00586
00587
00588 }
00589
00590 }
00591
00592 #endif