vSMC
vSMC: Scalable Monte Carlo
beta_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/beta_distribution.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2015, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_RNG_BETA_DISTRIBUTION_HPP
33 #define VSMC_RNG_BETA_DISTRIBUTION_HPP
34 
38 
39 namespace vsmc
40 {
41 
42 namespace internal
43 {
44 
45 template <typename RealType>
46 inline bool beta_distribution_check_param(RealType alpha, RealType beta)
47 {
48  return alpha > 0 && beta > 0;
49 }
50 
61 }; // enum BetaDistributionAlgorithm
62 
63 template <typename RealType>
65 {
66  public:
67  BetaDistributionConstant(RealType alpha = 1, RealType beta = 1)
68  {
69  reset(alpha, beta);
70  }
71 
72  void reset(RealType alpha, RealType beta)
73  {
74  const RealType K = static_cast<RealType>(0.852);
75  const RealType C = static_cast<RealType>(-0.956);
76  const RealType D = beta + K * alpha * alpha + C;
77  if (is_equal<RealType>(alpha, 0.5) && is_equal<RealType>(beta, 0.5))
79  else if (is_equal<RealType>(alpha, 1) && is_equal<RealType>(beta, 1))
81  else if (is_equal<RealType>(alpha, 1))
83  else if (is_equal<RealType>(beta, 1))
85  else if (alpha > 1 && beta > 1)
87  else if (alpha < 1 && beta < 1 && D <= 0)
89  else if (alpha < 1 && beta < 1)
91  else if (alpha < 1 && beta > 1)
93  else if (alpha > 1 && beta < 1)
95  else
97 
98  a = b = t = p = 0;
99  switch (algorithm) {
100  case BetaDistributionAlgorithmAS: break;
101  case BetaDistributionAlgorithm11: break;
102  case BetaDistributionAlgorithm1X: b = 1 / beta; break;
103  case BetaDistributionAlgorithmX1: a = 1 / alpha; break;
105  a = alpha + beta;
106  b = std::min(alpha, beta);
107  if (b > 1)
108  b = std::sqrt((2 * alpha * beta - a) / (a - 2));
109  b = 1 / b;
110  t = alpha + 1 / b;
111  p = a * std::log(a);
112  break;
114  a = 1 / alpha;
115  b = 1 / beta;
116  break;
118  a = 1 / alpha;
119  b = 1 / beta;
120  t = std::sqrt(alpha * (1 - alpha));
121  t /= t + std::sqrt(beta * (1 - beta));
122  p = beta * t;
123  p /= p + alpha * (1 - t);
124  break;
126  a = 1 / alpha;
127  b = 1 / beta;
128  t = 1 - alpha;
129  t /= t + beta;
130  p = beta * t;
131  p /= p + alpha * std::pow(1 - t, beta);
132  break;
134  a = 1 / beta;
135  b = 1 / alpha;
136  t = 1 - beta;
137  t /= t + alpha;
138  p = alpha * t;
139  p /= p + beta * std::pow(1 - t, alpha);
140  break;
141  }
142  }
143 
144  RealType a;
145  RealType b;
146  RealType t;
147  RealType p;
149 }; // class BetaDistributionConstant
150 
151 } // namespace internal
152 
155 template <typename RealType>
157 {
159  Beta, beta, RealType, result_type, alpha, 1, result_type, beta, 1)
161 
162  public:
163  result_type min VSMC_MNE() const { return 0; }
164  result_type max VSMC_MNE() const { return 1; }
165  void reset() { constant_.reset(alpha(), beta()); }
166 
167  private:
169 
170  template <typename RNGType>
171  result_type generate(RNGType &rng, const param_type &param)
172  {
173  if (param == param_)
174  return generate(rng, param_, constant_);
175 
177  param.alpha(), param.beta());
178 
179  return generate(rng, param, constant);
180  }
181 
182  template <typename RNGType>
183  result_type generate(RNGType &rng, const param_type &param,
185  {
186  result_type r = 0;
187  switch (constant.algorithm) {
189  r = generate_as(rng, param, constant);
190  break;
192  r = generate_11(rng, param, constant);
193  break;
195  r = generate_1x(rng, param, constant);
196  break;
198  r = generate_x1(rng, param, constant);
199  break;
201  r = generate_c(rng, param, constant);
202  break;
204  r = generate_j(rng, param, constant);
205  break;
207  r = generate_a1(rng, param, constant);
208  break;
210  r = generate_a2(rng, param, constant);
211  break;
213  r = generate_a3(rng, param, constant);
214  break;
215  }
216 
217  return r;
218  }
219 
220  template <typename RNGType>
221  result_type generate_as(RNGType &rng, const param_type &,
223  {
225  result_type u = runif(rng);
226  u = std::sin(
227  -const_pi_by2<result_type>() + const_pi<result_type>() * u);
228 
229  return static_cast<result_type>(0.5) +
230  static_cast<result_type>(0.5) * u;
231  }
232 
233  template <typename RNGType>
234  result_type generate_11(RNGType &rng, const param_type &,
236  {
238 
239  return runif(rng);
240  }
241 
242  template <typename RNGType>
243  result_type generate_1x(RNGType &rng, const param_type &,
245  {
247 
248  return 1 - std::exp(constant.b * std::log(runif(rng)));
249  }
250 
251  template <typename RNGType>
252  result_type generate_x1(RNGType &rng, const param_type &,
254  {
256 
257  return std::exp(constant.a * std::log(runif(rng)));
258  }
259 
260  template <typename RNGType>
261  result_type generate_c(RNGType &rng, const param_type &param,
263  {
265  const result_type ln_4 = 2 * const_ln_2<result_type>();
266  result_type x = 0;
267  result_type y = 0;
268  result_type left = 0;
269  result_type right = 0;
270  do {
271  result_type u1 = runif(rng);
272  result_type u2 = runif(rng);
273  result_type v = constant.b * std::log(u1 / (1 - u1));
274  x = param.alpha() * std::exp(v);
275  y = param.beta() + x;
276  left = (constant.p - constant.a * std::log(y)) +
277  (constant.t * v - ln_4);
278  right = std::log(u1 * u1 * u2);
279  } while (left < right);
280 
281  return x / y;
282  }
283 
284  template <typename RNGType>
285  result_type generate_j(RNGType &rng, const param_type &,
287  {
289  result_type x = 0;
290  result_type y = 0;
291  do {
292  x = std::pow(runif(rng), constant.a);
293  y = std::pow(runif(rng), constant.b);
294  } while (x + y > 1);
295 
296  return x / (x + y);
297  }
298 
299  template <typename RNGType>
300  result_type generate_a1(RNGType &rng, const param_type &param,
302  {
304  while (true) {
305  result_type u = runif(rng);
306  result_type e = -std::log(runif(rng));
307  result_type x = 0;
308  result_type v = 0;
309  if (u < constant.p) {
310  x = constant.t * std::pow(u / constant.p, constant.a);
311  v = (1 - param.beta()) * std::log((1 - x) / (1 - constant.t));
312  } else {
313  x = 1 -
314  (1 - constant.t) *
315  std::pow((1 - u) / (1 - constant.p), constant.b);
316  v = (1 - param.alpha()) * std::log(x / constant.t);
317  }
318  if (v < e)
319  return x;
320  }
321  }
322 
323  template <typename RNGType>
324  result_type generate_a2(RNGType &rng, const param_type &param,
326  {
328  while (true) {
329  result_type u = runif(rng);
330  result_type e = -std::log(runif(rng));
331  result_type x = 0;
332  result_type v = 0;
333  if (u < constant.p) {
334  x = constant.t * std::pow(u / constant.p, constant.a);
335  v = (1 - param.beta()) * std::log(1 - x);
336  } else {
337  x = 1 -
338  (1 - constant.t) *
339  std::pow((1 - u) / (1 - constant.p), constant.b);
340  v = (1 - param.alpha()) * std::log(x / constant.t);
341  }
342  if (v < e)
343  return x;
344  }
345  }
346 
347  template <typename RNGType>
348  result_type generate_a3(RNGType &rng, const param_type &param,
350  {
352  while (true) {
353  result_type u = runif(rng);
354  result_type e = -std::log(runif(rng));
355  result_type x = 0;
356  result_type v = 0;
357  if (u < constant.p) {
358  x = constant.t * std::pow(u / constant.p, constant.a);
359  v = (1 - param.alpha()) * std::log(1 - x);
360  } else {
361  x = 1 -
362  (1 - constant.t) *
363  std::pow((1 - u) / (1 - constant.p), constant.b);
364  v = (1 - param.beta()) * std::log(x / constant.t);
365  }
366  if (v < e)
367  return 1 - x;
368  }
369  }
370 }; // class BetaDistribution
371 
372 namespace internal
373 {
374 
375 template <std::size_t, typename RealType, typename RNGType>
376 inline std::size_t beta_distribution_impl_as(RNGType &rng, std::size_t n,
377  RealType *r, RealType, RealType,
379 {
380  u01_oo_distribution(rng, n, r);
381  fma(n, const_pi<RealType>(), r, -const_pi_by2<RealType>(), r);
382  sin(n, r, r);
383  fma(n, static_cast<RealType>(0.5), r, static_cast<RealType>(0.5), r);
384 
385  return n;
386 }
387 
388 template <std::size_t, typename RealType, typename RNGType>
389 inline std::size_t beta_distribution_impl_11(RNGType &rng, std::size_t n,
390  RealType *r, RealType, RealType,
392 {
393  u01_oo_distribution(rng, n, r);
394 
395  return n;
396 }
397 
398 template <std::size_t, typename RealType, typename RNGType>
399 inline std::size_t beta_distribution_impl_1x(RNGType &rng, std::size_t n,
400  RealType *r, RealType, RealType,
401  const BetaDistributionConstant<RealType> &constant)
402 {
403  u01_oo_distribution(rng, n, r);
404  log(n, r, r);
405  mul(n, constant.b, r, r);
406  exp(n, r, r);
407  sub(n, static_cast<RealType>(1), r, r);
408 
409  return n;
410 }
411 
412 template <std::size_t, typename RealType, typename RNGType>
413 inline std::size_t beta_distribution_impl_x1(RNGType &rng, std::size_t n,
414  RealType *r, RealType, RealType,
415  const BetaDistributionConstant<RealType> &constant)
416 {
417  u01_oo_distribution(rng, n, r);
418  log(n, r, r);
419  mul(n, constant.a, r, r);
420  exp(n, r, r);
421 
422  return n;
423 }
424 
425 template <std::size_t K, typename RealType, typename RNGType>
426 inline std::size_t beta_distribution_impl_c(RNGType &rng, std::size_t n,
427  RealType *r, RealType alpha, RealType beta,
428  const BetaDistributionConstant<RealType> &constant)
429 {
430  const RealType a = constant.a;
431  const RealType b = constant.b;
432  const RealType t = constant.t;
433  const RealType p = constant.p;
434  const RealType ln_4 = 2 * const_ln_2<RealType>();
435  RealType s[K * 5];
436  RealType *const u1 = s;
437  RealType *const u2 = s + n;
438  RealType *const v = s + n * 2;
439  RealType *const x = s + n * 3;
440  RealType *const y = s + n * 4;
441  u01_co_distribution(rng, n * 2, s);
442  sub(n, static_cast<RealType>(1), u1, v);
443  div(n, u1, v, v);
444  log(n, v, v);
445  mul(n, b, v, v);
446  exp(n, v, x);
447  mul(n, alpha, x, x);
448  add(n, beta, x, y);
449  div(n, x, y, x);
450  sqr(n, u1, u1);
451  mul(n, u1, u2, u2);
452  log(n, u2, u2);
453  log(n, y, u1);
454  fma(n, -a, u1, p, u1);
455  fma(n, t, v, -ln_4, v);
456  add(n, v, u1, u1);
457 
458  std::size_t m = 0;
459  for (std::size_t i = 0; i != n; ++i)
460  if (u1[i] > u2[i])
461  r[m++] = x[i];
462 
463  return m;
464 }
465 
466 template <std::size_t K, typename RealType, typename RNGType>
467 inline std::size_t beta_distribution_impl_j(RNGType &rng, std::size_t n,
468  RealType *r, RealType, RealType,
469  const BetaDistributionConstant<RealType> &constant)
470 {
471  const RealType a = constant.a;
472  const RealType b = constant.b;
473  RealType s[K * 3];
474  RealType *const x = s;
475  RealType *const y = s + n;
476  RealType *const u = s + n * 2;
477  u01_co_distribution(rng, n * 2, s);
478  pow(n, x, a, x);
479  pow(n, y, b, y);
480  add(n, x, y, u);
481  div(n, x, u, x);
482 
483  std::size_t m = 0;
484  for (std::size_t i = 0; i != n; ++i)
485  if (u[i] < 1)
486  r[m++] = x[i];
487 
488  return m;
489 }
490 
491 template <std::size_t, typename RealType, typename RNGType>
492 inline std::size_t beta_distribution_impl_a1(RNGType &, std::size_t,
493  RealType *, RealType, RealType, const BetaDistributionConstant<RealType> &)
494 {
495  return 0;
496 }
497 
498 template <std::size_t, typename RealType, typename RNGType>
499 inline std::size_t beta_distribution_impl_a2(RNGType &, std::size_t,
500  RealType *, RealType, RealType, const BetaDistributionConstant<RealType> &)
501 {
502  return 0;
503 }
504 
505 template <std::size_t, typename RealType, typename RNGType>
506 inline std::size_t beta_distribution_impl_a3(RNGType &, std::size_t,
507  RealType *, RealType, RealType, const BetaDistributionConstant<RealType> &)
508 {
509  return 0;
510 }
511 
512 template <std::size_t K, typename RealType, typename RNGType>
513 inline std::size_t beta_distribution_impl(RNGType &rng, std::size_t n,
514  RealType *r, RealType alpha, RealType beta,
515  const BetaDistributionConstant<RealType> &constant)
516 {
517  switch (constant.algorithm) {
519  return beta_distribution_impl_as<K>(
520  rng, n, r, alpha, beta, constant);
522  return beta_distribution_impl_11<K>(
523  rng, n, r, alpha, beta, constant);
525  return beta_distribution_impl_1x<K>(
526  rng, n, r, alpha, beta, constant);
528  return beta_distribution_impl_x1<K>(
529  rng, n, r, alpha, beta, constant);
531  return beta_distribution_impl_c<K>(
532  rng, n, r, alpha, beta, constant);
534  return beta_distribution_impl_j<K>(
535  rng, n, r, alpha, beta, constant);
537  return beta_distribution_impl_a1<K>(
538  rng, n, r, alpha, beta, constant);
540  return beta_distribution_impl_a2<K>(
541  rng, n, r, alpha, beta, constant);
543  return beta_distribution_impl_a3<K>(
544  rng, n, r, alpha, beta, constant);
545  }
546  return 0;
547 }
548 
549 } // namespace vsmc::internal
550 
553 template <typename RealType, typename RNGType>
554 inline void beta_distribution(
555  RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta)
556 {
557  const std::size_t k = 1000;
558  const internal::BetaDistributionConstant<RealType> constant(alpha, beta);
559  while (n > k) {
560  std::size_t m = internal::beta_distribution_impl<k>(
561  rng, k, r, alpha, beta, constant);
562  if (m == 0)
563  break;
564  n -= m;
565  r += m;
566  }
567  std::size_t m =
568  internal::beta_distribution_impl<k>(rng, n, r, alpha, beta, constant);
569  n -= m;
570  r += m;
571  if (n > 0) {
572  BetaDistribution<RealType> dist(alpha, beta);
573  for (std::size_t i = 0; i != n; ++i)
574  r[i] = dist(rng);
575  }
576 }
577 
578 template <typename RealType, typename RNGType>
579 inline void rng_rand(
580  RNGType &rng, BetaDistribution<RealType> &dist, std::size_t n, RealType *r)
581 {
582  dist(rng, n, r);
583 }
584 
585 } // namespace vsmc
586 
587 #endif // VSMC_RNG_BETA_DISTRIBUTION_HPP
Definition: monitor.hpp:49
Standard uniform distribution with open/closed variants.
Definition: common.hpp:512
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:112
void reset(RealType alpha, RealType beta)
std::size_t beta_distribution_impl_c(RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta, const BetaDistributionConstant< RealType > &constant)
void sqrt(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:129
std::size_t beta_distribution_impl_11(RNGType &rng, std::size_t n, RealType *r, RealType, RealType, const BetaDistributionConstant< RealType > &)
std::size_t beta_distribution_impl_j(RNGType &rng, std::size_t n, RealType *r, RealType, RealType, const BetaDistributionConstant< RealType > &constant)
std::size_t beta_distribution_impl(RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta, const BetaDistributionConstant< RealType > &constant)
void u01_oo_distribution(RNGType &rng, std::size_t n, RealType *r)
Generate standard uniform random variates on open-open interval.
void rng_rand(RNGType &rng, BernoulliDistribution< IntType > &dist, std::size_t n, IntType *r)
std::size_t beta_distribution_impl_as(RNGType &rng, std::size_t n, RealType *r, RealType, RealType, const BetaDistributionConstant< RealType > &)
#define VSMC_DEFINE_RNG_DISTRIBUTION_OPERATORS
Definition: common.hpp:286
std::size_t beta_distribution_impl_a2(RNGType &, std::size_t, RealType *, RealType, RealType, const BetaDistributionConstant< RealType > &)
void pow(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:135
#define VSMC_DEFINE_RNG_DISTRIBUTION_2(Name, name, T, T1, p1, v1, T2, p2, v2)
Definition: common.hpp:159
#define VSMC_MNE
Definition: defines.hpp:38
void u01_co_distribution(RNGType &rng, std::size_t n, RealType *r)
Generate standard uniform random variates on closed-open interval.
BetaDistributionConstant(RealType alpha=1, RealType beta=1)
void exp(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:146
std::size_t beta_distribution_impl_x1(RNGType &rng, std::size_t n, RealType *r, RealType, RealType, const BetaDistributionConstant< RealType > &constant)
std::size_t beta_distribution_impl_a1(RNGType &, std::size_t, RealType *, RealType, RealType, const BetaDistributionConstant< RealType > &)
void div(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:128
void sub(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:110
void fma(std::size_t n, const T *a, const T *b, const T *c, T *y)
For , compute .
Definition: vmath.hpp:257
void sin(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:153
void beta_distribution(RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta)
Generating beta random variates.
void add(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:109
bool beta_distribution_check_param(RealType alpha, RealType beta)
void log(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:148
void sqr(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:111
std::size_t beta_distribution_impl_1x(RNGType &rng, std::size_t n, RealType *r, RealType, RealType, const BetaDistributionConstant< RealType > &constant)
std::size_t beta_distribution_impl_a3(RNGType &, std::size_t, RealType *, RealType, RealType, const BetaDistributionConstant< RealType > &)