Stan  1.1
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
neg_binomial.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__NEG_BINOMIAL_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__NEG_BINOMIAL_HPP__
3 
4 #include <boost/math/special_functions/digamma.hpp>
5 #include <stan/agrad.hpp>
8 #include <stan/meta/traits.hpp>
9 #include <stan/prob/traits.hpp>
10 #include <stan/prob/constants.hpp>
12 
13 namespace stan {
14 
15  namespace prob {
16 
17  // NegBinomial(n|alpha,beta) [alpha > 0; beta > 0; n >= 0]
18  template <bool propto,
19  typename T_n,
20  typename T_shape, typename T_inv_scale,
21  class Policy>
22  typename return_type<T_shape, T_inv_scale>::type
23  neg_binomial_log(const T_n& n,
24  const T_shape& alpha,
25  const T_inv_scale& beta,
26  const Policy&) {
27 
28  static const char* function = "stan::prob::neg_binomial_log(%1%)";
29 
36 
37  // check if any vectors are zero length
38  if (!(stan::length(n)
39  && stan::length(alpha)
40  && stan::length(beta)))
41  return 0.0;
42 
43  double logp(0.0);
44  if (!check_nonnegative(function, n, "Failures variable", &logp, Policy()))
45  return logp;
46  if (!check_finite(function, alpha, "Shape parameter", &logp, Policy()))
47  return logp;
48  if (!check_positive(function, alpha, "Shape parameter", &logp, Policy()))
49  return logp;
50  if (!check_finite(function, beta, "Inverse scale parameter",
51  &logp, Policy()))
52  return logp;
53  if (!check_positive(function, beta, "Inverse scale parameter",
54  &logp, Policy()))
55  return logp;
56  if (!(check_consistent_sizes(function,
57  n,alpha,beta,
58  "Failures variable",
59  "Shape parameter","Inverse scale parameter",
60  &logp, Policy())))
61  return logp;
62 
63  // check if no variables are involved and prop-to
65  return 0.0;
66 
69  using boost::math::digamma;
70 
71  // set up template expressions wrapping scalars into vector views
72  VectorView<const T_n> n_vec(n);
73  VectorView<const T_shape> alpha_vec(alpha);
74  VectorView<const T_inv_scale> beta_vec(beta);
75  size_t size = max_size(n, alpha, beta);
76 
77  agrad::OperandsAndPartials<T_shape,T_inv_scale> operands_and_partials(alpha,beta);
78 
79  size_t len_ab = max_size(alpha,beta);
81  lambda(len_ab);
82  for (size_t i = 0; i < len_ab; ++i)
83  lambda[i] = value_of(alpha_vec[i]) / value_of(beta_vec[i]);
84 
86  log1p_beta(length(beta));
87  for (size_t i = 0; i < length(beta); ++i)
88  log1p_beta[i] = log1p(value_of(beta_vec[i]));
89 
91  log_beta_m_log1p_beta(length(beta));
92  for (size_t i = 0; i < length(beta); ++i)
93  log_beta_m_log1p_beta[i] = log(value_of(beta_vec[i])) - log1p_beta[i];
94 
96  alpha_times_log_beta_over_1p_beta(len_ab);
97  for (size_t i = 0; i < len_ab; ++i)
98  alpha_times_log_beta_over_1p_beta[i]
99  = value_of(alpha_vec[i])
100  * log(value_of(beta_vec[i])
101  / (1.0 + value_of(beta_vec[i])));
102 
104  digamma_alpha(length(alpha));
106  for (size_t i = 0; i < length(alpha); ++i)
107  digamma_alpha[i] = digamma(value_of(alpha_vec[i]));
108 
110  log_beta(length(beta));
112  for (size_t i = 0; i < length(beta); ++i)
113  log_beta[i] = log(value_of(beta_vec[i]));
114 
117  lambda_m_alpha_over_1p_beta(len_ab);
119  for (size_t i = 0; i < len_ab; ++i)
120  lambda_m_alpha_over_1p_beta[i] =
121  lambda[i]
122  - ( value_of(alpha_vec[i])
123  / (1.0 + value_of(beta_vec[i])) );
124 
125  for (size_t i = 0; i < size; i++) {
126  if (alpha_vec[i] > 1e10) { // reduces numerically to Poisson
128  logp -= lgamma(n_vec[i] + 1.0);
130  logp += multiply_log(n_vec[i], lambda[i]) - lambda[i];
131 
133  operands_and_partials.d_x1[i]
134  += n_vec[i] / value_of(alpha_vec[i])
135  - 1.0 / value_of(beta_vec[i]);
137  operands_and_partials.d_x2[i]
138  += (lambda[i] - n_vec[i]) / value_of(beta_vec[i]) ;
139  } else { // standard density definition
141  if (n_vec[i] != 0)
142  logp += binomial_coefficient_log<double>(n_vec[i]
143  + value_of(alpha_vec[i]) - 1.0,
144  n_vec[i]);
146  logp +=
147  alpha_times_log_beta_over_1p_beta[i]
148  - n_vec[i] * log1p_beta[i];
149 
151  operands_and_partials.d_x1[i]
152  += digamma(value_of(alpha_vec[i]) + n_vec[i])
153  - digamma_alpha[i]
154  + log_beta_m_log1p_beta[i];
156  operands_and_partials.d_x2[i]
157  += lambda_m_alpha_over_1p_beta[i]
158  - n_vec[i] / (value_of(beta_vec[i]) + 1.0);
159  }
160  }
161  return operands_and_partials.to_var(logp);
162  }
163 
164  template <bool propto,
165  typename T_n,
166  typename T_shape, typename T_inv_scale>
167  inline
169  neg_binomial_log(const T_n& n,
170  const T_shape& alpha,
171  const T_inv_scale& beta) {
172  return neg_binomial_log<propto>(n,alpha,beta,
174  }
175 
176  template <typename T_n,
177  typename T_shape, typename T_inv_scale,
178  class Policy>
179  inline
181  neg_binomial_log(const T_n& n,
182  const T_shape& alpha,
183  const T_inv_scale& beta,
184  const Policy&) {
185  return neg_binomial_log<false>(n,alpha,beta,Policy());
186  }
187 
188  template <typename T_n,
189  typename T_shape, typename T_inv_scale>
190  inline
192  neg_binomial_log(const T_n& n,
193  const T_shape& alpha,
194  const T_inv_scale& beta) {
195  return neg_binomial_log<false>(n,alpha,beta,
197  }
198 
199  // Negative Binomial CDF
200  template <bool propto, typename T_n, typename T_shape, typename T_inv_scale,
201  class Policy>
203  neg_binomial_cdf(const T_n& n, const T_shape& alpha, const T_inv_scale& beta,
204  const Policy&) {
205 
206  static const char* function = "stan::prob::neg_binomial_cdf(%1%)";
207 
213 
214  // Ensure non-zero arugment lengths
215  if (!(stan::length(n) && stan::length(alpha) && stan::length(beta)))
216  return 0.0;
217 
218  double P(1.0);
219 
220  // Validate arguments
221  if (!check_nonnegative(function, n, "Failures variable", &P, Policy()))
222  return P;
223 
224  if (!check_finite(function, alpha, "Shape parameter", &P, Policy()))
225  return P;
226 
227  if (!check_positive(function, alpha, "Shape parameter", &P, Policy()))
228  return P;
229 
230  if (!check_finite(function, beta, "Inverse scale parameter",
231  &P, Policy()))
232  return P;
233 
234  if (!check_positive(function, beta, "Inverse scale parameter",
235  &P, Policy()))
236  return P;
237 
238  if (!(check_consistent_sizes(function,
239  n, alpha, beta,
240  "Failures variable",
241  "Shape parameter","Inverse scale parameter",
242  &P, Policy())))
243  return P;
244 
245  // Return if everything is constant and only proportionality is required
247  return 0.0;
248 
249  // Wrap arguments in vector views
250  VectorView<const T_n> n_vec(n);
251  VectorView<const T_shape> alpha_vec(alpha);
252  VectorView<const T_inv_scale> beta_vec(beta);
253  size_t size = max_size(n, alpha, beta);
254 
255  // Compute vectorized CDF and gradient
256  using stan::math::value_of;
257  using boost::math::ibetac;
258  using boost::math::ibeta_derivative;
259 
260  using boost::math::digamma;
261 
262  // Cache a few expensive function calls if alpha is a parameter
264  is_vector<T_shape>::value> digammaN_vec(stan::length(alpha));
266  is_vector<T_shape>::value> digammaAlpha_vec(stan::length(alpha));
268  is_vector<T_shape>::value> digammaSum_vec(stan::length(alpha));
270  is_vector<T_shape>::value> betaFunc_vec(stan::length(alpha));
271 
273  for (size_t i = 0; i < stan::length(alpha); i++) {
274  const double n_dbl = value_of(n_vec[i]);
275  const double alpha_dbl = value_of(alpha_vec[i]);
276 
277  digammaN_vec[i] = digamma(n_dbl);
278  digammaAlpha_vec[i] = digamma(alpha_dbl + 1);
279  digammaSum_vec[i] = digamma(n_dbl + alpha_dbl + 1);
280  betaFunc_vec[i] = boost::math::beta(n_dbl, alpha_dbl + 1);
281  }
282  }
283 
285  operands_and_partials(alpha, beta);
286 
287  std::fill(operands_and_partials.all_partials,
288  operands_and_partials.all_partials + operands_and_partials.nvaris,
289  0.0);
290 
291  for (size_t i = 0; i < size; i++) {
292  const double n_dbl = value_of(n_vec[i]);
293  const double alpha_dbl = value_of(alpha_vec[i]);
294  const double beta_dbl = value_of(beta_vec[i]);
295 
296  const double p_dbl = beta_dbl / (1.0 + beta_dbl);
297  const double d_dbl = 1.0 / ( (1.0 + beta_dbl) * (1.0 + beta_dbl) );
298 
299  const double Pi = ibetac(alpha_dbl + 1, n_dbl, p_dbl);
300 
301  P *= Pi;
302 
304  double g1 = 0;
305  double g2 = 0;
306 
307  stan::math::gradRegIncBeta(g1, g2, alpha_dbl + 1, n_dbl, p_dbl,
308  digammaAlpha_vec[i], digammaN_vec[i],
309  digammaSum_vec[i], betaFunc_vec[i]);
310 
311  operands_and_partials.d_x1[n]
312  += - g1 / Pi;
313  }
314 
316  operands_and_partials.d_x2[i]
317  += - d_dbl * ibeta_derivative(alpha_dbl + 1, n_dbl, p_dbl) / Pi;
318 
319  }
320 
321  for (size_t i = 0; i < size; i++) {
323  operands_and_partials.d_x1[i] *= P;
325  operands_and_partials.d_x2[i] *= P;
326  }
327 
328  return P;
329  }
330 
331  template <bool propto, typename T_n, typename T_shape, typename T_inv_scale>
333  neg_binomial_cdf(const T_n& n, const T_shape& alpha, const T_inv_scale& beta) {
334  return neg_binomial_cdf<propto>(n, alpha, beta, stan::math::default_policy());
335  }
336 
337  template <typename T_n, typename T_shape, typename T_inv_scale, class Policy>
339  neg_binomial_cdf(const T_n& n, const T_shape& alpha, const T_inv_scale& beta,
340  const Policy&) {
341  return neg_binomial_cdf<false>(n, alpha, beta, Policy());
342  }
343 
344  template <typename T_n, typename T_shape, typename T_inv_scale>
346  neg_binomial_cdf(const T_n& n, const T_shape& alpha, const T_inv_scale& beta) {
347  return neg_binomial_cdf<false>(n, alpha, beta, stan::math::default_policy());
348  }
349 
350 
351  }
352 }
353 #endif

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