bpp-core3  3.0.0
RandomTools.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_NUMERIC_RANDOM_RANDOMTOOLS_H
6 #define BPP_NUMERIC_RANDOM_RANDOMTOOLS_H
7 
8 
9 #include "../../Exceptions.h"
10 #include "../VectorExceptions.h"
11 #include "../VectorTools.h"
12 
13 // From the STL:
14 #include <cmath>
15 #include <cassert>
16 #include <ctime>
17 #include <vector>
18 #include <algorithm>
19 #include <random>
20 
21 namespace bpp
22 {
35 {
36 public:
38  virtual ~RandomTools() {}
39 
40 private:
44  static double incompletebetafe(double a,
45  double b,
46  double x,
47  double big,
48  double biginv);
49  static double incompletebetafe2(double a,
50  double b,
51  double x,
52  double big,
53  double biginv);
54  static double incompletebetaps(double a,
55  double b,
56  double x,
57  double maxgam);
58 
59 public:
60  static std::random_device RANDOM_DEVICE;
61  static std::mt19937 DEFAULT_GENERATOR;
62 
68  static void setSeed(std::mt19937::result_type seed)
69  {
70  DEFAULT_GENERATOR.seed(seed);
71  }
72 
78  static double giveRandomNumberBetweenZeroAndEntry(double entry)
79  {
80  std::uniform_real_distribution<double> dis(0, entry);
81  return dis(DEFAULT_GENERATOR);
82  }
83 
89  static bool flipCoin(double prob = 0.5)
90  {
91  std::bernoulli_distribution d(prob);
92  return d(DEFAULT_GENERATOR);
93  }
94 
102  template<class intType>
103  static intType giveIntRandomNumberBetweenZeroAndEntry(intType entry)
104  {
105  if (entry == 0)
106  throw Exception("RandomTools::giveIntRandomNumberBetweenZeroAndEntry. Entry must be at least 1.");
107  std::uniform_int_distribution<intType> dis(0, entry - 1);
108  return dis(DEFAULT_GENERATOR);
109  }
110 
116  static double randGaussian(double mean, double variance)
117  {
118  std::normal_distribution<double> dis(mean, sqrt(variance));
119  return dis(DEFAULT_GENERATOR);
120  }
121 
126  static double randGamma(double alpha)
127  {
128  std::gamma_distribution<double> dis(alpha, 1.);
129  return dis(DEFAULT_GENERATOR);
130  }
131 
137  static double randGamma(double alpha, double beta)
138  {
139  std::gamma_distribution<double> dis(alpha, beta);
140  return dis(DEFAULT_GENERATOR);
141  }
142 
148  static double randBeta(double alpha, double beta);
149 
154  static double randExponential(double mean)
155  {
156  std::exponential_distribution<double> dis(mean);
157  return dis(DEFAULT_GENERATOR);
158  }
159 
174  template<class T>
175  static T pickOne(std::vector<T>& v, bool replace = false)
176  {
177  if (v.empty())
178  throw EmptyVectorException<T>("RandomTools::pickOne: input vector is empty", &v);
179  size_t pos = RandomTools::giveIntRandomNumberBetweenZeroAndEntry<size_t>(v.size());
180  if (replace)
181  return v[pos];
182  else
183  {
184  T e = v[pos];
185  v[pos] = v.back();
186  v.pop_back();
187  return e;
188  }
189  }
190 
200  template<class T>
201  static T pickOne(const std::vector<T>& v)
202  {
203  if (v.empty())
204  throw EmptyVectorException<T>("RandomTools::pickOne: input vector is empty", &v);
205  size_t pos = RandomTools::giveIntRandomNumberBetweenZeroAndEntry<size_t>(v.size());
206  return v[pos];
207  }
208 
226  template<class T>
227  static void getSample(const std::vector<T>& vin, std::vector<T>& vout, bool replace = false)
228  {
229  if (vout.size() > vin.size() && !replace)
230  throw IndexOutOfBoundsException("RandomTools::getSample: size exceeded v.size.", vout.size(), 0, vin.size());
231  if (replace)
232  {
233  for (size_t i = 0; i < vout.size(); ++i)
234  {
235  vout[i] = pickOne(vin);
236  }
237  }
238  else
239  {
240  std::vector<size_t> hat(vin.size());
241  std::iota(hat.begin(), hat.end(), 0);
242  std::shuffle(hat.begin(), hat.end(), DEFAULT_GENERATOR);
243  for (size_t i = 0; i < vout.size(); i++)
244  {
245  vout[i] = vin[hat[i]];
246  }
247  }
248  }
249 
265  template<class T>
266  static T pickOne(std::vector<T>& v, std::vector<double>& w, bool replace = false)
267  {
268  if (v.empty())
269  throw EmptyVectorException<T>("RandomTools::pickOne (with weight): input vector is empty", &v);
270  // Compute cumulative sum of weights:
271  std::vector<double> sumw = VectorTools::cumSum(w);
272  // Convert to cumulative distribution:
273  sumw /= sumw.back();
274  // Get random positions:
276  size_t pos = v.size() - 1;
277  for (size_t i = 0; i < v.size(); ++i)
278  {
279  if (prob < sumw[i])
280  {
281  pos = i;
282  break;
283  }
284  }
285  if (replace)
286  return v[pos];
287  else
288  {
289  T e = v[pos];
290  v[pos] = v.back();
291  v.pop_back();
292  w[pos] = w.back();
293  w.pop_back();
294  return e;
295  }
296  }
297 
311  template<class T>
312  static T pickOne(const std::vector<T>& v, const std::vector<double>& w)
313  {
314  if (v.empty())
315  throw EmptyVectorException<T>("RandomTools::pickOne (with weight): input vector is empty", &v);
316  // Compute cumulative sum of weights:
317  std::vector<double> sumw = VectorTools::cumSum(w);
318  // Convert to cumulative distribution:
319  sumw /= sumw.back();
320  // Get random positions:
322  size_t pos = v.size() - 1;
323  for (size_t i = 0; i < v.size(); ++i)
324  {
325  if (prob < sumw[i])
326  {
327  pos = i;
328  break;
329  }
330  }
331  return v[pos];
332  }
333 
345  static size_t pickFromCumSum(const std::vector<double>& w)
346  {
348  size_t pos = 0;
349  while (pos < w.size() - 1)
350  {
351  if (prob <= w[pos])
352  return pos;
353  pos += 1;
354  }
355  return w.size() - 1;
356  }
357 
382  template<class T>
383  static void getSample(const std::vector<T>& vin, const std::vector<double>& w, std::vector<T>& vout, bool replace = false)
384  {
385  if (vout.size() > vin.size() && !replace)
386  throw IndexOutOfBoundsException("RandomTools::getSample (with weights): size exceeded v.size.", vout.size(), 0, vin.size());
387  std::vector<size_t> hat(vin.size());
388  std::iota(hat.begin(), hat.end(), 0);
389  if (replace)
390  {
391  for (size_t i = 0; i < vout.size(); i++)
392  {
393  vout[i] = vin[pickOne(hat, w)];
394  }
395  }
396  else
397  {
398  std::vector<double> w2(w); // non const copy
399  for (size_t i = 0; i < vout.size(); i++)
400  {
401  vout[i] = vin[pickOne(hat, w2, false)];
402  }
403  }
404  }
405 
416  static std::vector<size_t> randMultinomial(size_t n, const std::vector<double>& probs);
417 
443  static double qNorm(double prob);
444 
464  static double qNorm(double prob, double mu, double sigma);
465 
472  static double lnGamma(double alpha) { return std::lgamma(alpha); }
473 
490  static double incompleteGamma(double x, double alpha, double ln_gamma_alpha);
491 
492 
507  static double qChisq(double prob, double v);
508 
516  static double pChisq(double x, double v)
517  {
518  if (x < 0) return 0;
519  return pGamma(x, v / 2, 0.5);
520  }
521 
530  static double qGamma(double prob, double alpha, double beta)
531  {
532  return qChisq(prob, 2.0 * (alpha)) / (2.0 * (beta));
533  }
534 
545  static double pGamma(double x, double alpha, double beta)
546  {
547  if (alpha < 0) throw Exception("RandomTools::pGamma. Negative alpha is not allowed.");
548  if (beta < 0) throw Exception("RandomTools::pGamma. Negative beta is not allowed.");
549  if (alpha == 0.) return 1.;
550  return incompleteGamma(beta * x, alpha, lnGamma(alpha));
551  }
552 
575  static double pNorm(double z);
576 
577  /* @brief Normal cumulative function.
578  *
579  * Returns Prob{x<=z} where x ~ N(mu,sigma^2)
580 
581  * @param z the value.
582  * @param mu The mean of the distribution
583  * @param sigma The standard deviation of the distribution
584  * @return The corresponding probability.
585  */
586 
587  static double pNorm(double z, double mu, double sigma);
588 
599  static double lnBeta(double alpha, double beta);
600 
614  static double incompleteBeta(double x, double alpha, double beta);
615  static double pBeta(double x, double alpha, double beta)
616  {
617  return incompleteBeta(x, alpha, beta);
618  }
619 
641  static double qBeta(double prob, double alpha, double beta);
642 
645 private:
646  static double DblGammaGreaterThanOne(double dblAlpha);
647  static double DblGammaLessThanOne(double dblAlpha);
648 };
649 } // end of namespace bpp.
650 #endif // BPP_NUMERIC_RANDOM_RANDOMTOOLS_H
static double pNorm(double z)
Normal cumulative function.
static double pChisq(double x, double v)
cumulative probability function.
Definition: RandomTools.h:516
static void getSample(const std::vector< T > &vin, const std::vector< double > &w, std::vector< T > &vout, bool replace=false)
Sample a vector, with associated probability weights.
Definition: RandomTools.h:383
static T pickOne(std::vector< T > &v, bool replace=false)
Pick (and extract) one element randomly in a vector and return it.
Definition: RandomTools.h:175
Utilitary function dealing with random numbers.
Definition: RandomTools.h:34
static double incompletebetafe2(double a, double b, double x, double big, double biginv)
static double randBeta(double alpha, double beta)
static double randExponential(double mean)
Definition: RandomTools.h:154
static bool flipCoin(double prob=0.5)
Get a boolean random value.
Definition: RandomTools.h:89
static void setSeed(std::mt19937::result_type seed)
Set the default generator seed.
Definition: RandomTools.h:68
static void getSample(const std::vector< T > &vin, std::vector< T > &vout, bool replace=false)
Sample a vector.
Definition: RandomTools.h:227
static std::random_device RANDOM_DEVICE
Definition: RandomTools.h:60
static double DblGammaGreaterThanOne(double dblAlpha)
Definition: RandomTools.cpp:43
static T pickOne(std::vector< T > &v, std::vector< double > &w, bool replace=false)
Pick one element in a vector, with associated probability weights.
Definition: RandomTools.h:266
static double qBeta(double prob, double alpha, double beta)
The Beta quantile function.
static double randGamma(double alpha)
Definition: RandomTools.h:126
static size_t pickFromCumSum(const std::vector< double > &w)
Pick one index from a cumsum vector of probabilities.
Definition: RandomTools.h:345
static double incompleteGamma(double x, double alpha, double ln_gamma_alpha)
Returns the incomplete gamma ratio I(x,alpha).
static double qNorm(double prob)
Normal quantile function.
static double giveRandomNumberBetweenZeroAndEntry(double entry)
Get a double random value (between 0 and specified range).
Definition: RandomTools.h:78
static T pickOne(const std::vector< T > &v)
Pick one element randomly in a vector and return it.
Definition: RandomTools.h:201
Exception thrown when an empty vector was found.
static std::vector< T > cumSum(const std::vector< T > &v1)
Definition: VectorTools.h:624
static double incompletebetafe(double a, double b, double x, double big, double biginv)
functions for the computation of incompleteBeta
static double randGamma(double alpha, double beta)
Definition: RandomTools.h:137
static double pGamma(double x, double alpha, double beta)
cumulative probability function.
Definition: RandomTools.h:545
static double pBeta(double x, double alpha, double beta)
Definition: RandomTools.h:615
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
static double lnGamma(double alpha)
Computes given .
Definition: RandomTools.h:472
virtual ~RandomTools()
Definition: RandomTools.h:38
static std::mt19937 DEFAULT_GENERATOR
Definition: RandomTools.h:61
static double incompletebetaps(double a, double b, double x, double maxgam)
Index out of bounds exception class.
Definition: Exceptions.h:131
static std::vector< size_t > randMultinomial(size_t n, const std::vector< double > &probs)
Get a random state from a set of probabilities/scores.
Definition: RandomTools.cpp:13
static double qGamma(double prob, double alpha, double beta)
The Gamma quantile function.
Definition: RandomTools.h:530
static double DblGammaLessThanOne(double dblAlpha)
Definition: RandomTools.cpp:87
static T pickOne(const std::vector< T > &v, const std::vector< double > &w)
Pick one element in a vector, with associated probability weights.
Definition: RandomTools.h:312
static double qChisq(double prob, double v)
quantile function.
static intType giveIntRandomNumberBetweenZeroAndEntry(intType entry)
Get an integer random value (between 0 and specified range).
Definition: RandomTools.h:103
static double randGaussian(double mean, double variance)
Definition: RandomTools.h:116
static double incompleteBeta(double x, double alpha, double beta)
Returns the regularized incomplete beta function .
static double lnBeta(double alpha, double beta)
Computes given and .