Version: SMASH-3.1
random.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2012-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_RANDOM_H_
11 #define SRC_INCLUDE_SMASH_RANDOM_H_
12 
13 #include <cassert>
14 #include <limits>
15 #include <random>
16 #include <utility>
17 #include <vector>
18 
19 namespace smash {
20 
24 namespace random {
25 
27 using Engine = std::mt19937_64;
28 
30 extern /*thread_local (see #3075)*/ Engine engine;
31 
48 template <typename T>
49 class uniform_dist {
50  public:
57  uniform_dist(T min, T max) : distribution(min, max) {}
59  T operator()() { return distribution(engine); }
60 
61  private:
63  std::uniform_real_distribution<T> distribution;
64 };
65 
67 int64_t generate_63bit_seed();
68 
70 template <typename T>
71 void set_seed(T &&seed) {
72  static_assert(std::is_same<Engine::result_type, uint64_t>::value,
73  "experiment.cc needs the seed to be 64 bits");
74  engine.seed(std::forward<T>(seed));
75 }
76 
78 inline Engine::result_type advance() { return engine(); }
79 
87 template <typename T>
88 T uniform(T min, T max) {
89  return std::uniform_real_distribution<T>(min, max)(engine);
90 }
91 
99 template <typename T>
100 T uniform_int(T min, T max) {
101  return std::uniform_int_distribution<T>(min, max)(engine);
102 }
103 
112 template <typename T = double>
114  return std::generate_canonical<T, std::numeric_limits<double>::digits>(
115  engine);
116 }
117 
121 template <typename T = double>
123  // use 'nextafter' to generate a value that is guaranteed to be larger than 0
124  return std::nextafter(
125  std::generate_canonical<T, std::numeric_limits<double>::digits>(engine),
126  T(1));
127 }
128 
134 template <typename T>
136  return uniform_dist<T>(min, max);
137 }
138 
148 template <typename T = double>
149 T exponential(T lambda) {
150  // We are not using std::exponential_distribution because of a bug in the
151  // implementations by clang and gcc.
152  return -std::log(canonical_nonzero()) / lambda;
153 }
154 
165 template <typename T = double>
166 T expo(T A, T x1, T x2) {
167  const T a1 = A * x1, a2 = A * x2;
168  const T a_min = std::log(std::numeric_limits<T>::min());
169 #ifndef NDEBUG
170  assert(A > T(0.) && x1 >= x2 && a1 > a_min);
171 #endif
172  const T r1 = std::exp(a1);
173  const T r2 = a2 > a_min ? std::exp(a2) : T(0.); // prevent underflow
174  T x;
175  do {
176  /* sample repeatedly until x is in the requested range
177  * (it can get outside due to numerical errors, see issue #2959) */
178  x = std::log(uniform(r1, r2)) / A;
179  } while (!(x <= x1 && x > x2));
180  return x;
181 }
182 
189 template <typename T>
190 int sgn(T val) {
191  return (T(0) < val) - (val < T(0));
192 }
193 
202 template <typename T = double>
203 T power(T n, T xMin, T xMax) {
204  const T n1 = n + 1;
205  if (std::abs(n1) < 1E-3) {
206  return xMin * std::pow(xMax / xMin, canonical());
207  } else if (xMin >= 0. && xMax > 0.) {
208  return std::pow(uniform(std::pow(xMin, n1), std::pow(xMax, n1)), 1. / n1);
209  } else {
210  return sgn(xMin) * std::pow(uniform(std::pow(std::abs(xMin), n1),
211  std::pow(std::abs(xMax), n1)),
212  1. / n1);
213  }
214 }
215 
225 template <typename T>
226 int poisson(const T &lam) {
227  return std::poisson_distribution<int>(lam)(engine);
228 }
229 
237 template <typename T>
238 int binomial(const int N, const T &p) {
239  return std::binomial_distribution<int>(N, p)(engine);
240 }
241 
249 template <typename T>
250 double normal(const T &mean, const T &sigma) {
251  return std::normal_distribution<double>(mean, sigma)(engine);
252 }
253 
257 template <typename T>
259  public:
265 
269  explicit discrete_dist(const std::vector<T> &plist)
270  : distribution(plist.begin(), plist.end()) {}
271 
275  explicit discrete_dist(std::initializer_list<T> l) : distribution(l) {}
276 
280  void reset_weights(const std::vector<T> &plist) {
281  distribution = std::discrete_distribution<>(plist.begin(), plist.end());
282  }
286  int operator()() { return distribution(engine); }
287 
288  private:
290  std::discrete_distribution<> distribution;
291 };
292 
306 template <typename T = double>
307 T cauchy(T pole, T width, T min, T max) {
308  /* Use double-precision variables, in order to work around a glibc bug in
309  * tanf:
310  * https://sourceware.org/bugzilla/show_bug.cgi?id=18221 */
311  const double u_min = std::atan((min - pole) / width);
312  const double u_max = std::atan((max - pole) / width);
313  const double u = uniform(u_min, u_max);
314  return pole + width * std::tan(u);
315 }
316 
328 template <typename T = double>
329 T beta(T a, T b) {
330  // Otherwise the integral over probability density diverges
331  assert(a > T(0.0) && b > T(0.0));
332  const T x1 = std::gamma_distribution<T>(a)(engine);
333  const T x2 = std::gamma_distribution<T>(b)(engine);
334  return x1 / (x1 + x2);
335 }
336 
350 template <typename T = double>
351 T beta_a0(T xmin, T b) {
352  assert(xmin > T(0.0) && xmin < T(1.0));
353  T y;
354  do {
355  y = uniform(0.0, -std::log(xmin));
356  } while (std::pow((1.0 - std::exp(-y)), b) < canonical());
357  return std::exp(-y);
358 }
359 
378  public:
387  BesselSampler(const double poisson_mean1, const double poisson_mean2,
388  const int fixed_difference);
389 
395  std::pair<int, int> sample();
396 
397  private:
407  static double r_(int n, double a);
408 
411 
413  double m_;
414 
416  const double a_;
417 
419  const int N_;
420 
422  const bool N_is_positive_;
423 
429  static constexpr double m_switch_method_ = 6.0;
430 
432  static constexpr double negligible_probability_ = 1.e-12;
433 
435  double mu_;
436 
438  double sigma_;
439 };
440 
441 } // namespace random
442 } // namespace smash
443 
444 #endif // SRC_INCLUDE_SMASH_RANDOM_H_
The intention of this class is to efficiently sample from the Bessel distribution ,...
Definition: random.h:377
double mu_
Mean of the Bessel distribution.
Definition: random.h:435
double sigma_
Standard deviation of the Bessel distribution.
Definition: random.h:438
std::pair< int, int > sample()
Sample two numbers from given Poissonians with a fixed difference.
Definition: random.cc:73
const bool N_is_positive_
Boolean variable to verify that N > 0.
Definition: random.h:422
static double r_(int n, double a)
Compute the ratio of two Bessel functions r(n,a) = bessel_I(n+1,a)/bessel_I(n,a) using the continued ...
Definition: random.cc:81
static constexpr double negligible_probability_
Probabilities smaller than negligibly_probability are neglected.
Definition: random.h:432
double m_
Mode of the Bessel function, see for details.
Definition: random.h:413
static constexpr double m_switch_method_
Switching mode to normal approximation.
Definition: random.h:429
random::discrete_dist< double > dist_
Vector to store tabulated values of probabilities for small m case (m <6).
Definition: random.h:410
BesselSampler(const double poisson_mean1, const double poisson_mean2, const int fixed_difference)
Construct a BesselSampler.
Definition: random.cc:31
const int N_
First parameter of Bessel distribution (= in ).
Definition: random.h:419
const double a_
Second parameter of Bessel distribution, see for details.
Definition: random.h:416
Discrete distribution with weight given by probability vector.
Definition: random.h:258
discrete_dist()
Default discrete distribution.
Definition: random.h:264
std::discrete_distribution distribution
The distribution object that is being used.
Definition: random.h:290
int operator()()
Draw a random number from the discrete distribution.
Definition: random.h:286
discrete_dist(const std::vector< T > &plist)
Construct from probability vector.
Definition: random.h:269
discrete_dist(std::initializer_list< T > l)
Construct from probability list.
Definition: random.h:275
void reset_weights(const std::vector< T > &plist)
Reset the discrete distribution from a new probability list.
Definition: random.h:280
Provides uniform random numbers on a fixed interval.
Definition: random.h:49
uniform_dist(T min, T max)
Creates the object and fixes the interval.
Definition: random.h:57
std::uniform_real_distribution< T > distribution
The distribution object that is being used.
Definition: random.h:63
constexpr int p
Proton.
constexpr int n
Neutron.
int poisson(const T &lam)
Returns a Poisson distributed random number.
Definition: random.h:226
T power(T n, T xMin, T xMax)
Draws a random number according to a power-law distribution ~ x^n.
Definition: random.h:203
T exponential(T lambda)
Draws an exponentially distributed random number.
Definition: random.h:149
T beta_a0(T xmin, T b)
Draws a random number from a beta-distribution with a = 0.
Definition: random.h:351
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:329
uniform_dist< T > make_uniform_distribution(T min, T max)
Definition: random.h:135
Engine::result_type advance()
Advance the engine's state and return the generated value.
Definition: random.h:78
T expo(T A, T x1, T x2)
Draws a random number x from an exponential distribution exp(A*x), where A is assumed to be positive,...
Definition: random.h:166
T canonical_nonzero()
Definition: random.h:122
Engine engine
The engine that is used commonly by all distributions.
Definition: random.cc:18
int64_t generate_63bit_seed()
Generates a seed with a truly random 63-bit value, if possible.
Definition: random.cc:20
std::mt19937_64 Engine
The random number engine used is the Mersenne Twister.
Definition: random.h:27
double normal(const T &mean, const T &sigma)
Returns a random number drawn from a normal distribution.
Definition: random.h:250
T uniform_int(T min, T max)
Definition: random.h:100
int binomial(const int N, const T &p)
Returns a binomially distributed random number.
Definition: random.h:238
T uniform(T min, T max)
Definition: random.h:88
T cauchy(T pole, T width, T min, T max)
Draws a random number from a Cauchy distribution (sometimes also called Lorentz or non-relativistic B...
Definition: random.h:307
int sgn(T val)
Signum function.
Definition: random.h:190
T canonical()
Definition: random.h:113
void set_seed(T &&seed)
Sets the seed of the random number engine.
Definition: random.h:71
Definition: action.h:24