Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
binomial.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__BINOMIAL_HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__BINOMIAL_HPP
3 
4 #include <boost/random/binomial_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
15 #include <stan/meta/traits.hpp>
16 #include <stan/prob/traits.hpp>
17 #include <stan/prob/constants.hpp>
18 
20 
21 namespace stan {
22 
23  namespace prob {
24 
25  // Binomial(n|N,theta) [N >= 0; 0 <= n <= N; 0 <= theta <= 1]
26  template <bool propto,
27  typename T_n,
28  typename T_N,
29  typename T_prob>
30  typename return_type<T_prob>::type
31  binomial_log(const T_n& n,
32  const T_N& N,
33  const T_prob& theta) {
34 
35  static const char* function = "stan::prob::binomial_log(%1%)";
36 
43 
44  // check if any vectors are zero length
45  if (!(stan::length(n)
46  && stan::length(N)
47  && stan::length(theta)))
48  return 0.0;
49 
50  double logp = 0;
51  check_bounded(function, n, 0, N,
52  "Successes variable",
53  &logp);
54  check_nonnegative(function, N,
55  "Population size parameter",
56  &logp);
57  check_finite(function, theta,
58  "Probability parameter",
59  &logp);
60  check_bounded(function, theta, 0.0, 1.0,
61  "Probability parameter",
62  &logp);
63  check_consistent_sizes(function,
64  n,N,theta,
65  "Successes variable",
66  "Population size parameter",
67  "Probability parameter",
68  &logp);
69 
70 
71  // check if no variables are involved and prop-to
73  return 0.0;
74 
75  // set up template expressions wrapping scalars into vector views
76  VectorView<const T_n> n_vec(n);
77  VectorView<const T_N> N_vec(N);
78  VectorView<const T_prob> theta_vec(theta);
79  size_t size = max_size(n, N, theta);
80 
81  agrad::OperandsAndPartials<T_prob> operands_and_partials(theta);
82 
85  using stan::math::log1m;
86 
88  for (size_t i = 0; i < size; ++i)
89  logp += binomial_coefficient_log(N_vec[i],n_vec[i]);
90 
92  for (size_t i = 0; i < length(theta); ++i)
93  log1m_theta[i] = log1m(value_of(theta_vec[i]));
94 
95  // no test for include_summand because return if not live
96  for (size_t i = 0; i < size; ++i)
97  logp += multiply_log(n_vec[i],value_of(theta_vec[i]))
98  + (N_vec[i] - n_vec[i]) * log1m_theta[i];
99 
100  if (length(theta) == 1) {
101  double temp1 = 0;
102  double temp2 = 0;
103  for (size_t i = 0; i < size; ++i) {
104  temp1 += n_vec[i];
105  temp2 += N_vec[i] - n_vec[i];
106  }
108  operands_and_partials.d_x1[0]
109  += temp1 / value_of(theta_vec[0])
110  - temp2 / (1.0 - value_of(theta_vec[0]));
111  }
112  } else {
114  for (size_t i = 0; i < size; ++i)
115  operands_and_partials.d_x1[i]
116  += n_vec[i] / value_of(theta_vec[i])
117  - (N_vec[i] - n_vec[i]) / (1.0 - value_of(theta_vec[i]));
118  }
119  }
120 
121  return operands_and_partials.to_var(logp);
122  }
123 
124  template <typename T_n,
125  typename T_N,
126  typename T_prob>
127  inline
129  binomial_log(const T_n& n,
130  const T_N& N,
131  const T_prob& theta) {
132  return binomial_log<false>(n,N,theta);
133  }
134 
135  // BinomialLogit(n|N,alpha) [N >= 0; 0 <= n <= N]
136  // BinomialLogit(n|N,alpha) = Binomial(n|N,inv_logit(alpha))
137  template <bool propto,
138  typename T_n,
139  typename T_N,
140  typename T_prob>
142  binomial_logit_log(const T_n& n,
143  const T_N& N,
144  const T_prob& alpha) {
145 
146  static const char* function = "stan::prob::binomial_logit_log(%1%)";
147 
151  using stan::math::value_of;
154 
155  // check if any vectors are zero length
156  if (!(stan::length(n)
157  && stan::length(N)
158  && stan::length(alpha)))
159  return 0.0;
160 
161  double logp = 0;
162  check_bounded(function, n, 0, N,
163  "Successes variable",
164  &logp);
165  check_nonnegative(function, N,
166  "Population size parameter",
167  &logp);
168  check_finite(function, alpha,
169  "Probability parameter",
170  &logp);
171  check_consistent_sizes(function,
172  n,N,alpha,
173  "Successes variable",
174  "Population size parameter",
175  "Probability parameter",
176  &logp);
177 
178  // check if no variables are involved and prop-to
180  return 0.0;
181 
182  // set up template expressions wrapping scalars into vector views
183  VectorView<const T_n> n_vec(n);
184  VectorView<const T_N> N_vec(N);
185  VectorView<const T_prob> alpha_vec(alpha);
186  size_t size = max_size(n, N, alpha);
187 
188  agrad::OperandsAndPartials<T_prob> operands_and_partials(alpha);
189 
192  using stan::math::inv_logit;
193 
195  for (size_t i = 0; i < size; ++i)
196  logp += binomial_coefficient_log(N_vec[i],n_vec[i]);
197 
198  DoubleVectorView<true,is_vector<T_prob>::value> log_inv_logit_alpha(length(alpha));
199  for (size_t i = 0; i < length(alpha); ++i)
200  log_inv_logit_alpha[i] = log_inv_logit(value_of(alpha_vec[i]));
201 
202  DoubleVectorView<true,is_vector<T_prob>::value> log_inv_logit_neg_alpha(length(alpha));
203  for (size_t i = 0; i < length(alpha); ++i)
204  log_inv_logit_neg_alpha[i] = log_inv_logit(-value_of(alpha_vec[i]));
205 
206  for (size_t i = 0; i < size; ++i)
207  logp += n_vec[i] * log_inv_logit_alpha[i]
208  + (N_vec[i] - n_vec[i]) * log_inv_logit_neg_alpha[i];
209 
210  if (length(alpha) == 1) {
211  double temp1 = 0;
212  double temp2 = 0;
213  for (size_t i = 0; i < size; ++i) {
214  temp1 += n_vec[i];
215  temp2 += N_vec[i] - n_vec[i];
216  }
218  operands_and_partials.d_x1[0]
219  += temp1 * inv_logit(-value_of(alpha_vec[0]))
220  - temp2 * inv_logit(value_of(alpha_vec[0]));
221  }
222  } else {
224  for (size_t i = 0; i < size; ++i)
225  operands_and_partials.d_x1[i]
226  += n_vec[i] * inv_logit(-value_of(alpha_vec[i]))
227  - (N_vec[i] - n_vec[i]) * inv_logit(value_of(alpha_vec[i]));
228  }
229  }
230 
231  return operands_and_partials.to_var(logp);
232  }
233 
234  template <typename T_n,
235  typename T_N,
236  typename T_prob>
237  inline
239  binomial_logit_log(const T_n& n,
240  const T_N& N,
241  const T_prob& alpha) {
242  return binomial_logit_log<false>(n,N,alpha);
243  }
244 
245 
246  // Binomial CDF
247  template <typename T_n, typename T_N, typename T_prob>
249  binomial_cdf(const T_n& n, const T_N& N, const T_prob& theta) {
250 
251  static const char* function = "stan::prob::binomial_cdf(%1%)";
252 
256  using stan::math::value_of;
259 
260  // Ensure non-zero arguments lenghts
261  if (!(stan::length(n) && stan::length(N) && stan::length(theta)))
262  return 1.0;
263 
264  double P(1.0);
265 
266  // Validate arguments
267  check_nonnegative(function, N, "Population size parameter", &P);
268  check_finite(function, theta, "Probability parameter", &P);
269  check_bounded(function, theta, 0.0, 1.0,
270  "Probability parameter", &P);
271  check_consistent_sizes(function, n, N, theta,
272  "Successes variable", "Population size parameter",
273  "Probability parameter",
274  &P);
275 
276  // Wrap arguments in vector views
277  VectorView<const T_n> n_vec(n);
278  VectorView<const T_N> N_vec(N);
279  VectorView<const T_prob> theta_vec(theta);
280  size_t size = max_size(n, N, theta);
281 
282  // Compute vectorized CDF and gradient
283  using stan::math::value_of;
284  using boost::math::ibeta;
285  using boost::math::ibeta_derivative;
286 
287  agrad::OperandsAndPartials<T_prob> operands_and_partials(theta);
288 
289  // Explicit return for extreme values
290  // The gradients are technically ill-defined, but treated as zero
291  for (size_t i = 0; i < stan::length(n); i++) {
292  if (value_of(n_vec[i]) < 0)
293  return operands_and_partials.to_var(0.0);
294  }
295 
296  for (size_t i = 0; i < size; i++) {
297 
298  // Explicit results for extreme values
299  // The gradients are technically ill-defined, but treated as zero
300  if (value_of(n_vec[i]) >= value_of(N_vec[i])) {
301  continue;
302  }
303 
304  const double n_dbl = value_of(n_vec[i]);
305  const double N_dbl = value_of(N_vec[i]);
306  const double theta_dbl = value_of(theta_vec[i]);
307 
308  const double Pi = ibeta(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl);
309 
310  P *= Pi;
311 
313  operands_and_partials.d_x1[i]
314  += - ibeta_derivative(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl) / Pi;
315 
316 
317  }
318 
320  for(size_t i = 0; i < stan::length(theta); ++i) operands_and_partials.d_x1[i] *= P;
321  }
322 
323  return operands_and_partials.to_var(P);
324 
325  }
326 
327  template <typename T_n, typename T_N, typename T_prob>
329  binomial_cdf_log(const T_n& n, const T_N& N, const T_prob& theta) {
330 
331  static const char* function = "stan::prob::binomial_cdf_log(%1%)";
332 
336  using stan::math::value_of;
339 
340  // Ensure non-zero arguments lenghts
341  if (!(stan::length(n) && stan::length(N) && stan::length(theta)))
342  return 0.0;
343 
344  double P(0.0);
345 
346  // Validate arguments
347  check_nonnegative(function, N, "Population size parameter", &P);
348  check_finite(function, theta, "Probability parameter", &P);
349  check_bounded(function, theta, 0.0, 1.0,
350  "Probability parameter", &P);
351  check_consistent_sizes(function, n, N, theta,
352  "Successes variable", "Population size parameter",
353  "Probability parameter",
354  &P);
355 
356  // Wrap arguments in vector views
357  VectorView<const T_n> n_vec(n);
358  VectorView<const T_N> N_vec(N);
359  VectorView<const T_prob> theta_vec(theta);
360  size_t size = max_size(n, N, theta);
361 
362  // Compute vectorized cdf_log and gradient
363  using stan::math::value_of;
364  using boost::math::ibeta;
365  using boost::math::ibeta_derivative;
366 
367  agrad::OperandsAndPartials<T_prob> operands_and_partials(theta);
368 
369  // Explicit return for extreme values
370  // The gradients are technically ill-defined, but treated as negative infinity
371  for (size_t i = 0; i < stan::length(n); i++) {
372  if (value_of(n_vec[i]) < 0)
373  return operands_and_partials.to_var(stan::math::negative_infinity());
374  }
375 
376  for (size_t i = 0; i < size; i++) {
377  // Explicit results for extreme values
378  // The gradients are technically ill-defined, but treated as zero
379  if (value_of(n_vec[i]) >= value_of(N_vec[i])) {
380  continue;
381  }
382  const double n_dbl = value_of(n_vec[i]);
383  const double N_dbl = value_of(N_vec[i]);
384  const double theta_dbl = value_of(theta_vec[i]);
385  const double Pi = ibeta(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl);
386 
387  P += log(Pi);
388 
390  operands_and_partials.d_x1[i]
391  += - ibeta_derivative(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl) / Pi;
392  }
393 
394  return operands_and_partials.to_var(P);
395  }
396 
397  template <typename T_n, typename T_N, typename T_prob>
399  binomial_ccdf_log(const T_n& n, const T_N& N, const T_prob& theta) {
400 
401  static const char* function = "stan::prob::binomial_ccdf_log(%1%)";
402 
406  using stan::math::value_of;
409 
410  // Ensure non-zero arguments lenghts
411  if (!(stan::length(n) && stan::length(N) && stan::length(theta)))
412  return 0.0;
413 
414  double P(0.0);
415 
416  // Validate arguments
417  check_nonnegative(function, N, "Population size parameter", &P);
418  check_finite(function, theta, "Probability parameter", &P);
419  check_bounded(function, theta, 0.0, 1.0,
420  "Probability parameter", &P);
421  check_consistent_sizes(function, n, N, theta,
422  "Successes variable", "Population size parameter",
423  "Probability parameter",
424  &P);
425 
426  // Wrap arguments in vector views
427  VectorView<const T_n> n_vec(n);
428  VectorView<const T_N> N_vec(N);
429  VectorView<const T_prob> theta_vec(theta);
430  size_t size = max_size(n, N, theta);
431 
432  // Compute vectorized cdf_log and gradient
433  using stan::math::value_of;
434  using boost::math::ibeta;
435  using boost::math::ibeta_derivative;
436 
437  agrad::OperandsAndPartials<T_prob> operands_and_partials(theta);
438 
439  // Explicit return for extreme values
440  // The gradients are technically ill-defined, but treated as negative infinity
441  for (size_t i = 0; i < stan::length(n); i++) {
442  if (value_of(n_vec[i]) < 0)
443  return operands_and_partials.to_var(0.0);
444  }
445 
446  for (size_t i = 0; i < size; i++) {
447  // Explicit results for extreme values
448  // The gradients are technically ill-defined, but treated as zero
449  if (value_of(n_vec[i]) >= value_of(N_vec[i])) {
450  return operands_and_partials.to_var(stan::math::negative_infinity());
451  }
452  const double n_dbl = value_of(n_vec[i]);
453  const double N_dbl = value_of(N_vec[i]);
454  const double theta_dbl = value_of(theta_vec[i]);
455  const double Pi = 1.0 - ibeta(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl);
456 
457  P += log(Pi);
458 
460  operands_and_partials.d_x1[i]
461  += ibeta_derivative(N_dbl - n_dbl, n_dbl + 1, 1 - theta_dbl) / Pi;
462  }
463 
464  return operands_and_partials.to_var(P);
465  }
466 
467 
468  template <class RNG>
469  inline int
470  binomial_rng(const int N,
471  const double theta,
472  RNG& rng) {
473  using boost::variate_generator;
474  using boost::binomial_distribution;
475 
476  static const char* function = "stan::prob::binomial_rng(%1%)";
477 
482 
483  check_nonnegative(function, N,
484  "Population size parameter", (double*)0);
485  check_finite(function, theta,
486  "Probability parameter", (double*)0);
487  check_less_or_equal(function, theta, 1.0,
488  "Probability parameter", (double*)0);
489  check_greater_or_equal(function, theta, 0.0,
490  "Probability parameter", (double*)0);
491 
492  variate_generator<RNG&, binomial_distribution<> >
493  binomial_rng(rng, binomial_distribution<>(N, theta));
494  return binomial_rng();
495  }
496 
497  }
498 }
499 #endif
fvar< T > log1m(const fvar< T > &x)
Definition: log1m.hpp:16
bool check_bounded(const char *function, const T_y &y, const T_low &low, const T_high &high, const char *name, T_result *result)
T_return_type to_var(double logp)
return_type< T_prob >::type binomial_cdf_log(const T_n &n, const T_N &N, const T_prob &theta)
Definition: binomial.hpp:329
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...
boost::math::tools::promote_args< T >::type log_inv_logit(const T &u)
Returns the natural logarithm of the inverse logit of the specified argument.
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
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
return_type< T_prob >::type binomial_log(const T_n &n, const T_N &N, const T_prob &theta)
Definition: binomial.hpp:31
boost::math::tools::promote_args< T >::type inv_logit(const T a)
Returns the inverse logit function applied to the argument.
Definition: inv_logit.hpp:52
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
int binomial_rng(const int N, const double theta, RNG &rng)
Definition: binomial.hpp:470
A variable implementation that stores operands and derivatives with respect to the variable...
fvar< T > inv_logit(const fvar< T > &x)
Definition: inv_logit.hpp:15
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
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_prob >::type binomial_ccdf_log(const T_n &n, const T_N &N, const T_prob &theta)
Definition: binomial.hpp:399
bool check_less_or_equal(const char *function, const T_y &y, const T_high &high, const char *name, T_result *result)
fvar< T > multiply_log(const fvar< T > &x1, const fvar< T > &x2)
int size(const std::vector< T > &x)
Definition: size.hpp:11
fvar< T > binomial_coefficient_log(const fvar< T > &x1, const fvar< T > &x2)
fvar< T > log_inv_logit(const fvar< T > &x)
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
return_type< T_prob >::type binomial_cdf(const T_n &n, const T_N &N, const T_prob &theta)
Definition: binomial.hpp:249
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
bool check_greater_or_equal(const char *function, const T_y &y, const T_low &low, const char *name, T_result *result)
boost::math::tools::promote_args< T >::type log1m(T x)
Return the natural logarithm of one minus the specified value.
Definition: log1m.hpp:40
return_type< T_prob >::type binomial_logit_log(const T_n &n, const T_N &N, const T_prob &alpha)
Definition: binomial.hpp:142
double negative_infinity()
Return negative infinity.
Definition: constants.hpp:123

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