Main MRPT website > C++ reference for MRPT 1.9.9
RandomGenerators.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #ifndef RandomGenerator_H
10 #define RandomGenerator_H
11 
12 #include <mrpt/utils/utils_defs.h>
14 
15 #include <random>
16 #include <limits>
17 
18 namespace mrpt
19 {
20 
21 /** A namespace of pseudo-random numbers genrators of diferent distributions.
22  * The central class in this namespace is mrpt::random::CRandomGenerator
23  * \ingroup mrpt_base_grp
24  */
25 namespace random
26 {
27 /** A thred-safe pseudo random number generator, based on an internal MT19937
28  * randomness generator.
29  * The base algorithm for randomness is platform-independent. See
30  * http://en.wikipedia.org/wiki/Mersenne_twister
31  *
32  * For real thread-safety, each thread must create and use its own instance of
33  * this class.
34  *
35  * Single-thread programs can use the static object
36  * mrpt::random::randomGenerator
37  * \ingroup mrpt_base_grp
38  */
40 {
41  protected:
42  /** Data used internally by the MT19937 PRNG algorithm. */
43  std::mt19937_64 m_MT19937;
44 
45  std::normal_distribution<double> m_normdistribution;
46  std::uniform_int_distribution<uint32_t> m_uint32;
47  std::uniform_int_distribution<uint64_t> m_uint64;
48 
49  void MT19937_initializeGenerator(const uint32_t& seed);
50 
51  public:
52  /** @name Initialization
53  @{ */
54 
55  /** Default constructor: initialize random seed based on current time */
57  /** Constructor for providing a custom random seed to initialize the PRNG */
58  CRandomGenerator(const uint32_t seed) { randomize(seed); }
59  /** Initialize the PRNG from the given random seed */
60  void randomize(const uint32_t seed);
61  /** Randomize the generators, based on current time */
62  void randomize();
63 
64  /** @} */
65 
66  /** @name Uniform pdf
67  @{ */
68 
69  /** Generate a uniformly distributed pseudo-random number using the MT19937
70  * algorithm, in the whole range of 32-bit integers.
71  * See: http://en.wikipedia.org/wiki/Mersenne_twister */
73 
74  /** Returns a uniformly distributed pseudo-random number by joining two
75  * 32bit numbers from \a drawUniform32bit() */
77 
78  /** You can call this overloaded method with either 32 or 64bit unsigned
79  * ints for the sake of general coding. */
80  void drawUniformUnsignedInt(uint32_t& ret_number)
81  {
82  ret_number = m_uint32(m_MT19937);
83  }
84  void drawUniformUnsignedInt(uint64_t& ret_number)
85  {
86  ret_number = m_uint64(m_MT19937);
87  }
88 
89  /** Return a uniform unsigned integer in the range [min_val,max_val] (both
90  * inclusive) */
91  template <typename T, typename U, typename V>
93  T& ret_number, const U min_val, const V max_val)
94  {
95  const T range = max_val - min_val + 1;
96  T rnd;
98  ret_number = min_val + (rnd % range);
99  }
100 
101  /** Generate a uniformly distributed pseudo-random number using the MT19937
102  * algorithm, scaled to the selected range. */
103  double drawUniform(const double Min, const double Max)
104  {
105  return Min +
106  (Max - Min) * drawUniform32bit() *
107  2.3283064370807973754314699618685e-10; // 0xFFFFFFFF ^ -1
108  }
109 
110  /** Fills the given matrix with independent, uniformly distributed samples.
111  * Matrix classes can be mrpt::math::CMatrixTemplateNumeric or
112  * mrpt::math::CMatrixFixedNumeric
113  * \sa drawUniform
114  */
115  template <class MAT>
117  MAT& matrix, const double unif_min = 0, const double unif_max = 1)
118  {
119  for (size_t r = 0; r < matrix.getRowCount(); r++)
120  for (size_t c = 0; c < matrix.getColCount(); c++)
121  matrix.get_unsafe(r, c) = static_cast<typename MAT::Scalar>(
122  drawUniform(unif_min, unif_max));
123  }
124 
125  /** Fills the given vector with independent, uniformly distributed samples.
126  * \sa drawUniform
127  */
128  template <class VEC>
130  VEC& v, const double unif_min = 0, const double unif_max = 1)
131  {
132  const size_t N = v.size();
133  for (size_t c = 0; c < N; c++)
134  v[c] =
135  static_cast<typename mrpt::math::ContainerType<VEC>::element_t>(
136  drawUniform(unif_min, unif_max));
137  }
138 
139  /** @} */
140 
141  /** @name Normal/Gaussian pdf
142  @{ */
143 
144  /** Generate a normalized (mean=0, std=1) normally distributed sample.
145  * \param likelihood If desired, pass a pointer to a double which will
146  * receive the likelihood of the given sample to have been obtained, that
147  * is, the value of the normal pdf at the sample value.
148  */
149  double drawGaussian1D_normalized();
150 
151  /** Generate a normally distributed pseudo-random number.
152  * \param mean The mean value of desired normal distribution
153  * \param std The standard deviation value of desired normal distribution
154  */
155  double drawGaussian1D(const double mean, const double std)
156  {
157  return mean + std * drawGaussian1D_normalized();
158  }
159 
160  /** Fills the given matrix with independent, 1D-normally distributed
161  * samples.
162  * Matrix classes can be mrpt::math::CMatrixTemplateNumeric or
163  * mrpt::math::CMatrixFixedNumeric
164  * \sa drawGaussian1D
165  */
166  template <class MAT>
168  MAT& matrix, const double mean = 0, const double std = 1)
169  {
170  for (size_t r = 0; r < matrix.getRowCount(); r++)
171  for (size_t c = 0; c < matrix.getColCount(); c++)
172  matrix.get_unsafe(r, c) = static_cast<typename MAT::Scalar>(
174  }
175 
176  /** Generates a random definite-positive matrix of the given size, using the
177  * formula C = v*v^t + epsilon*I, with "v" being a vector of gaussian random
178  * samples.
179  */
181  const size_t dim, const double std_scale = 1.0,
182  const double diagonal_epsilon = 1e-8);
183 
184  /** Fills the given vector with independent, 1D-normally distributed
185  * samples.
186  * \sa drawGaussian1D
187  */
188  template <class VEC>
190  VEC& v, const double mean = 0, const double std = 1)
191  {
192  const size_t N = v.size();
193  for (size_t c = 0; c < N; c++)
194  v[c] =
195  static_cast<typename mrpt::math::ContainerType<VEC>::element_t>(
197  }
198 
199  /** Generate multidimensional random samples according to a given covariance
200  * matrix.
201  * Mean is assumed to be zero if mean==nullptr.
202  * \exception std::exception On invalid covariance matrix
203  * \sa drawGaussianMultivariateMany
204  */
205  template <typename T>
207  std::vector<T>& out_result,
209  const std::vector<T>* mean = nullptr);
210 
211  /** Generate multidimensional random samples according to a given covariance
212  * matrix.
213  * Mean is assumed to be zero if mean==nullptr.
214  * \exception std::exception On invalid covariance matrix
215  * \sa drawGaussianMultivariateMany
216  */
217  template <class VECTORLIKE, class COVMATRIX>
219  VECTORLIKE& out_result, const COVMATRIX& cov,
220  const VECTORLIKE* mean = nullptr)
221  {
222  const size_t N = cov.rows();
223  ASSERT_(cov.rows() == cov.cols())
224  if (mean) ASSERT_EQUAL_(size_t(mean->size()), N)
225 
226  // Compute eigenvalues/eigenvectors of cov:
227  Eigen::SelfAdjointEigenSolver<typename COVMATRIX::PlainObject>
228  eigensolver(cov);
229 
230  typename Eigen::SelfAdjointEigenSolver<
231  typename COVMATRIX::PlainObject>::MatrixType eigVecs =
232  eigensolver.eigenvectors();
233  typename Eigen::SelfAdjointEigenSolver<
234  typename COVMATRIX::PlainObject>::RealVectorType eigVals =
235  eigensolver.eigenvalues();
236 
237  // Scale eigenvectors with eigenvalues:
238  // D.Sqrt(); Z = Z * D; (for each column)
239  eigVals = eigVals.array().sqrt();
240  for (typename COVMATRIX::Index i = 0; i < eigVecs.cols(); i++)
241  eigVecs.col(i) *= eigVals[i];
242 
243  // Set size of output vector:
244  out_result.assign(N, 0);
245 
246  for (size_t i = 0; i < N; i++)
247  {
249  for (size_t d = 0; d < N; d++)
250  out_result[d] += eigVecs.coeff(d, i) * rnd;
251  }
252  if (mean)
253  for (size_t d = 0; d < N; d++) out_result[d] += (*mean)[d];
254  }
255 
256  /** Generate a given number of multidimensional random samples according to
257  * a given covariance matrix.
258  * \param cov The covariance matrix where to draw the samples from.
259  * \param desiredSamples The number of samples to generate.
260  * \param ret The output list of samples
261  * \param mean The mean, or zeros if mean==nullptr.
262  */
263  template <typename VECTOR_OF_VECTORS, typename COVMATRIX>
265  VECTOR_OF_VECTORS& ret, size_t desiredSamples, const COVMATRIX& cov,
266  const typename VECTOR_OF_VECTORS::value_type* mean = nullptr)
267  {
268  ASSERT_EQUAL_(cov.cols(), cov.rows())
269  if (mean) ASSERT_EQUAL_(size_t(mean->size()), size_t(cov.cols()))
270 
271  // Compute eigenvalues/eigenvectors of cov:
272  Eigen::SelfAdjointEigenSolver<typename COVMATRIX::PlainObject>
273  eigensolver(cov);
274 
275  typename Eigen::SelfAdjointEigenSolver<
276  typename COVMATRIX::PlainObject>::MatrixType eigVecs =
277  eigensolver.eigenvectors();
278  typename Eigen::SelfAdjointEigenSolver<
279  typename COVMATRIX::PlainObject>::RealVectorType eigVals =
280  eigensolver.eigenvalues();
281 
282  // Scale eigenvectors with eigenvalues:
283  // D.Sqrt(); Z = Z * D; (for each column)
284  eigVals = eigVals.array().sqrt();
285  for (typename COVMATRIX::Index i = 0; i < eigVecs.cols(); i++)
286  eigVecs.col(i) *= eigVals[i];
287 
288  // Set size of output vector:
289  ret.resize(desiredSamples);
290  const size_t N = cov.cols();
291  for (size_t k = 0; k < desiredSamples; k++)
292  {
293  ret[k].assign(N, 0);
294  for (size_t i = 0; i < N; i++)
295  {
297  for (size_t d = 0; d < N; d++)
298  ret[k][d] += eigVecs.coeff(d, i) * rnd;
299  }
300  if (mean)
301  for (size_t d = 0; d < N; d++) ret[k][d] += (*mean)[d];
302  }
303  }
304 
305  /** @} */
306 
307  /** @name Miscellaneous
308  @{ */
309 
310  /** Returns a random permutation of a vector: all the elements of the input
311  * vector are in the output but at random positions.
312  */
313  template <class VEC>
314  void permuteVector(const VEC& in_vector, VEC& out_result)
315  {
316  out_result = in_vector;
317  const size_t N = out_result.size();
318  if (N > 1) std::random_shuffle(&out_result[0], &out_result[N - 1]);
319  }
320 
321  /** @} */
322 
323 }; // end of CRandomGenerator
324 // --------------------------------------------------------------
325 
326 /** A static instance of a CRandomGenerator class, for use in single-thread
327  * applications */
328 CRandomGenerator &getRandomGenerator();
329 
330 /** A random number generator for usage in STL algorithms expecting a function
331  * like this (eg, random_shuffle):
332  */
334 {
335  return getRandomGenerator().drawUniform32bit() % i;
336 }
337 
338 /** Fills the given matrix with independent, uniformly distributed samples.
339  * Matrix classes can be mrpt::math::CMatrixTemplateNumeric or
340  * mrpt::math::CMatrixFixedNumeric
341  * \sa matrixRandomNormal
342  */
343 template <class MAT>
345  MAT& matrix, const double unif_min = 0, const double unif_max = 1)
346 {
347  for (size_t r = 0; r < matrix.getRowCount(); r++)
348  for (size_t c = 0; c < matrix.getColCount(); c++)
349  matrix.get_unsafe(r, c) = static_cast<typename MAT::Scalar>(
350  getRandomGenerator().drawUniform(unif_min, unif_max));
351 }
352 
353 /** Fills the given matrix with independent, uniformly distributed samples.
354  * \sa vectorRandomNormal
355  */
356 template <class T>
358  std::vector<T>& v_out, const T& unif_min = 0, const T& unif_max = 1)
359 {
360  size_t n = v_out.size();
361  for (size_t r = 0; r < n; r++)
362  v_out[r] = getRandomGenerator().drawUniform(unif_min, unif_max);
363 }
364 
365 /** Fills the given matrix with independent, normally distributed samples.
366  * Matrix classes can be mrpt::math::CMatrixTemplateNumeric or
367  * mrpt::math::CMatrixFixedNumeric
368  * \sa matrixRandomUni
369  */
370 template <class MAT>
372  MAT& matrix, const double mean = 0, const double std = 1)
373 {
374  for (size_t r = 0; r < matrix.getRowCount(); r++)
375  for (size_t c = 0; c < matrix.getColCount(); c++)
376  matrix.get_unsafe(r, c) = static_cast<typename MAT::Scalar>(
378 }
379 
380 /** Generates a random vector with independent, normally distributed samples.
381  * \sa matrixRandomUni
382  */
383 template <class T>
385  std::vector<T>& v_out, const T& mean = 0, const T& std = 1)
386 {
387  size_t n = v_out.size();
388  for (size_t r = 0; r < n; r++)
390 }
391 
392 /** Randomize the generators.
393  * A seed can be providen, or a current-time based seed can be used (default)
394  */
395 inline void Randomize(const uint32_t seed) { getRandomGenerator().randomize(seed); }
396 inline void Randomize() { getRandomGenerator().randomize(); }
397 /** Returns a random permutation of a vector: all the elements of the input
398  * vector are in the output but at random positions.
399  */
400 template <class T>
402  const std::vector<T>& in_vector, std::vector<T>& out_result)
403 {
404  getRandomGenerator().permuteVector(in_vector, out_result);
405 }
406 
407 /** Generate multidimensional random samples according to a given covariance
408  * matrix.
409  * \exception std::exception On invalid covariance matrix
410  * \sa randomNormalMultiDimensionalMany
411  */
412 template <typename T>
415  std::vector<T>& out_result)
416 {
418 }
419 
420 /** Generate a given number of multidimensional random samples according to a
421 * given covariance matrix.
422 * \param cov The covariance matrix where to draw the samples from.
423 * \param desiredSamples The number of samples to generate.
424 * \param samplesLikelihoods If desired, set to a valid pointer to a vector,
425 * where it will be stored the likelihoods of having obtained each sample: the
426 * product of the gaussian-pdf for each independent variable.
427 * \param ret The output list of samples
428 *
429 * \exception std::exception On invalid covariance matrix
430 *
431 * \sa randomNormalMultiDimensional
432 */
433 template <typename T>
435  const mrpt::math::CMatrixTemplateNumeric<T>& cov, size_t desiredSamples,
436  std::vector<std::vector<T>>& ret,
437  std::vector<T>* samplesLikelihoods = nullptr)
438 {
440  ret, desiredSamples, cov, static_cast<const std::vector<T>*>(nullptr),
441  samplesLikelihoods);
442 }
443 
444 /** Generate multidimensional random samples according to a given covariance
445  * matrix.
446  * \exception std::exception On invalid covariance matrix
447  * \sa randomNormalMultiDimensional
448  */
449 template <typename T, typename MATRIXLIKE>
451  const MATRIXLIKE& cov, size_t desiredSamples,
452  std::vector<std::vector<T>>& ret)
453 {
454  getRandomGenerator().drawGaussianMultivariateMany(ret, desiredSamples, cov);
455 }
456 
457 /** Generate multidimensional random samples according to a given covariance
458  * matrix.
459  * \exception std::exception On invalid covariance matrix
460  * \sa randomNormalMultiDimensionalMany
461  */
462 template <typename T, typename MATRIXLIKE>
464  const MATRIXLIKE& cov, std::vector<T>& out_result)
465 {
467 }
468 
469 } // End of namespace
470 
471 } // End of namespace
472 
473 #endif
#define ASSERT_EQUAL_(__A, __B)
uint32_t drawUniform32bit()
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm, in the whole range of 32-bit integers.
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm, scaled to the selected range.
GLsizei range
Definition: glext.h:5907
void permuteVector(const VEC &in_vector, VEC &out_result)
Returns a random permutation of a vector: all the elements of the input vector are in the output but ...
void drawUniformUnsignedInt(uint32_t &ret_number)
You can call this overloaded method with either 32 or 64bit unsigned ints for the sake of general cod...
GLuint GLenum matrix
Definition: glext.h:6975
void drawGaussian1DVector(VEC &v, const double mean=0, const double std=1)
Fills the given vector with independent, 1D-normally distributed samples.
void randomNormalMultiDimensional(const mrpt::math::CMatrixTemplateNumeric< T > &cov, std::vector< T > &out_result)
Generate multidimensional random samples according to a given covariance matrix.
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
GLenum GLsizei n
Definition: glext.h:5074
void drawGaussian1DMatrix(MAT &matrix, const double mean=0, const double std=1)
Fills the given matrix with independent, 1D-normally distributed samples.
std::uniform_int_distribution< uint64_t > m_uint64
STL namespace.
std::normal_distribution< double > m_normdistribution
A thred-safe pseudo random number generator, based on an internal MT19937 randomness generator...
void randomPermutation(const std::vector< T > &in_vector, std::vector< T > &out_result)
Returns a random permutation of a vector: all the elements of the input vector are in the output but ...
void drawUniformUnsignedIntRange(T &ret_number, const U min_val, const V max_val)
Return a uniform unsigned integer in the range [min_val,max_val] (both inclusive) ...
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
void drawUniformMatrix(MAT &matrix, const double unif_min=0, const double unif_max=1)
Fills the given matrix with independent, uniformly distributed samples.
void randomNormalMultiDimensionalMany(const mrpt::math::CMatrixTemplateNumeric< T > &cov, size_t desiredSamples, std::vector< std::vector< T >> &ret, std::vector< T > *samplesLikelihoods=nullptr)
Generate a given number of multidimensional random samples according to a given covariance matrix...
void drawGaussianMultivariate(VECTORLIKE &out_result, const COVMATRIX &cov, const VECTORLIKE *mean=nullptr)
Generate multidimensional random samples according to a given covariance matrix.
const GLubyte * c
Definition: glext.h:6313
void drawGaussianMultivariateMany(VECTOR_OF_VECTORS &ret, size_t desiredSamples, const COVMATRIX &cov, const typename VECTOR_OF_VECTORS::value_type *mean=nullptr)
Generate a given number of multidimensional random samples according to a given covariance matrix...
void Randomize(const uint32_t seed)
Randomize the generators.
std::mt19937_64 m_MT19937
Data used internally by the MT19937 PRNG algorithm.
void vectorRandomNormal(std::vector< T > &v_out, const T &mean=0, const T &std=1)
Generates a random vector with independent, normally distributed samples.
CRandomGenerator(const uint32_t seed)
Constructor for providing a custom random seed to initialize the PRNG.
ptrdiff_t random_generator_for_STL(ptrdiff_t i)
A random number generator for usage in STL algorithms expecting a function like this (eg...
_W64 int ptrdiff_t
Definition: glew.h:137
uint64_t drawUniform64bit()
Returns a uniformly distributed pseudo-random number by joining two 32bit numbers from drawUniform32b...
mrpt::math::CMatrixDouble drawDefinitePositiveMatrix(const size_t dim, const double std_scale=1.0, const double diagonal_epsilon=1e-8)
Generates a random definite-positive matrix of the given size, using the formula C = v*v^t + epsilon*...
unsigned __int64 uint64_t
Definition: rptypes.h:50
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
void matrixRandomNormal(MAT &matrix, const double mean=0, const double std=1)
Fills the given matrix with independent, normally distributed samples.
void matrixRandomUni(MAT &matrix, const double unif_min=0, const double unif_max=1)
Fills the given matrix with independent, uniformly distributed samples.
void randomize()
Randomize the generators, based on current time.
void MT19937_initializeGenerator(const uint32_t &seed)
#define ASSERT_(f)
std::uniform_int_distribution< uint32_t > m_uint32
CRandomGenerator()
Default constructor: initialize random seed based on current time.
CONTAINER::value_type element_t
Definition: math_frwds.h:103
void vectorRandomUni(std::vector< T > &v_out, const T &unif_min=0, const T &unif_max=1)
Fills the given matrix with independent, uniformly distributed samples.
Eigen::Matrix< typename MATRIX::Scalar, MATRIX::ColsAtCompileTime, MATRIX::ColsAtCompileTime > cov(const MATRIX &v)
Computes the covariance matrix from a list of samples in an NxM matrix, where each row is a sample...
Definition: ops_matrices.h:148
void drawGaussianMultivariate(std::vector< T > &out_result, const mrpt::math::CMatrixTemplateNumeric< T > &cov, const std::vector< T > *mean=nullptr)
Generate multidimensional random samples according to a given covariance matrix.
unsigned __int32 uint32_t
Definition: rptypes.h:47
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
void drawUniformVector(VEC &v, const double unif_min=0, const double unif_max=1)
Fills the given vector with independent, uniformly distributed samples.
double Scalar
Definition: KmUtils.h:44
EIGEN_STRONG_INLINE double mean() const
Computes the mean of the entire matrix.
void drawUniformUnsignedInt(uint64_t &ret_number)
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019