Stan  1.1
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 <limits>
5 
6 #include <stan/agrad.hpp>
9 #include <stan/meta/traits.hpp>
10 #include <stan/prob/traits.hpp>
11 #include <stan/prob/constants.hpp>
12 
13 namespace stan {
14 
15  namespace prob {
16 
17  // Poisson(n|lambda) [lambda > 0; n >= 0]
18  template <bool propto,
19  typename T_n, typename T_rate,
20  class Policy>
21  typename return_type<T_rate>::type
22  poisson_log(const T_n& n, const T_rate& lambda,
23  const Policy&) {
24 
25  static const char* function = "stan::prob::poisson_log(%1%)";
26 
32 
33  // check if any vectors are zero length
34  if (!(stan::length(n)
35  && stan::length(lambda)))
36  return 0.0;
37 
38  // set up return value accumulator
39  double logp(0.0);
40 
41  // validate args
42  if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
43  return logp;
44  if (!check_not_nan(function, lambda,
45  "Rate parameter", &logp, Policy()))
46  return logp;
47  if (!check_nonnegative(function, lambda,
48  "Rate parameter", &logp, Policy()))
49  return logp;
50  if (!(check_consistent_sizes(function,
51  n,lambda,
52  "Random variable","Rate parameter",
53  &logp, Policy())))
54  return logp;
55 
56  // check if no variables are involved and prop-to
58  return 0.0;
59 
60  // set up expression templates wrapping scalars/vecs into vector views
61  VectorView<const T_n> n_vec(n);
62  VectorView<const T_rate> lambda_vec(lambda);
63  size_t size = max_size(n, lambda);
64 
65  for (size_t i = 0; i < size; i++)
66  if (std::isinf(lambda_vec[i]))
67  return LOG_ZERO;
68  for (size_t i = 0; i < size; i++)
69  if (lambda_vec[i] == 0 && n_vec[i] != 0)
70  return LOG_ZERO;
71 
72  // return accumulator with gradients
73  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
74 
76  for (size_t i = 0; i < size; i++) {
77  if (!(lambda_vec[i] == 0 && n_vec[i] == 0)) {
79  logp -= lgamma(n_vec[i] + 1.0);
81  logp += multiply_log(n_vec[i], value_of(lambda_vec[i]))
82  - value_of(lambda_vec[i]);
83  }
84 
85  // gradients
87  operands_and_partials.d_x1[i] += n_vec[i] / value_of(lambda_vec[i]) - 1.0;
88 
89  }
90 
91 
92  return operands_and_partials.to_var(logp);
93  }
94 
95  template <bool propto,
96  typename T_n,
97  typename T_rate>
98  inline
100  poisson_log(const T_n& n, const T_rate& lambda) {
101  return poisson_log<propto>(n,lambda,stan::math::default_policy());
102  }
103 
104 
105  template <typename T_n,
106  typename T_rate,
107  class Policy>
108  inline
110  poisson_log(const T_n& n, const T_rate& lambda,
111  const Policy&) {
112  return poisson_log<false>(n,lambda,Policy());
113  }
114 
115 
116  template <typename T_n,
117  typename T_rate>
118  inline
120  poisson_log(const T_n& n, const T_rate& lambda) {
121  return poisson_log<false>(n,lambda,stan::math::default_policy());
122  }
123 
124 
125 
126 
127 
128  // PoissonLog(n|alpha) [n >= 0] = Poisson(n|exp(alpha))
129  template <bool propto,
130  typename T_n, typename T_log_rate,
131  class Policy>
133  poisson_log_log(const T_n& n, const T_log_rate& alpha,
134  const Policy&) {
135 
136  static const char* function = "stan::prob::poisson_log_log(%1%)";
137 
138  using std::exp;
141  using stan::math::value_of;
144 
145  // check if any vectors are zero length
146  if (!(stan::length(n)
147  && stan::length(alpha)))
148  return 0.0;
149 
150  // set up return value accumulator
151  double logp(0.0);
152 
153  // validate args
154  if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
155  return logp;
156  if (!check_not_nan(function, alpha,
157  "Log rate parameter", &logp, Policy()))
158  return logp;
159  if (!(check_consistent_sizes(function,
160  n,alpha,
161  "Random variable","Log rate parameter",
162  &logp, Policy())))
163  return logp;
164 
165  // check if no variables are involved and prop-to
167  return 0.0;
168 
169  // set up expression templates wrapping scalars/vecs into vector views
170  VectorView<const T_n> n_vec(n);
171  VectorView<const T_log_rate> alpha_vec(alpha);
172  size_t size = max_size(n, alpha);
173 
174  // FIXME: first loop size of alpha_vec, second loop if-ed for size==1
175  for (size_t i = 0; i < size; i++)
176  if (std::numeric_limits<double>::infinity() == alpha_vec[i])
177  return LOG_ZERO;
178  for (size_t i = 0; i < size; i++)
179  if (-std::numeric_limits<double>::infinity() == alpha_vec[i]
180  && n_vec[i] != 0)
181  return LOG_ZERO;
182 
183  // return accumulator with gradients
184  agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha);
185 
186  // FIXME: cache value_of for alpha_vec? faster if only one?
187 
189  for (size_t i = 0; i < size; i++) {
190  if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity()
191  && n_vec[i] == 0)) {
193  logp -= lgamma(n_vec[i] + 1.0);
195  logp += n_vec[i] * value_of(alpha_vec[i]) - exp(value_of(alpha_vec[i]));
196  }
197 
198  // gradients
200  operands_and_partials.d_x1[i] += n_vec[i] - exp(value_of(alpha_vec[i]));
201  }
202  return operands_and_partials.to_var(logp);
203  }
204 
205  template <bool propto,
206  typename T_n,
207  typename T_log_rate>
208  inline
210  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
211  return poisson_log_log<propto>(n,alpha,stan::math::default_policy());
212  }
213 
214 
215  template <typename T_n,
216  typename T_log_rate,
217  class Policy>
218  inline
220  poisson_log_log(const T_n& n, const T_log_rate& alpha,
221  const Policy&) {
222  return poisson_log_log<false>(n,alpha,Policy());
223  }
224 
225 
226  template <typename T_n,
227  typename T_log_rate>
228  inline
230  poisson_log_log(const T_n& n, const T_log_rate& alpha) {
231  return poisson_log_log<false>(n,alpha,stan::math::default_policy());
232  }
233 
234  // Poisson CDF
235  template <bool propto, typename T_n, typename T_rate, class Policy>
237  poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
238 
239  static const char* function = "stan::prob::poisson_cdf(%1%)";
240 
243  using stan::math::value_of;
246 
247  // Ensure non-zero argument slengths
248  if (!(stan::length(n) && stan::length(lambda)))
249  return 0.0;
250 
251  double P(1.0);
252 
253  // Validate arguments
254  if (!check_nonnegative(function, n, "Random variable", &P, Policy()))
255  return P;
256 
257  if (!check_not_nan(function, lambda, "Rate parameter", &P, Policy()))
258  return P;
259 
260  if (!check_nonnegative(function, lambda, "Rate parameter", &P, Policy()))
261  return P;
262 
263  if (!(check_consistent_sizes(function, n,lambda,
264  "Random variable","Rate parameter",
265  &P, Policy())))
266  return P;
267 
268  // Return if everything is constant and only proportionality is required
270  return 0.0;
271 
272  // Wrap arguments into vector views
273  VectorView<const T_n> n_vec(n);
274  VectorView<const T_rate> lambda_vec(lambda);
275  size_t size = max_size(n, lambda);
276 
277  // Validate vector views - redundant with the above validations?
278  for (size_t i = 0; i < size; i++)
279  if (std::isinf(lambda_vec[i])) return LOG_ZERO;
280 
281  for (size_t i = 0; i < size; i++)
282  if (lambda_vec[i] == 0 && n_vec[i] != 0)
283  return LOG_ZERO;
284 
285 
286  // Compute vectorized CDF and gradient
287  using stan::math::value_of;
288  using boost::math::gamma_p_derivative;
289  using boost::math::gamma_p;
290 
291  agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);
292 
293  std::fill(operands_and_partials.all_partials,
294  operands_and_partials.all_partials + operands_and_partials.nvaris, 0.0);
295 
296  for (size_t i = 0; i < size; i++)
297  {
298 
299  const double n_dbl = value_of(n_vec[i]);
300  const double lambda_dbl = value_of(lambda_vec[i]);
301 
302  const double Pi = gamma_p(n_dbl, lambda_dbl);
303 
304  P *= Pi;
305 
307  operands_and_partials.d_x1[i] += gamma_p_derivative(n_dbl, lambda_dbl) / Pi;
308 
309  }
310 
311  for (size_t i = 0; i < size; i++) {
312 
314  operands_and_partials.d_x1[n] *= P;
315 
316  }
317 
318  return operands_and_partials.to_var(P);
319  }
320 
321  template <bool propto, typename T_n, typename T_rate>
322  inline typename return_type<T_rate>::type
323  poisson_cdf(const T_n& n, const T_rate& lambda) {
324  return poisson_cdf<propto>(n, lambda, stan::math::default_policy());
325  }
326 
327 
328  template <typename T_n, typename T_rate, class Policy>
329  inline typename return_type<T_rate>::type
330  poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
331  return poisson_cdf<false>(n, lambda, Policy());
332  }
333 
334 
335  template <typename T_n, typename T_rate>
336  inline typename return_type<T_rate>::type
337  poisson_cdf(const T_n& n, const T_rate& lambda) {
338  return poisson_cdf<false>(n, lambda, stan::math::default_policy());
339  }
340 
341 
342  }
343 }
344 #endif

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