Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs 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 
9 #include <stan/agrad.hpp>
12 #include <stan/meta/traits.hpp>
13 #include <stan/prob/traits.hpp>
14 #include <stan/prob/constants.hpp>
15 
16 namespace stan {
17 
18  namespace prob {
19 
20  // Poisson(n|lambda) [lambda > 0; n >= 0]
21  template <bool propto,
22  typename T_n, typename T_rate,
23  class Policy>
24  typename return_type<T_rate>::type
25  poisson_log(const T_n& n, const T_rate& lambda,
26  const Policy&) {
27 
28  static const char* function = "stan::prob::poisson_log(%1%)";
29 
30  using boost::math::lgamma;
36 
37  // check if any vectors are zero length
38  if (!(stan::length(n)
39  && stan::length(lambda)))
40  return 0.0;
41 
42  // set up return value accumulator
43  double logp(0.0);
44 
45  // validate args
46  if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
47  return logp;
48  if (!check_not_nan(function, lambda,
49  "Rate parameter", &logp, Policy()))
50  return logp;
51  if (!check_nonnegative(function, lambda,
52  "Rate parameter", &logp, Policy()))
53  return logp;
54  if (!(check_consistent_sizes(function,
55  n,lambda,
56  "Random variable","Rate parameter",
57  &logp, Policy())))
58  return logp;
59 
60  // check if no variables are involved and prop-to
62  return 0.0;
63 
64  // set up expression templates wrapping scalars/vecs into vector views
65  VectorView<const T_n> n_vec(n);
66  VectorView<const T_rate> lambda_vec(lambda);
67  size_t size = max_size(n, lambda);
68 
69  for (size_t i = 0; i < size; i++)
70  if (std::isinf(lambda_vec[i]))
71  return LOG_ZERO;
72  for (size_t i = 0; i < size; i++)
73  if (lambda_vec[i] == 0 && n_vec[i] != 0)
74  return LOG_ZERO;
75 
76  // return accumulator with gradients
77  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
78 
80  for (size_t i = 0; i < size; i++) {
81  if (!(lambda_vec[i] == 0 && n_vec[i] == 0)) {
83  logp -= lgamma(n_vec[i] + 1.0);
85  logp += multiply_log(n_vec[i], value_of(lambda_vec[i]))
86  - value_of(lambda_vec[i]);
87  }
88 
89  // gradients
91  operands_and_partials.d_x1[i]
92  += n_vec[i] / value_of(lambda_vec[i]) - 1.0;
93 
94  }
95 
96 
97  return operands_and_partials.to_var(logp);
98  }
99 
100  template <bool propto,
101  typename T_n,
102  typename T_rate>
103  inline
105  poisson_log(const T_n& n, const T_rate& lambda) {
106  return poisson_log<propto>(n,lambda,stan::math::default_policy());
107  }
108 
109 
110  template <typename T_n,
111  typename T_rate,
112  class Policy>
113  inline
115  poisson_log(const T_n& n, const T_rate& lambda,
116  const Policy&) {
117  return poisson_log<false>(n,lambda,Policy());
118  }
119 
120 
121  template <typename T_n,
122  typename T_rate>
123  inline
125  poisson_log(const T_n& n, const T_rate& lambda) {
126  return poisson_log<false>(n,lambda,stan::math::default_policy());
127  }
128 
129 
130 
131 
132 
133  // PoissonLog(n|alpha) [n >= 0] = Poisson(n|exp(alpha))
134  template <bool propto,
135  typename T_n, typename T_log_rate,
136  class Policy>
138  poisson_log_log(const T_n& n, const T_log_rate& alpha,
139  const Policy&) {
140 
141  static const char* function = "stan::prob::poisson_log_log(%1%)";
142 
143  using boost::math::lgamma;
146  using stan::math::value_of;
149  using std::exp;
150 
151  // check if any vectors are zero length
152  if (!(stan::length(n)
153  && stan::length(alpha)))
154  return 0.0;
155 
156  // set up return value accumulator
157  double logp(0.0);
158 
159  // validate args
160  if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
161  return logp;
162  if (!check_not_nan(function, alpha,
163  "Log rate parameter", &logp, Policy()))
164  return logp;
165  if (!(check_consistent_sizes(function,
166  n,alpha,
167  "Random variable","Log rate parameter",
168  &logp, Policy())))
169  return logp;
170 
171  // check if no variables are involved and prop-to
173  return 0.0;
174 
175  // set up expression templates wrapping scalars/vecs into vector views
176  VectorView<const T_n> n_vec(n);
177  VectorView<const T_log_rate> alpha_vec(alpha);
178  size_t size = max_size(n, alpha);
179 
180  // FIXME: first loop size of alpha_vec, second loop if-ed for size==1
181  for (size_t i = 0; i < size; i++)
182  if (std::numeric_limits<double>::infinity() == alpha_vec[i])
183  return LOG_ZERO;
184  for (size_t i = 0; i < size; i++)
185  if (-std::numeric_limits<double>::infinity() == alpha_vec[i]
186  && n_vec[i] != 0)
187  return LOG_ZERO;
188 
189  // return accumulator with gradients
190  agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha);
191 
192  // FIXME: cache value_of for alpha_vec? faster if only one?
195  exp_alpha(length(alpha));
196  for (size_t i = 0; i < length(alpha); i++)
198  exp_alpha[i] = exp(value_of(alpha_vec[i]));
200  for (size_t i = 0; i < size; i++) {
201  if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity()
202  && n_vec[i] == 0)) {
204  logp -= lgamma(n_vec[i] + 1.0);
206  logp += n_vec[i] * value_of(alpha_vec[i]) - exp_alpha[i];
207  }
208 
209  // gradients
211  operands_and_partials.d_x1[i] += n_vec[i] - exp_alpha[i];
212  }
213  return operands_and_partials.to_var(logp);
214  }
215 
216  template <bool propto,
217  typename T_n,
218  typename T_log_rate>
219  inline
221  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
222  return poisson_log_log<propto>(n,alpha,stan::math::default_policy());
223  }
224 
225 
226  template <typename T_n,
227  typename T_log_rate,
228  class Policy>
229  inline
231  poisson_log_log(const T_n& n, const T_log_rate& alpha,
232  const Policy&) {
233  return poisson_log_log<false>(n,alpha,Policy());
234  }
235 
236 
237  template <typename T_n,
238  typename T_log_rate>
239  inline
241  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
242  return poisson_log_log<false>(n,alpha,stan::math::default_policy());
243  }
244 
245  // Poisson CDF
246  template <bool propto, typename T_n, typename T_rate, class Policy>
248  poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
249 
250  static const char* function = "stan::prob::poisson_cdf(%1%)";
251 
254  using stan::math::value_of;
256 
257  // Ensure non-zero argument slengths
258  if (!(stan::length(n) && stan::length(lambda)))
259  return 1.0;
260 
261  double P(1.0);
262 
263  // Validate arguments
264  if (!check_not_nan(function, lambda, "Rate parameter", &P, Policy()))
265  return P;
266 
267  if (!check_nonnegative(function, lambda, "Rate parameter", &P, Policy()))
268  return P;
269 
270  if (!(check_consistent_sizes(function, n,lambda,
271  "Random variable","Rate parameter",
272  &P, Policy())))
273  return P;
274 
275  // Return if everything is constant and only proportionality is required
277  return 1.0;
278 
279  // Wrap arguments into vector views
280  VectorView<const T_n> n_vec(n);
281  VectorView<const T_rate> lambda_vec(lambda);
282  size_t size = max_size(n, lambda);
283 
284  // Compute vectorized CDF and gradient
285  using stan::math::value_of;
286  using boost::math::gamma_p_derivative;
287  using boost::math::gamma_q;
288 
289  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
290 
291  std::fill(operands_and_partials.all_partials,
292  operands_and_partials.all_partials
293  + operands_and_partials.nvaris, 0.0);
294 
295  // Explicit return for extreme values
296  // The gradients are technically ill-defined, but treated as zero
297  for (size_t i = 0; i < stan::length(n); i++) {
298  if (value_of(n_vec[i]) < 0)
299  return operands_and_partials.to_var(0.0);
300  }
301 
302  for (size_t i = 0; i < size; i++) {
303 
304  // Explicit results for extreme values
305  // The gradients are technically ill-defined, but treated as zero
306  if (value_of(n_vec[i]) == std::numeric_limits<double>::infinity())
307  continue;
308 
309  const double n_dbl = value_of(n_vec[i]);
310  const double lambda_dbl = value_of(lambda_vec[i]);
311 
312  const double Pi = gamma_q(n_dbl+1, lambda_dbl);
313  P *= Pi;
314 
316  operands_and_partials.d_x1[i]
317  -= gamma_p_derivative(n_dbl + 1, lambda_dbl) / Pi;
318 
319 
320  }
321 
323  for(size_t i = 0; i < stan::length(lambda); ++i)
324  operands_and_partials.d_x1[i] *= P;
325 
326  return operands_and_partials.to_var(P);
327 
328  }
329 
330  template <bool propto, typename T_n, typename T_rate>
331  inline typename return_type<T_rate>::type
332  poisson_cdf(const T_n& n, const T_rate& lambda) {
333  return poisson_cdf<propto>(n, lambda, stan::math::default_policy());
334  }
335 
336 
337  template <typename T_n, typename T_rate, class Policy>
338  inline typename return_type<T_rate>::type
339  poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
340  return poisson_cdf<false>(n, lambda, Policy());
341  }
342 
343 
344  template <typename T_n, typename T_rate>
345  inline typename return_type<T_rate>::type
346  poisson_cdf(const T_n& n, const T_rate& lambda) {
347  return poisson_cdf<false>(n, lambda, stan::math::default_policy());
348  }
349 
350  template <class RNG>
351  inline int
352  poisson_rng(const double lambda,
353  RNG& rng) {
354  using boost::variate_generator;
355  using boost::random::poisson_distribution;
356  variate_generator<RNG&, poisson_distribution<> >
357  poisson_rng(rng, poisson_distribution<>(lambda));
358  return poisson_rng();
359  }
360 
361 }
362  }
363 #endif

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