Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
beta.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__BETA_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__BETA_HPP__
3 
4 #include <boost/math/special_functions/gamma.hpp>
5 #include <boost/random/gamma_distribution.hpp>
6 #include <boost/random/variate_generator.hpp>
7 
8 #include <stan/agrad.hpp>
12 #include <stan/meta/traits.hpp>
13 #include <stan/prob/constants.hpp>
14 #include <stan/prob/traits.hpp>
16 
17 namespace stan {
18 
19  namespace prob {
20 
42  template <bool propto,
43  typename T_y, typename T_scale_succ, typename T_scale_fail,
44  class Policy>
45  typename return_type<T_y,T_scale_succ,T_scale_fail>::type
46  beta_log(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta,
47  const Policy&) {
48  static const char* function = "stan::prob::beta_log(%1%)";
49 
50  using boost::math::digamma;
51  using boost::math::lgamma;
53  using stan::is_vector;
59  using stan::math::log1m;
62 
63  // check if any vectors are zero length
64  if (!(stan::length(y)
65  && stan::length(alpha)
66  && stan::length(beta)))
67  return 0.0;
68 
69  // set up return value accumulator
70  double logp(0.0);
71 
72  // validate args (here done over var, which should be OK)
73  if (!check_finite(function, alpha,
74  "First shape parameter",
75  &logp, Policy()))
76  return logp;
77  if (!check_positive(function, alpha,
78  "First shape parameter",
79  &logp, Policy()))
80  return logp;
81  if (!check_finite(function, beta,
82  "Second shape parameter",
83  &logp, Policy()))
84  return logp;
85  if (!check_positive(function, beta,
86  "Second shape parameter",
87  &logp, Policy()))
88  return logp;
89  if (!check_not_nan(function, y, "Random variable", &logp, Policy()))
90  return logp;
91  if (!(check_consistent_sizes(function,
92  y,alpha,beta,
93  "Random variable","First shape parameter",
94  "Second shape parameter",
95  &logp, Policy())))
96  return logp;
97 
98  // check if no variables are involved and prop-to
100  return 0.0;
101 
102  VectorView<const T_y> y_vec(y);
103  VectorView<const T_scale_succ> alpha_vec(alpha);
104  VectorView<const T_scale_fail> beta_vec(beta);
105  size_t N = max_size(y, alpha, beta);
106 
107  for (size_t n = 0; n < N; n++) {
108  const double y_dbl = value_of(y_vec[n]);
109  if (y_dbl < 0 || y_dbl > 1)
110  return LOG_ZERO;
111  }
112 
113  // set up template expressions wrapping scalars into vector views
115  operands_and_partials(y, alpha, beta);
116 
118  is_vector<T_y>::value> log_y(length(y));
120  is_vector<T_y>::value> log1m_y(length(y));
121 
122  for (size_t n = 0; n < length(y); n++) {
124  log_y[n] = log(value_of(y_vec[n]));
126  log1m_y[n] = log1m(value_of(y_vec[n]));
127  }
128 
130  is_vector<T_scale_succ>::value> lgamma_alpha(length(alpha));
132  is_vector<T_scale_succ>::value> digamma_alpha(length(alpha));
133  for (size_t n = 0; n < length(alpha); n++) {
135  lgamma_alpha[n] = lgamma(value_of(alpha_vec[n]));
137  digamma_alpha[n] = digamma(value_of(alpha_vec[n]));
138  }
139 
141  is_vector<T_scale_fail>::value> lgamma_beta(length(beta));
143  is_vector<T_scale_fail>::value> digamma_beta(length(beta));
144 
145  for (size_t n = 0; n < length(beta); n++) {
147  lgamma_beta[n] = lgamma(value_of(beta_vec[n]));
149  digamma_beta[n] = digamma(value_of(beta_vec[n]));
150  }
151 
155  lgamma_alpha_beta(max_size(alpha,beta));
156 
161  digamma_alpha_beta(max_size(alpha,beta));
162 
163  for (size_t n = 0; n < max_size(alpha,beta); n++) {
164  const double alpha_beta = value_of(alpha_vec[n]) + value_of(beta_vec[n]);
166  lgamma_alpha_beta[n] = lgamma(alpha_beta);
169  digamma_alpha_beta[n] = digamma(alpha_beta);
170  }
171 
172  for (size_t n = 0; n < N; n++) {
173  // pull out values of arguments
174  const double y_dbl = value_of(y_vec[n]);
175  const double alpha_dbl = value_of(alpha_vec[n]);
176  const double beta_dbl = value_of(beta_vec[n]);
177 
178  // log probability
180  logp += lgamma_alpha_beta[n];
182  logp -= lgamma_alpha[n];
184  logp -= lgamma_beta[n];
186  logp += (alpha_dbl-1.0) * log_y[n];
188  logp += (beta_dbl-1.0) * log1m_y[n];
189 
190  // gradients
192  operands_and_partials.d_x1[n] += (alpha_dbl-1)/y_dbl + (beta_dbl-1)/(y_dbl-1);
194  operands_and_partials.d_x2[n]
195  += log_y[n] + digamma_alpha_beta[n] - digamma_alpha[n];
197  operands_and_partials.d_x3[n]
198  += log1m_y[n] + digamma_alpha_beta[n] - digamma_beta[n];
199  }
200  return operands_and_partials.to_var(logp);
201  }
202 
203  template <bool propto,
204  typename T_y, typename T_scale_succ, typename T_scale_fail>
205  inline
207  beta_log(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta) {
208  return beta_log<propto>(y,alpha,beta,stan::math::default_policy());
209  }
210 
211  template <typename T_y, typename T_scale_succ, typename T_scale_fail,
212  class Policy>
214  beta_log(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta,
215  const Policy&) {
216  return beta_log<false>(y,alpha,beta,Policy());
217  }
218 
219  template <typename T_y, typename T_scale_succ, typename T_scale_fail>
220  inline
222  beta_log(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta) {
223  return beta_log<false>(y,alpha,beta,stan::math::default_policy());
224  }
225 
226 
240  template <typename T_y, typename T_scale_succ, typename T_scale_fail, class Policy>
242  beta_cdf(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta,
243  const Policy&) {
244 
245  // Size checks
246  if ( !( stan::length(y) && stan::length(alpha) && stan::length(beta) ) ) return 1.0;
247 
248  // Error checks
249  static const char* function = "stan::prob::beta_cdf(%1%)";
250 
254  using boost::math::tools::promote_args;
256  using stan::math::value_of;
257 
258  double P(1.0);
259 
260  if (!check_finite(function, alpha, "First shape parameter", &P, Policy()))
261  return P;
262 
263  if (!check_positive(function, alpha, "First shape parameter", &P, Policy()))
264  return P;
265 
266  if (!check_finite(function, beta, "Second shape parameter", &P, Policy()))
267  return P;
268 
269  if (!check_positive(function, beta, "Second shape parameter", &P, Policy()))
270  return P;
271 
272  if (!check_not_nan(function, y, "Random variable", &P, Policy()))
273  return P;
274 
275  if (!(check_consistent_sizes(function, y, alpha, beta,
276  "Random variable", "Shape parameter", "Scale Parameter",
277  &P, Policy())))
278  return P;
279 
280  // Wrap arguments in vectors
281  VectorView<const T_y> y_vec(y);
282  VectorView<const T_scale_succ> alpha_vec(alpha);
283  VectorView<const T_scale_fail> beta_vec(beta);
284  size_t N = max_size(y, alpha, beta);
285 
287  operands_and_partials(y, alpha, beta);
288 
289  std::fill(operands_and_partials.all_partials,
290  operands_and_partials.all_partials + operands_and_partials.nvaris, 0.0);
291 
292  // Explicit return for extreme values
293  // The gradients are technically ill-defined, but treated as zero
294  for (size_t i = 0; i < stan::length(y); i++) {
295  if (value_of(y_vec[i]) <= 0)
296  return operands_and_partials.to_var(0.0);
297  }
298 
299  // Compute CDF and its gradients
300  using boost::math::ibeta;
301  using boost::math::ibeta_derivative;
302  using boost::math::digamma;
303 
304  // Cache a few expensive function calls if alpha or beta is a parameter
308  digamma_alpha_vec(max_size(alpha, beta));
309 
313  digamma_beta_vec(max_size(alpha, beta));
314 
318  digamma_sum_vec(max_size(alpha, beta));
319 
323  betafunc_vec(max_size(alpha, beta));
324 
327 
328  for (size_t i = 0; i < N; i++) {
329 
330  const double alpha_dbl = value_of(alpha_vec[i]);
331  const double beta_dbl = value_of(beta_vec[i]);
332 
333  digamma_alpha_vec[i] = digamma(alpha_dbl);
334  digamma_beta_vec[i] = digamma(beta_dbl);
335  digamma_sum_vec[i] = digamma(alpha_dbl + beta_dbl);
336  betafunc_vec[i] = boost::math::beta(alpha_dbl, beta_dbl);
337 
338  }
339 
340  }
341 
342  // Compute vectorized CDF and gradient
343  for (size_t n = 0; n < N; n++) {
344 
345  // Explicit results for extreme values
346  // The gradients are technically ill-defined, but treated as zero
347  if (value_of(y_vec[n]) >= 1.0) continue;
348 
349  // Pull out values
350  const double y_dbl = value_of(y_vec[n]);
351  const double alpha_dbl = value_of(alpha_vec[n]);
352  const double beta_dbl = value_of(beta_vec[n]);
353 
354  // Compute
355  const double Pn = ibeta(alpha_dbl, beta_dbl, y_dbl);
356 
357  P *= Pn;
358 
360  operands_and_partials.d_x1[n] += ibeta_derivative(alpha_dbl, beta_dbl, y_dbl) / Pn;
361 
362  double g1 = 0;
363  double g2 = 0;
364 
367  stan::math::gradRegIncBeta(g1, g2, alpha_dbl, beta_dbl, y_dbl,
368  digamma_alpha_vec[n],
369  digamma_beta_vec[n], digamma_sum_vec[n],
370  betafunc_vec[n]);
371  }
372 
374  operands_and_partials.d_x2[n] += g1 / Pn;
375 
377  operands_and_partials.d_x3[n] += g2 / Pn;
378  }
379 
381  for(size_t n = 0; n < stan::length(y); ++n) operands_and_partials.d_x1[n] *= P;
382  }
383 
385  for(size_t n = 0; n < stan::length(alpha); ++n) operands_and_partials.d_x2[n] *= P;
386  }
387 
389  for(size_t n = 0; n < stan::length(beta); ++n) operands_and_partials.d_x3[n] *= P;
390  }
391 
392  return operands_and_partials.to_var(P);
393  }
394 
395  template <typename T_y, typename T_scale_succ, typename T_scale_fail>
397  beta_cdf(const T_y& y, const T_scale_succ& alpha, const T_scale_fail& beta) {
398  return beta_cdf(y, alpha, beta, stan::math::default_policy());
399  }
400 
401  template <class RNG>
402  inline double
403  beta_rng(const double alpha,
404  const double beta,
405  RNG& rng) {
406  using boost::variate_generator;
407  using boost::random::gamma_distribution;
408  variate_generator<RNG&, gamma_distribution<> >
409  rng_gamma_alpha(rng, gamma_distribution<>(alpha, 1.0));
410  variate_generator<RNG&, gamma_distribution<> >
411  rng_gamma_beta(rng, gamma_distribution<>(beta, 1.0));
412  double a = rng_gamma_alpha();
413  double b = rng_gamma_beta();
414  return a / (a + b);
415  }
416 
417  }
418 }
419 #endif

     [ Stan Home Page ] © 2011–2013, Stan Development Team.