Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations 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/random/negative_binomial_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
7 #include <boost/math/special_functions/digamma.hpp>
10 #include <stan/math/constants.hpp>
13 #include <stan/meta/traits.hpp>
14 #include <stan/prob/traits.hpp>
15 #include <stan/prob/constants.hpp>
20 
21 namespace stan {
22 
23  namespace prob {
24 
25  // NegBinomial(n|alpha,beta) [alpha > 0; beta > 0; n >= 0]
26  template <bool propto,
27  typename T_n,
28  typename T_shape, typename T_inv_scale>
29  typename return_type<T_shape, T_inv_scale>::type
30  neg_binomial_log(const T_n& n,
31  const T_shape& alpha,
32  const T_inv_scale& beta) {
33 
34  static const char* function = "stan::prob::neg_binomial_log(%1%)";
35 
41 
42  // check if any vectors are zero length
43  if (!(stan::length(n)
44  && stan::length(alpha)
45  && stan::length(beta)))
46  return 0.0;
47 
48  double logp(0.0);
49  check_nonnegative(function, n, "Failures variable", &logp);
50  check_positive_finite(function, alpha, "Shape parameter", &logp);
51  check_positive_finite(function, beta, "Inverse scale parameter", &logp);
52  check_consistent_sizes(function,
53  n,alpha,beta,
54  "Failures variable",
55  "Shape parameter","Inverse scale parameter",
56  &logp);
57 
58  // check if no variables are involved and prop-to
60  return 0.0;
61 
65  using boost::math::lgamma;
66 
67  // set up template expressions wrapping scalars into vector views
68  VectorView<const T_n> n_vec(n);
69  VectorView<const T_shape> alpha_vec(alpha);
70  VectorView<const T_inv_scale> beta_vec(beta);
71  size_t size = max_size(n, alpha, beta);
72 
74  operands_and_partials(alpha,beta);
75 
76  size_t len_ab = max_size(alpha,beta);
79  lambda(len_ab);
80  for (size_t i = 0; i < len_ab; ++i)
81  lambda[i] = value_of(alpha_vec[i]) / value_of(beta_vec[i]);
82 
84  log1p_beta(length(beta));
85  for (size_t i = 0; i < length(beta); ++i)
86  log1p_beta[i] = log1p(value_of(beta_vec[i]));
87 
89  log_beta_m_log1p_beta(length(beta));
90  for (size_t i = 0; i < length(beta); ++i)
91  log_beta_m_log1p_beta[i] = log(value_of(beta_vec[i])) - log1p_beta[i];
92 
95  alpha_times_log_beta_over_1p_beta(len_ab);
96  for (size_t i = 0; i < len_ab; ++i)
97  alpha_times_log_beta_over_1p_beta[i]
98  = value_of(alpha_vec[i])
99  * log(value_of(beta_vec[i])
100  / (1.0 + value_of(beta_vec[i])));
101 
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 
111  log_beta(length(beta));
113  for (size_t i = 0; i < length(beta); ++i)
114  log_beta[i] = log(value_of(beta_vec[i]));
115 
119  lambda_m_alpha_over_1p_beta(len_ab);
121  for (size_t i = 0; i < len_ab; ++i)
122  lambda_m_alpha_over_1p_beta[i] =
123  lambda[i]
124  - ( value_of(alpha_vec[i])
125  / (1.0 + value_of(beta_vec[i])) );
126 
127  for (size_t i = 0; i < size; i++) {
128  if (alpha_vec[i] > 1e10) { // reduces numerically to Poisson
130  logp -= lgamma(n_vec[i] + 1.0);
132  logp += multiply_log(n_vec[i], lambda[i]) - lambda[i];
133 
135  operands_and_partials.d_x1[i]
136  += n_vec[i] / value_of(alpha_vec[i])
137  - 1.0 / value_of(beta_vec[i]);
139  operands_and_partials.d_x2[i]
140  += (lambda[i] - n_vec[i]) / value_of(beta_vec[i]) ;
141  } else { // standard density definition
143  if (n_vec[i] != 0)
144  logp += binomial_coefficient_log<double>(n_vec[i]
145  + value_of(alpha_vec[i])
146  - 1.0,
147  n_vec[i]);
149  logp +=
150  alpha_times_log_beta_over_1p_beta[i]
151  - n_vec[i] * log1p_beta[i];
152 
154  operands_and_partials.d_x1[i]
155  += digamma(value_of(alpha_vec[i]) + n_vec[i])
156  - digamma_alpha[i]
157  + log_beta_m_log1p_beta[i];
159  operands_and_partials.d_x2[i]
160  += lambda_m_alpha_over_1p_beta[i]
161  - n_vec[i] / (value_of(beta_vec[i]) + 1.0);
162  }
163  }
164  return operands_and_partials.to_var(logp);
165  }
166 
167  template <typename T_n,
168  typename T_shape, typename T_inv_scale>
169  inline
171  neg_binomial_log(const T_n& n,
172  const T_shape& alpha,
173  const T_inv_scale& beta) {
174  return neg_binomial_log<false>(n,alpha,beta);
175  }
176 
177  // Negative Binomial CDF
178  template <typename T_n, typename T_shape,
179  typename T_inv_scale>
181  neg_binomial_cdf(const T_n& n, const T_shape& alpha,
182  const T_inv_scale& beta) {
183  static const char* function = "stan::prob::neg_binomial_cdf(%1%)";
184 
189 
190  // Ensure non-zero arugment lengths
191  if (!(stan::length(n) && stan::length(alpha) && stan::length(beta)))
192  return 1.0;
193 
194  double P(1.0);
195 
196  // Validate arguments
197  check_positive_finite(function, alpha, "Shape parameter", &P);
198  check_positive_finite(function, beta, "Inverse scale parameter", &P);
199  check_consistent_sizes(function,
200  n, alpha, beta,
201  "Failures variable",
202  "Shape parameter",
203  "Inverse scale parameter",
204  &P);
205 
206  // Wrap arguments in vector views
207  VectorView<const T_n> n_vec(n);
208  VectorView<const T_shape> alpha_vec(alpha);
209  VectorView<const T_inv_scale> beta_vec(beta);
210  size_t size = max_size(n, alpha, beta);
211 
212  // Compute vectorized CDF and gradient
213  using stan::math::value_of;
214  using boost::math::ibeta;
215  using boost::math::ibeta_derivative;
216 
217  using boost::math::digamma;
218 
220  operands_and_partials(alpha, beta);
221 
222  // Explicit return for extreme values
223  // The gradients are technically ill-defined, but treated as zero
224  for (size_t i = 0; i < stan::length(n); i++) {
225  if (value_of(n_vec[i]) <= 0)
226  return operands_and_partials.to_var(0.0);
227  }
228 
229  // Cache a few expensive function calls if alpha is a parameter
232  digammaN_vec(stan::length(alpha));
235  digammaAlpha_vec(stan::length(alpha));
238  digammaSum_vec(stan::length(alpha));
241  betaFunc_vec(stan::length(alpha));
242 
244 
245  for (size_t i = 0; i < stan::length(alpha); i++) {
246  const double n_dbl = value_of(n_vec[i]);
247  const double alpha_dbl = value_of(alpha_vec[i]);
248 
249  digammaN_vec[i] = digamma(n_dbl + 1);
250  digammaAlpha_vec[i] = digamma(alpha_dbl);
251  digammaSum_vec[i] = digamma(n_dbl + alpha_dbl + 1);
252  betaFunc_vec[i] = boost::math::beta(n_dbl + 1, alpha_dbl);
253  }
254  }
255 
256  for (size_t i = 0; i < size; i++) {
257 
258  // Explicit results for extreme values
259  // The gradients are technically ill-defined, but treated as zero
260  if (value_of(n_vec[i])
261  == std::numeric_limits<double>::infinity())
262  continue;
263 
264  const double n_dbl = value_of(n_vec[i]);
265  const double alpha_dbl = value_of(alpha_vec[i]);
266  const double beta_dbl = value_of(beta_vec[i]);
267 
268  const double p_dbl = beta_dbl / (1.0 + beta_dbl);
269  const double d_dbl = 1.0 / ( (1.0 + beta_dbl)
270  * (1.0 + beta_dbl) );
271 
272  const double Pi = ibeta(alpha_dbl, n_dbl + 1.0, p_dbl);
273 
274  P *= Pi;
275 
277 
278  double g1 = 0;
279  double g2 = 0;
280 
281  stan::math::gradRegIncBeta(g1, g2, alpha_dbl,
282  n_dbl + 1, p_dbl,
283  digammaAlpha_vec[i],
284  digammaN_vec[i],
285  digammaSum_vec[i],
286  betaFunc_vec[i]);
287 
288  operands_and_partials.d_x1[i]
289  += g1 / Pi;
290  }
291 
293  operands_and_partials.d_x2[i]
294  += d_dbl * ibeta_derivative(alpha_dbl, n_dbl + 1, p_dbl)
295  / Pi;
296 
297  }
298 
300  for(size_t i = 0; i < stan::length(alpha); ++i)
301  operands_and_partials.d_x1[i] *= P;
302 
304  for(size_t i = 0; i < stan::length(beta); ++i)
305  operands_and_partials.d_x2[i] *= P;
306 
307  return operands_and_partials.to_var(P);
308 
309  }
310 
311  template <typename T_n, typename T_shape,
312  typename T_inv_scale>
314  neg_binomial_cdf_log(const T_n& n, const T_shape& alpha,
315  const T_inv_scale& beta) {
316  static const char* function = "stan::prob::neg_binomial_cdf_log(%1%)";
317 
322 
323  // Ensure non-zero arugment lengths
324  if (!(stan::length(n) && stan::length(alpha) && stan::length(beta)))
325  return 0.0;
326 
327  double P(0.0);
328 
329  // Validate arguments
330  check_positive_finite(function, alpha, "Shape parameter", &P);
331  check_positive_finite(function, beta, "Inverse scale parameter", &P);
332  check_consistent_sizes(function,
333  n, alpha, beta,
334  "Failures variable",
335  "Shape parameter",
336  "Inverse scale parameter",
337  &P);
338 
339  // Wrap arguments in vector views
340  VectorView<const T_n> n_vec(n);
341  VectorView<const T_shape> alpha_vec(alpha);
342  VectorView<const T_inv_scale> beta_vec(beta);
343  size_t size = max_size(n, alpha, beta);
344 
345  // Compute vectorized cdf_log and gradient
346  using stan::math::value_of;
347  using boost::math::ibeta;
348  using boost::math::ibeta_derivative;
349 
350  using boost::math::digamma;
351 
353  operands_and_partials(alpha, beta);
354 
355  // Explicit return for extreme values
356  // The gradients are technically ill-defined, but treated as zero
357  for (size_t i = 0; i < stan::length(n); i++) {
358  if (value_of(n_vec[i]) <= 0)
359  return operands_and_partials.to_var(stan::math::negative_infinity());
360  }
361 
362  // Cache a few expensive function calls if alpha is a parameter
365  digammaN_vec(stan::length(alpha));
368  digammaAlpha_vec(stan::length(alpha));
371  digammaSum_vec(stan::length(alpha));
374  betaFunc_vec(stan::length(alpha));
375 
377  for (size_t i = 0; i < stan::length(alpha); i++) {
378  const double n_dbl = value_of(n_vec[i]);
379  const double alpha_dbl = value_of(alpha_vec[i]);
380 
381  digammaN_vec[i] = digamma(n_dbl + 1);
382  digammaAlpha_vec[i] = digamma(alpha_dbl);
383  digammaSum_vec[i] = digamma(n_dbl + alpha_dbl + 1);
384  betaFunc_vec[i] = boost::math::beta(n_dbl + 1, alpha_dbl);
385  }
386  }
387 
388  for (size_t i = 0; i < size; i++) {
389  // Explicit results for extreme values
390  // The gradients are technically ill-defined, but treated as zero
391  if (value_of(n_vec[i])
392  == std::numeric_limits<double>::infinity())
393  continue;
394 
395  const double n_dbl = value_of(n_vec[i]);
396  const double alpha_dbl = value_of(alpha_vec[i]);
397  const double beta_dbl = value_of(beta_vec[i]);
398  const double p_dbl = beta_dbl / (1.0 + beta_dbl);
399  const double d_dbl = 1.0 / ( (1.0 + beta_dbl)
400  * (1.0 + beta_dbl) );
401  const double Pi = ibeta(alpha_dbl, n_dbl + 1.0, p_dbl);
402 
403  P += log(Pi);
404 
406  double g1 = 0;
407  double g2 = 0;
408 
409  stan::math::gradRegIncBeta(g1, g2, alpha_dbl,
410  n_dbl + 1, p_dbl,
411  digammaAlpha_vec[i],
412  digammaN_vec[i],
413  digammaSum_vec[i],
414  betaFunc_vec[i]);
415  operands_and_partials.d_x1[i] += g1 / Pi;
416  }
418  operands_and_partials.d_x2[i]
419  += d_dbl * ibeta_derivative(alpha_dbl, n_dbl + 1, p_dbl) / Pi;
420  }
421 
422  return operands_and_partials.to_var(P);
423  }
424 
425  template <typename T_n, typename T_shape,
426  typename T_inv_scale>
428  neg_binomial_ccdf_log(const T_n& n, const T_shape& alpha,
429  const T_inv_scale& beta) {
430  static const char* function = "stan::prob::neg_binomial_ccdf_log(%1%)";
431 
436 
437  // Ensure non-zero arugment lengths
438  if (!(stan::length(n) && stan::length(alpha) && stan::length(beta)))
439  return 0.0;
440 
441  double P(0.0);
442 
443  // Validate arguments
444  check_positive_finite(function, alpha, "Shape parameter", &P);
445  check_positive_finite(function, beta, "Inverse scale parameter", &P);
446  check_consistent_sizes(function,
447  n, alpha, beta,
448  "Failures variable",
449  "Shape parameter",
450  "Inverse scale parameter",
451  &P);
452 
453  // Wrap arguments in vector views
454  VectorView<const T_n> n_vec(n);
455  VectorView<const T_shape> alpha_vec(alpha);
456  VectorView<const T_inv_scale> beta_vec(beta);
457  size_t size = max_size(n, alpha, beta);
458 
459  // Compute vectorized cdf_log and gradient
460  using stan::math::value_of;
461  using boost::math::ibeta;
462  using boost::math::ibeta_derivative;
463 
464  using boost::math::digamma;
465 
467  operands_and_partials(alpha, beta);
468 
469  // Explicit return for extreme values
470  // The gradients are technically ill-defined, but treated as zero
471  for (size_t i = 0; i < stan::length(n); i++) {
472  if (value_of(n_vec[i]) <= 0)
473  return operands_and_partials.to_var(0.0);
474  }
475 
476  // Cache a few expensive function calls if alpha is a parameter
479  digammaN_vec(stan::length(alpha));
482  digammaAlpha_vec(stan::length(alpha));
485  digammaSum_vec(stan::length(alpha));
488  betaFunc_vec(stan::length(alpha));
489 
491  for (size_t i = 0; i < stan::length(alpha); i++) {
492  const double n_dbl = value_of(n_vec[i]);
493  const double alpha_dbl = value_of(alpha_vec[i]);
494 
495  digammaN_vec[i] = digamma(n_dbl + 1);
496  digammaAlpha_vec[i] = digamma(alpha_dbl);
497  digammaSum_vec[i] = digamma(n_dbl + alpha_dbl + 1);
498  betaFunc_vec[i] = boost::math::beta(n_dbl + 1, alpha_dbl);
499  }
500  }
501 
502  for (size_t i = 0; i < size; i++) {
503  // Explicit results for extreme values
504  // The gradients are technically ill-defined, but treated as zero
505  if (value_of(n_vec[i])
506  == std::numeric_limits<double>::infinity())
507  return operands_and_partials.to_var(stan::math::negative_infinity());
508 
509  const double n_dbl = value_of(n_vec[i]);
510  const double alpha_dbl = value_of(alpha_vec[i]);
511  const double beta_dbl = value_of(beta_vec[i]);
512  const double p_dbl = beta_dbl / (1.0 + beta_dbl);
513  const double d_dbl = 1.0 / ( (1.0 + beta_dbl)
514  * (1.0 + beta_dbl) );
515  const double Pi = 1.0 - ibeta(alpha_dbl, n_dbl + 1.0, p_dbl);
516 
517  P += log(Pi);
518 
520  double g1 = 0;
521  double g2 = 0;
522 
523  stan::math::gradRegIncBeta(g1, g2, alpha_dbl,
524  n_dbl + 1, p_dbl,
525  digammaAlpha_vec[i],
526  digammaN_vec[i],
527  digammaSum_vec[i],
528  betaFunc_vec[i]);
529  operands_and_partials.d_x1[i] -= g1 / Pi;
530  }
532  operands_and_partials.d_x2[i]
533  -= d_dbl * ibeta_derivative(alpha_dbl, n_dbl + 1, p_dbl) / Pi;
534  }
535 
536  return operands_and_partials.to_var(P);
537  }
538 
539  template <class RNG>
540  inline int
541  neg_binomial_rng(const double alpha,
542  const double beta,
543  RNG& rng) {
544  using boost::variate_generator;
545  using boost::random::negative_binomial_distribution;
546 
547  static const char* function = "stan::prob::neg_binomial_rng(%1%)";
548 
550 
551  check_positive_finite(function, alpha, "Shape parameter", (double*)0);
552  check_positive_finite(function, beta, "Inverse scale parameter",
553  (double*)0);
554 
556  rng),rng);
557  }
558  }
559 }
560 #endif
void gradRegIncBeta(double &g1, double &g2, double a, double b, double z, double digammaA, double digammaB, double digammaSum, double betaAB)
T_return_type to_var(double logp)
bool check_positive_finite(const char *function, const T_y &y, const char *name, T_result *result)
boost::math::tools::promote_args< T_a, T_b >::type multiply_log(const T_a a, const T_b b)
Calculated the value of the first argument times log of the second argument while behaving properly w...
size_t length(const T &)
Definition: traits.hpp:159
boost::math::tools::promote_args< T_N, T_n >::type binomial_coefficient_log(const T_N N, const T_n n)
Return the log of the binomial coefficient for the specified arguments.
DoubleVectorView allocates double values to be used as intermediate values.
Definition: traits.hpp:358
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
fvar< T > lgamma(const fvar< T > &x)
Definition: lgamma.hpp:15
A variable implementation that stores operands and derivatives with respect to the variable...
boost::math::tools::promote_args< typename scalar_type< T1 >::type, typename scalar_type< T2 >::type, typename scalar_type< T3 >::type, typename scalar_type< T4 >::type, typename scalar_type< T5 >::type, typename scalar_type< T6 >::type >::type type
Definition: traits.hpp:406
Metaprogram to determine if a type has a base scalar type that can be assigned to type double...
Definition: traits.hpp:57
double value_of(const T x)
Return the value of the specified scalar argument converted to a double value.
Definition: value_of.hpp:24
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
Definition: traits.hpp:35
int poisson_rng(const double lambda, RNG &rng)
Definition: poisson.hpp:384
return_type< T_shape, T_inv_scale >::type neg_binomial_ccdf_log(const T_n &n, const T_shape &alpha, const T_inv_scale &beta)
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
var ibeta(const var &a, const var &b, const var &x)
The normalized incomplete beta function of a, b, and x.
Definition: ibeta.hpp:223
bool check_nonnegative(const char *function, const T_y &y, const char *name, T_result *result)
bool check_consistent_sizes(const char *function, const T1 &x1, const T2 &x2, const char *name1, const char *name2, T_result *result)
size_t max_size(const T1 &x1, const T2 &x2)
Definition: traits.hpp:191
return_type< T_shape, T_inv_scale >::type neg_binomial_log(const T_n &n, const T_shape &alpha, const T_inv_scale &beta)
return_type< T_shape, T_inv_scale >::type neg_binomial_cdf(const T_n &n, const T_shape &alpha, const T_inv_scale &beta)
fvar< T > multiply_log(const fvar< T > &x1, const fvar< T > &x2)
int size(const std::vector< T > &x)
Definition: size.hpp:11
return_type< T_shape, T_inv_scale >::type neg_binomial_cdf_log(const T_n &n, const T_shape &alpha, const T_inv_scale &beta)
fvar< T > digamma(const fvar< T > &x)
Definition: digamma.hpp:16
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
int neg_binomial_rng(const double alpha, const double beta, RNG &rng)
fvar< T > log(const fvar< T > &x)
Definition: log.hpp:15
VectorView is a template metaprogram that takes its argument and allows it to be used like a vector...
Definition: traits.hpp:275
double gamma_rng(const double alpha, const double beta, RNG &rng)
Definition: gamma.hpp:491
fvar< T > log1p(const fvar< T > &x)
Definition: log1p.hpp:16
double negative_infinity()
Return negative infinity.
Definition: constants.hpp:123

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