Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
poisson.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP
3 
4 #include <boost/random/poisson_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
7 #include <limits>
8 #include <boost/math/special_functions/fpclassify.hpp>
9 
12 #include <stan/math/constants.hpp>
15 #include <stan/meta/traits.hpp>
16 #include <stan/prob/traits.hpp>
17 #include <stan/prob/constants.hpp>
18 
19 namespace stan {
20 
21  namespace prob {
22 
23  // Poisson(n|lambda) [lambda > 0; n >= 0]
24  template <bool propto,
25  typename T_n, typename T_rate>
26  typename return_type<T_rate>::type
27  poisson_log(const T_n& n, const T_rate& lambda) {
28 
29  static const char* function = "stan::prob::poisson_log(%1%)";
30 
31  using boost::math::lgamma;
37 
38  // check if any vectors are zero length
39  if (!(stan::length(n)
40  && stan::length(lambda)))
41  return 0.0;
42 
43  // set up return value accumulator
44  double logp(0.0);
45 
46  // validate args
47  check_nonnegative(function, n, "Random variable", &logp);
48  check_not_nan(function, lambda,
49  "Rate parameter", &logp);
50  check_nonnegative(function, lambda,
51  "Rate parameter", &logp);
52  check_consistent_sizes(function,
53  n,lambda,
54  "Random variable","Rate parameter",
55  &logp);
56 
57  // check if no variables are involved and prop-to
59  return 0.0;
60 
61  // set up expression templates wrapping scalars/vecs into vector views
62  VectorView<const T_n> n_vec(n);
63  VectorView<const T_rate> lambda_vec(lambda);
64  size_t size = max_size(n, lambda);
65 
66  for (size_t i = 0; i < size; i++)
67  if (boost::math::isinf(lambda_vec[i]))
68  return LOG_ZERO;
69  for (size_t i = 0; i < size; i++)
70  if (lambda_vec[i] == 0 && n_vec[i] != 0)
71  return LOG_ZERO;
72 
73  // return accumulator with gradients
74  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
75 
77  for (size_t i = 0; i < size; i++) {
78  if (!(lambda_vec[i] == 0 && n_vec[i] == 0)) {
80  logp -= lgamma(n_vec[i] + 1.0);
82  logp += multiply_log(n_vec[i], value_of(lambda_vec[i]))
83  - value_of(lambda_vec[i]);
84  }
85 
86  // gradients
88  operands_and_partials.d_x1[i]
89  += n_vec[i] / value_of(lambda_vec[i]) - 1.0;
90 
91  }
92 
93 
94  return operands_and_partials.to_var(logp);
95  }
96 
97  template <typename T_n,
98  typename T_rate>
99  inline
101  poisson_log(const T_n& n, const T_rate& lambda) {
102  return poisson_log<false>(n,lambda);
103  }
104 
105  // PoissonLog(n|alpha) [n >= 0] = Poisson(n|exp(alpha))
106  template <bool propto,
107  typename T_n, typename T_log_rate>
109  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
110 
111  static const char* function = "stan::prob::poisson_log_log(%1%)";
112 
113  using boost::math::lgamma;
116  using stan::math::value_of;
119  using std::exp;
120 
121  // check if any vectors are zero length
122  if (!(stan::length(n)
123  && stan::length(alpha)))
124  return 0.0;
125 
126  // set up return value accumulator
127  double logp(0.0);
128 
129  // validate args
130  check_nonnegative(function, n, "Random variable", &logp);
131  check_not_nan(function, alpha,
132  "Log rate parameter", &logp);
133  check_consistent_sizes(function,
134  n,alpha,
135  "Random variable","Log rate parameter",
136  &logp);
137 
138  // check if no variables are involved and prop-to
140  return 0.0;
141 
142  // set up expression templates wrapping scalars/vecs into vector views
143  VectorView<const T_n> n_vec(n);
144  VectorView<const T_log_rate> alpha_vec(alpha);
145  size_t size = max_size(n, alpha);
146 
147  // FIXME: first loop size of alpha_vec, second loop if-ed for size==1
148  for (size_t i = 0; i < size; i++)
149  if (std::numeric_limits<double>::infinity() == alpha_vec[i])
150  return LOG_ZERO;
151  for (size_t i = 0; i < size; i++)
152  if (-std::numeric_limits<double>::infinity() == alpha_vec[i]
153  && n_vec[i] != 0)
154  return LOG_ZERO;
155 
156  // return accumulator with gradients
157  agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha);
158 
159  // FIXME: cache value_of for alpha_vec? faster if only one?
162  exp_alpha(length(alpha));
163  for (size_t i = 0; i < length(alpha); i++)
165  exp_alpha[i] = exp(value_of(alpha_vec[i]));
167  for (size_t i = 0; i < size; i++) {
168  if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity()
169  && n_vec[i] == 0)) {
171  logp -= lgamma(n_vec[i] + 1.0);
173  logp += n_vec[i] * value_of(alpha_vec[i]) - exp_alpha[i];
174  }
175 
176  // gradients
178  operands_and_partials.d_x1[i] += n_vec[i] - exp_alpha[i];
179  }
180  return operands_and_partials.to_var(logp);
181  }
182 
183  template <typename T_n,
184  typename T_log_rate>
185  inline
187  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
188  return poisson_log_log<false>(n,alpha);
189  }
190 
191  // Poisson CDF
192  template <typename T_n, typename T_rate>
194  poisson_cdf(const T_n& n, const T_rate& lambda) {
195  static const char* function = "stan::prob::poisson_cdf(%1%)";
196 
199  using stan::math::value_of;
201 
202  // Ensure non-zero argument slengths
203  if (!(stan::length(n) && stan::length(lambda)))
204  return 1.0;
205 
206  double P(1.0);
207 
208  // Validate arguments
209  check_not_nan(function, lambda, "Rate parameter", &P);
210  check_nonnegative(function, lambda, "Rate parameter", &P);
211  check_consistent_sizes(function, n,lambda,
212  "Random variable","Rate parameter",
213  &P);
214 
215  // Wrap arguments into vector views
216  VectorView<const T_n> n_vec(n);
217  VectorView<const T_rate> lambda_vec(lambda);
218  size_t size = max_size(n, lambda);
219 
220  // Compute vectorized CDF and gradient
221  using stan::math::value_of;
222  using boost::math::gamma_p_derivative;
223  using boost::math::gamma_q;
224 
225  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
226 
227  // Explicit return for extreme values
228  // The gradients are technically ill-defined, but treated as zero
229  for (size_t i = 0; i < stan::length(n); i++) {
230  if (value_of(n_vec[i]) < 0)
231  return operands_and_partials.to_var(0.0);
232  }
233 
234  for (size_t i = 0; i < size; i++) {
235  // Explicit results for extreme values
236  // The gradients are technically ill-defined, but treated as zero
237  if (value_of(n_vec[i]) == std::numeric_limits<double>::infinity())
238  continue;
239 
240  const double n_dbl = value_of(n_vec[i]);
241  const double lambda_dbl = value_of(lambda_vec[i]);
242  const double Pi = gamma_q(n_dbl+1, lambda_dbl);
243 
244  P *= Pi;
245 
247  operands_and_partials.d_x1[i]
248  -= gamma_p_derivative(n_dbl + 1, lambda_dbl) / Pi;
249  }
250 
252  for(size_t i = 0; i < stan::length(lambda); ++i)
253  operands_and_partials.d_x1[i] *= P;
254 
255  return operands_and_partials.to_var(P);
256  }
257 
258  template <typename T_n, typename T_rate>
260  poisson_cdf_log(const T_n& n, const T_rate& lambda) {
261  static const char* function = "stan::prob::poisson_cdf_log(%1%)";
262 
265  using stan::math::value_of;
267 
268  // Ensure non-zero argument slengths
269  if (!(stan::length(n) && stan::length(lambda)))
270  return 0.0;
271 
272  double P(0.0);
273 
274  // Validate arguments
275  check_not_nan(function, lambda, "Rate parameter", &P);
276  check_nonnegative(function, lambda, "Rate parameter", &P);
277  check_consistent_sizes(function, n,lambda,
278  "Random variable","Rate parameter",
279  &P);
280 
281  // Wrap arguments into vector views
282  VectorView<const T_n> n_vec(n);
283  VectorView<const T_rate> lambda_vec(lambda);
284  size_t size = max_size(n, lambda);
285 
286  // Compute vectorized cdf_log and gradient
287  using stan::math::value_of;
288  using boost::math::gamma_p_derivative;
289  using boost::math::gamma_q;
290 
291  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
292 
293  // Explicit return for extreme values
294  // The gradients are technically ill-defined, but treated as neg infinity
295  for (size_t i = 0; i < stan::length(n); i++) {
296  if (value_of(n_vec[i]) < 0)
297  return operands_and_partials.to_var(stan::math::negative_infinity());
298  }
299 
300  for (size_t i = 0; i < size; i++) {
301  // Explicit results for extreme values
302  // The gradients are technically ill-defined, but treated as zero
303  if (value_of(n_vec[i]) == std::numeric_limits<double>::infinity())
304  continue;
305 
306  const double n_dbl = value_of(n_vec[i]);
307  const double lambda_dbl = value_of(lambda_vec[i]);
308  const double Pi = gamma_q(n_dbl+1, lambda_dbl);
309 
310  P += log(Pi);
311 
313  operands_and_partials.d_x1[i]
314  -= gamma_p_derivative(n_dbl + 1, lambda_dbl) / Pi;
315  }
316 
317  return operands_and_partials.to_var(P);
318  }
319 
320  template <typename T_n, typename T_rate>
322  poisson_ccdf_log(const T_n& n, const T_rate& lambda) {
323  static const char* function = "stan::prob::poisson_ccdf_log(%1%)";
324 
327  using stan::math::value_of;
329 
330  // Ensure non-zero argument slengths
331  if (!(stan::length(n) && stan::length(lambda)))
332  return 0.0;
333 
334  double P(0.0);
335 
336  // Validate arguments
337  check_not_nan(function, lambda, "Rate parameter", &P);
338  check_nonnegative(function, lambda, "Rate parameter", &P);
339  check_consistent_sizes(function, n,lambda,
340  "Random variable","Rate parameter",
341  &P);
342 
343  // Wrap arguments into vector views
344  VectorView<const T_n> n_vec(n);
345  VectorView<const T_rate> lambda_vec(lambda);
346  size_t size = max_size(n, lambda);
347 
348  // Compute vectorized cdf_log and gradient
349  using stan::math::value_of;
350  using boost::math::gamma_p_derivative;
351  using boost::math::gamma_q;
352 
353  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
354 
355  // Explicit return for extreme values
356  // The gradients are technically ill-defined, but treated as neg infinity
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(0.0);
360  }
361 
362  for (size_t i = 0; i < size; i++) {
363  // Explicit results for extreme values
364  // The gradients are technically ill-defined, but treated as zero
365  if (value_of(n_vec[i]) == std::numeric_limits<double>::infinity())
366  return operands_and_partials.to_var(stan::math::negative_infinity());
367 
368  const double n_dbl = value_of(n_vec[i]);
369  const double lambda_dbl = value_of(lambda_vec[i]);
370  const double Pi = 1.0 - gamma_q(n_dbl+1, lambda_dbl);
371 
372  P += log(Pi);
373 
375  operands_and_partials.d_x1[i]
376  += gamma_p_derivative(n_dbl + 1, lambda_dbl) / Pi;
377  }
378 
379  return operands_and_partials.to_var(P);
380  }
381 
382  template <class RNG>
383  inline int
384  poisson_rng(const double lambda,
385  RNG& rng) {
386  using boost::variate_generator;
387  using boost::random::poisson_distribution;
388 
389  static const char* function = "stan::prob::poisson_rng(%1%)";
390 
393 
394  check_not_nan(function, lambda,
395  "Rate parameter", (double*)0);
396  check_nonnegative(function, lambda,
397  "Rate parameter", (double*)0);
398 
399  variate_generator<RNG&, poisson_distribution<> >
400  poisson_rng(rng, poisson_distribution<>(lambda));
401  return poisson_rng();
402  }
403 
404  }
405 }
406 #endif
T_return_type to_var(double logp)
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
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
return_type< T_rate >::type poisson_log(const T_n &n, const T_rate &lambda)
Definition: poisson.hpp:27
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
bool isinf(const stan::agrad::var &v)
Checks if the given number is infinite.
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
Definition: traits.hpp:35
return_type< T_rate >::type poisson_cdf_log(const T_n &n, const T_rate &lambda)
Definition: poisson.hpp:260
int poisson_rng(const double lambda, RNG &rng)
Definition: poisson.hpp:384
return_type< T_log_rate >::type poisson_log_log(const T_n &n, const T_log_rate &alpha)
Definition: poisson.hpp:109
fvar< T > gamma_q(const fvar< T > &x1, const fvar< T > &x2)
Definition: gamma_q.hpp:15
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
bool check_not_nan(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is nan.
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_rate >::type poisson_ccdf_log(const T_n &n, const T_rate &lambda)
Definition: poisson.hpp:322
return_type< T_rate >::type poisson_cdf(const T_n &n, const T_rate &lambda)
Definition: poisson.hpp:194
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
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
fvar< T > exp(const fvar< T > &x)
Definition: exp.hpp:16
double negative_infinity()
Return negative infinity.
Definition: constants.hpp:123

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