Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
inv_gamma.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__INV_GAMMA_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__INV_GAMMA_HPP__
3 
4 #include <boost/random/gamma_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
7 #include <stan/agrad.hpp>
10 #include <stan/meta/traits.hpp>
11 #include <stan/prob/constants.hpp>
12 #include <stan/prob/traits.hpp>
14 
15 namespace stan {
16 
17  namespace prob {
18 
35  template <bool propto,
36  typename T_y, typename T_shape, typename T_scale,
37  class Policy>
38  typename return_type<T_y,T_shape,T_scale>::type
39  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta,
40  const Policy&) {
41  static const char* function = "stan::prob::inv_gamma_log(%1%)";
42 
47  using boost::math::tools::promote_args;
50 
51  // check if any vectors are zero length
52  if (!(stan::length(y)
53  && stan::length(alpha)
54  && stan::length(beta)))
55  return 0.0;
56 
57  // set up return value accumulator
58  double logp(0.0);
59 
60  if (!check_not_nan(function, y, "Random variable", &logp, Policy()))
61  return logp;
62  if (!check_finite(function, alpha, "Shape parameter",
63  &logp, Policy()))
64  return logp;
65  if (!check_positive(function, alpha, "Shape parameter",
66  &logp, Policy()))
67  return logp;
68  if (!check_finite(function, beta, "Scale parameter",
69  &logp, Policy()))
70  return logp;
71  if (!check_positive(function, beta, "Scale parameter",
72  &logp, Policy()))
73  return logp;
74  if (!(check_consistent_sizes(function,
75  y,alpha,beta,
76  "Random variable","Shape parameter",
77  "Scale parameter",
78  &logp, Policy())))
79  return logp;
80 
81  // check if no variables are involved and prop-to
83  return 0.0;
84 
85  // set up template expressions wrapping scalars into vector views
86  VectorView<const T_y> y_vec(y);
87  VectorView<const T_shape> alpha_vec(alpha);
88  VectorView<const T_scale> beta_vec(beta);
89 
90  for (size_t n = 0; n < length(y); n++) {
91  const double y_dbl = value_of(y_vec[n]);
92  if (y_dbl <= 0)
93  return LOG_ZERO;
94  }
95 
96  size_t N = max_size(y, alpha, beta);
98  operands_and_partials(y, alpha, beta);
99 
100  using boost::math::lgamma;
102  using boost::math::digamma;
103 
106  log_y(length(y));
109  inv_y(length(y));
110  for(size_t n = 0; n < length(y); n++) {
112  if (value_of(y_vec[n]) > 0)
113  log_y[n] = log(value_of(y_vec[n]));
115  inv_y[n] = 1.0 / value_of(y_vec[n]);
116  }
117 
120  lgamma_alpha(length(alpha));
123  digamma_alpha(length(alpha));
124  for (size_t n = 0; n < length(alpha); n++) {
126  lgamma_alpha[n] = lgamma(value_of(alpha_vec[n]));
128  digamma_alpha[n] = digamma(value_of(alpha_vec[n]));
129  }
130 
133  log_beta(length(beta));
135  for (size_t n = 0; n < length(beta); n++)
136  log_beta[n] = log(value_of(beta_vec[n]));
137 
138  for (size_t n = 0; n < N; n++) {
139  // pull out values of arguments
140  const double alpha_dbl = value_of(alpha_vec[n]);
141  const double beta_dbl = value_of(beta_vec[n]);
142 
144  logp -= lgamma_alpha[n];
146  logp += alpha_dbl * log_beta[n];
148  logp -= (alpha_dbl+1.0) * log_y[n];
150  logp -= beta_dbl * inv_y[n];
151 
152  // gradients
153  if (!is_constant<typename is_vector<T_y>::type>::value)
154  operands_and_partials.d_x1[n]
155  += -(alpha_dbl+1) * inv_y[n] + beta_dbl * inv_y[n] * inv_y[n];
156  if (!is_constant<typename is_vector<T_shape>::type>::value)
157  operands_and_partials.d_x2[n]
158  += -digamma_alpha[n] + log_beta[n] - log_y[n];
159  if (!is_constant<typename is_vector<T_scale>::type>::value)
160  operands_and_partials.d_x3[n] += alpha_dbl / beta_dbl - inv_y[n];
161  }
162  return operands_and_partials.to_var(logp);
163  }
164 
165  template <bool propto,
166  typename T_y, typename T_shape, typename T_scale>
167  inline
169  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta) {
170  return inv_gamma_log<propto>(y,alpha,beta,stan::math::default_policy());
171  }
172 
173  template <typename T_y, typename T_shape, typename T_scale,
174  class Policy>
175  inline
177  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta,
178  const Policy&) {
179  return inv_gamma_log<false>(y,alpha,beta,Policy());
180  }
181 
182  template <typename T_y, typename T_shape, typename T_scale>
183  inline
185  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta) {
186  return inv_gamma_log<false>(y,alpha,beta,stan::math::default_policy());
187  }
188 
205  template <typename T_y, typename T_shape, typename T_scale, class Policy>
207  inv_gamma_cdf(const T_y& y, const T_shape& alpha, const T_scale& beta,
208  const Policy&) {
209 
210  // Size checks
211  if (!(stan::length(y) && stan::length(alpha) && stan::length(beta)))
212  return 1.0;
213 
214  // Error checks
215  static const char* function = "stan::prob::inv_gamma_cdf(%1%)";
216 
224  using stan::math::value_of;
225 
226  using boost::math::tools::promote_args;
227 
228  double P(1.0);
229 
230  if (!check_finite(function, alpha, "Shape parameter", &P, Policy()))
231  return P;
232 
233  if (!check_positive(function, alpha, "Shape parameter", &P, Policy()))
234  return P;
235 
236  if (!check_finite(function, beta, "Scale parameter", &P, Policy()))
237  return P;
238 
239  if (!check_positive(function, beta, "Scale parameter", &P, Policy()))
240  return P;
241 
242  if (!check_not_nan(function, y, "Random variable", &P, Policy()))
243  return P;
244 
245  if (!check_nonnegative(function, y, "Random variable", &P, Policy()))
246  return P;
247 
248  if (!(check_consistent_sizes(function, y, alpha, beta,
249  "Random variable", "Shape parameter",
250  "Scale Parameter",
251  &P, Policy())))
252  return P;
253 
254  // Wrap arguments in vectors
255  VectorView<const T_y> y_vec(y);
256  VectorView<const T_shape> alpha_vec(alpha);
257  VectorView<const T_scale> beta_vec(beta);
258  size_t N = max_size(y, alpha, beta);
259 
261  operands_and_partials(y, alpha, beta);
262 
263  std::fill(operands_and_partials.all_partials,
264  operands_and_partials.all_partials
265  + operands_and_partials.nvaris, 0.0);
266 
267  // Explicit return for extreme values
268  // The gradients are technically ill-defined, but treated as zero
269 
270  for (size_t i = 0; i < stan::length(y); i++) {
271  if (value_of(y_vec[i]) == 0)
272  return operands_and_partials.to_var(0.0);
273  }
274 
275  // Compute CDF and its gradients
276  using boost::math::gamma_p_derivative;
277  using boost::math::gamma_q;
278  using boost::math::digamma;
279  using boost::math::tgamma;
280 
281  // Cache a few expensive function calls if nu is a parameter
284  gamma_vec(stan::length(alpha));
287  digamma_vec(stan::length(alpha));
288 
290  for (size_t i = 0; i < stan::length(alpha); i++) {
291  const double alpha_dbl = value_of(alpha_vec[i]);
292  gamma_vec[i] = tgamma(alpha_dbl);
293  digamma_vec[i] = digamma(alpha_dbl);
294  }
295  }
296 
297  // Compute vectorized CDF and gradient
298  for (size_t n = 0; n < N; n++) {
299  // Explicit results for extreme values
300  // The gradients are technically ill-defined, but treated as zero
301  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity())
302  continue;
303 
304  // Pull out values
305  const double y_dbl = value_of(y_vec[n]);
306  const double y_inv_dbl = 1.0 / y_dbl;
307  const double alpha_dbl = value_of(alpha_vec[n]);
308  const double beta_dbl = value_of(beta_vec[n]);
309 
310  // Compute
311  const double Pn = gamma_q(alpha_dbl, beta_dbl * y_inv_dbl);
312 
313  P *= Pn;
314 
316  operands_and_partials.d_x1[n]
317  += beta_dbl * y_inv_dbl * y_inv_dbl
318  * gamma_p_derivative(alpha_dbl, beta_dbl * y_inv_dbl)
319  / Pn;
320 
322  operands_and_partials.d_x2[n]
323  += stan::math::gradRegIncGamma(alpha_dbl, beta_dbl
324  * y_inv_dbl, gamma_vec[n],
325  digamma_vec[n]) / Pn;
326 
328  operands_and_partials.d_x3[n]
329  += - y_inv_dbl * gamma_p_derivative(alpha_dbl,
330  beta_dbl * y_inv_dbl) / Pn;
331 
332  }
333 
335  for (size_t n = 0; n < stan::length(y); ++n)
336  operands_and_partials.d_x1[n] *= P;
337 
339  for (size_t n = 0; n < stan::length(alpha); ++n)
340  operands_and_partials.d_x2[n] *= P;
341 
343  for (size_t n = 0; n < stan::length(beta); ++n)
344  operands_and_partials.d_x3[n] *= P;
345 
346  return operands_and_partials.to_var(P);
347  }
348 
349  template <typename T_y, typename T_shape, typename T_scale>
351  inv_gamma_cdf(const T_y& y, const T_shape& alpha, const T_scale& beta) {
352  return inv_gamma_cdf(y, alpha, beta, stan::math::default_policy());
353  }
354 
355  template <class RNG>
356  inline double
357  inv_gamma_rng(const double alpha,
358  const double beta,
359  RNG& rng) {
360  using boost::variate_generator;
361  using boost::random::gamma_distribution;
362  variate_generator<RNG&, gamma_distribution<> >
363  gamma_rng(rng, gamma_distribution<>(alpha, 1 / beta));
364  return 1 / gamma_rng();
365  }
366  }
367 }
368 
369 #endif

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