Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
exp_mod_normal.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__EXP__MOD__NORMAL__HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__EXP__MOD__NORMAL__HPP
3 
4 #include <boost/random/normal_distribution.hpp>
5 #include <boost/math/special_functions/fpclassify.hpp>
6 #include <boost/random/variate_generator.hpp>
9 
12 #include <stan/math/constants.hpp>
13 #include <stan/meta/traits.hpp>
14 #include <stan/prob/constants.hpp>
15 #include <stan/prob/traits.hpp>
17 
18 namespace stan {
19 
20  namespace prob {
21 
22  template <bool propto,
23  typename T_y, typename T_loc, typename T_scale,
24  typename T_inv_scale>
25  typename return_type<T_y,T_loc,T_scale, T_inv_scale>::type
26  exp_mod_normal_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
27  const T_inv_scale& lambda) {
28  static const char* function = "stan::prob::exp_mod_normal_log(%1%)";
29 
37 
38  // check if any vectors are zero length
39  if (!(stan::length(y)
40  && stan::length(mu)
41  && stan::length(sigma)
42  && stan::length(lambda)))
43  return 0.0;
44 
45  // set up return value accumulator
46  double logp(0.0);
47 
48  // validate args (here done over var, which should be OK)
49  check_not_nan(function, y, "Random variable", &logp);
50  check_finite(function, mu, "Location parameter", &logp);
51  check_positive_finite(function, lambda, "Inv_scale parameter", &logp);
52  check_positive_finite(function, sigma, "Scale parameter", &logp);
53  check_consistent_sizes(function,
54  y,mu,sigma,lambda,
55  "Random variable","Location parameter",
56  "Scale parameter", "Inv_scale paramter",
57  &logp);
58 
59  // check if no variables are involved and prop-to
61  return 0.0;
62 
63  // set up template expressions wrapping scalars into vector views
65  operands_and_partials(y, mu, sigma,lambda);
66 
67  VectorView<const T_y> y_vec(y);
68  VectorView<const T_loc> mu_vec(mu);
69  VectorView<const T_scale> sigma_vec(sigma);
70  VectorView<const T_inv_scale> lambda_vec(lambda);
71  size_t N = max_size(y, mu, sigma, lambda);
72 
73  for (size_t n = 0; n < N; n++) {
74  //pull out values of arguments
75  const double y_dbl = value_of(y_vec[n]);
76  const double mu_dbl = value_of(mu_vec[n]);
77  const double sigma_dbl = value_of(sigma_vec[n]);
78  const double lambda_dbl = value_of(lambda_vec[n]);
79 
80  const double pi_dbl = boost::math::constants::pi<double>();
81 
82  // log probability
84  logp -= log(2.0);
86  logp += log(lambda_dbl);
88  logp += lambda_dbl
89  * (mu_dbl + 0.5 * lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
90  + log(boost::math::erfc((mu_dbl + lambda_dbl * sigma_dbl
91  * sigma_dbl - y_dbl)
92  / (std::sqrt(2.0) * sigma_dbl)));
93 
94  // gradients
95  const double deriv_logerfc
96  = -2.0 / std::sqrt(pi_dbl)
97  * exp(-(mu_dbl + lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
98  / (std::sqrt(2.0) * sigma_dbl)
99  * (mu_dbl + lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
100  / (sigma_dbl * std::sqrt(2.0)))
101  / boost::math::erfc((mu_dbl + lambda_dbl * sigma_dbl * sigma_dbl
102  - y_dbl)
103  / (sigma_dbl * std::sqrt(2.0)));
104 
106  operands_and_partials.d_x1[n]
107  += -lambda_dbl
108  + deriv_logerfc * -1.0 / (sigma_dbl * std::sqrt(2.0));
110  operands_and_partials.d_x2[n]
111  += lambda_dbl
112  + deriv_logerfc / (sigma_dbl * std::sqrt(2.0));
114  operands_and_partials.d_x3[n]
115  += sigma_dbl * lambda_dbl * lambda_dbl
116  + deriv_logerfc
117  * (-mu_dbl / (sigma_dbl * sigma_dbl * std::sqrt(2.0))
118  + lambda_dbl / std::sqrt(2.0)
119  + y_dbl / (sigma_dbl * sigma_dbl * std::sqrt(2.0)));
121  operands_and_partials.d_x4[n]
122  += 1 / lambda_dbl + lambda_dbl * sigma_dbl * sigma_dbl
123  + mu_dbl - y_dbl + deriv_logerfc * sigma_dbl / std::sqrt(2.0);
124  }
125  return operands_and_partials.to_var(logp);
126  }
127 
128  template <typename T_y, typename T_loc, typename T_scale,
129  typename T_inv_scale>
130  inline
132  exp_mod_normal_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
133  const T_inv_scale& lambda) {
134  return exp_mod_normal_log<false>(y,mu,sigma,lambda);
135  }
136 
137  template <typename T_y, typename T_loc, typename T_scale,
138  typename T_inv_scale>
140  exp_mod_normal_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma,
141  const T_inv_scale& lambda) {
142  static const char* function = "stan::prob::exp_mod_normal_cdf(%1%)";
143 
148  using stan::math::value_of;
149 
150  double cdf(1.0);
151  //check if any vectors are zero length
152  if (!(stan::length(y)
153  && stan::length(mu)
154  && stan::length(sigma)
155  && stan::length(lambda)))
156  return cdf;
157 
158  check_not_nan(function, y, "Random variable", &cdf);
159  check_finite(function, mu, "Location parameter", &cdf);
160  check_not_nan(function, sigma, "Scale parameter", &cdf);
161  check_positive_finite(function, sigma, "Scale parameter", &cdf);
162  check_positive_finite(function, lambda, "Inv_scale parameter", &cdf);
163  check_not_nan(function, lambda, "Inv_scale parameter", &cdf);
164  check_consistent_sizes(function,
165  y,mu,sigma,lambda,
166  "Random variable","Location parameter",
167  "Scale parameter","Inv_scale paramter",
168  &cdf);
169 
171  operands_and_partials(y, mu, sigma,lambda);
172 
173  using stan::math::SQRT_2;
174 
175  VectorView<const T_y> y_vec(y);
176  VectorView<const T_loc> mu_vec(mu);
177  VectorView<const T_scale> sigma_vec(sigma);
178  VectorView<const T_inv_scale> lambda_vec(lambda);
179  size_t N = max_size(y, mu, sigma, lambda);
180  const double sqrt_pi = std::sqrt(stan::math::pi());
181  for (size_t n = 0; n < N; n++) {
182 
183  if(boost::math::isinf(y_vec[n])) {
184  if (y_vec[n] < 0.0)
185  return operands_and_partials.to_var(0.0);
186  }
187 
188  const double y_dbl = value_of(y_vec[n]);
189  const double mu_dbl = value_of(mu_vec[n]);
190  const double sigma_dbl = value_of(sigma_vec[n]);
191  const double lambda_dbl = value_of(lambda_vec[n]);
192  const double u = lambda_dbl * (y_dbl - mu_dbl);
193  const double v = lambda_dbl * sigma_dbl ;
194  const double v_sq = v * v;
195  const double scaled_diff = (y_dbl - mu_dbl) / (SQRT_2 * sigma_dbl);
196  const double scaled_diff_sq = scaled_diff * scaled_diff;
197  const double erf_calc = 0.5 * (1 + erf(-v / SQRT_2 + scaled_diff));
198  const double deriv_1 = lambda_dbl * exp(0.5 * v_sq - u) * erf_calc;
199  const double deriv_2 = SQRT_2 / sqrt_pi * 0.5 * exp(0.5 * v_sq
200  - (scaled_diff
201  - (v / SQRT_2)) * (scaled_diff
202  - (v / SQRT_2)) - u) / sigma_dbl;
203  const double deriv_3 = SQRT_2 / sqrt_pi * 0.5 * exp(-scaled_diff_sq)
204  / sigma_dbl;
205 
206  const double cdf_ = 0.5 * (1 + erf(u / (v * SQRT_2)))
207  - exp(-u + v_sq * 0.5) * (erf_calc);
208 
209  cdf *= cdf_;
210 
212  operands_and_partials.d_x1[n] += (deriv_1 - deriv_2 + deriv_3)
213  / cdf_;
215  operands_and_partials.d_x2[n] += (-deriv_1 + deriv_2 - deriv_3)
216  / cdf_;
218  operands_and_partials.d_x3[n] += (-deriv_1 * v - deriv_3
219  * scaled_diff * SQRT_2 - deriv_2 * sigma_dbl * SQRT_2 * (-SQRT_2
220  * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2 / sigma_dbl) - SQRT_2
221  * lambda_dbl)) / cdf_;
223  operands_and_partials.d_x4[n] += exp(0.5 * v_sq - u) * (SQRT_2
224  / sqrt_pi * 0.5 * sigma_dbl * exp(-(v / SQRT_2 - scaled_diff) * (v
225  / SQRT_2 - scaled_diff)) - (v * sigma_dbl + mu_dbl - y_dbl)
226  * erf_calc) / cdf_;
227  }
228 
230  for(size_t n = 0; n < stan::length(y); ++n)
231  operands_and_partials.d_x1[n] *= cdf;
232  }
234  for(size_t n = 0; n < stan::length(mu); ++n)
235  operands_and_partials.d_x2[n] *= cdf;
236  }
238  for(size_t n = 0; n < stan::length(sigma); ++n)
239  operands_and_partials.d_x3[n] *= cdf;
240  }
242  for(size_t n = 0; n < stan::length(lambda); ++n)
243  operands_and_partials.d_x4[n] *= cdf;
244  }
245 
246  return operands_and_partials.to_var(cdf);
247  }
248 
249  template <typename T_y, typename T_loc, typename T_scale,
250  typename T_inv_scale>
252  exp_mod_normal_cdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
253  const T_inv_scale& lambda) {
254  static const char* function = "stan::prob::exp_mod_normal_cdf_log(%1%)";
255 
260  using stan::math::value_of;
261 
262  double cdf_log(0.0);
263  //check if any vectors are zero length
264  if (!(stan::length(y)
265  && stan::length(mu)
266  && stan::length(sigma)
267  && stan::length(lambda)))
268  return cdf_log;
269 
270  check_not_nan(function, y, "Random variable", &cdf_log);
271  check_finite(function, mu, "Location parameter", &cdf_log);
272  check_not_nan(function, sigma, "Scale parameter", &cdf_log);
273  check_positive_finite(function, sigma, "Scale parameter", &cdf_log);
274  check_positive_finite(function, lambda, "Inv_scale parameter", &cdf_log);
275  check_not_nan(function, lambda, "Inv_scale parameter", &cdf_log);
276  check_consistent_sizes(function,
277  y,mu,sigma,lambda,
278  "Random variable","Location parameter",
279  "Scale parameter","Inv_scale paramter",
280  &cdf_log);
281 
283  operands_and_partials(y, mu, sigma,lambda);
284 
285  using stan::math::SQRT_2;
286  using std::log;
287 
288  VectorView<const T_y> y_vec(y);
289  VectorView<const T_loc> mu_vec(mu);
290  VectorView<const T_scale> sigma_vec(sigma);
291  VectorView<const T_inv_scale> lambda_vec(lambda);
292  size_t N = max_size(y, mu, sigma, lambda);
293  const double sqrt_pi = std::sqrt(stan::math::pi());
294  for (size_t n = 0; n < N; n++) {
295 
296  if(boost::math::isinf(y_vec[n])) {
297  if (y_vec[n] < 0.0)
298  return operands_and_partials.to_var(stan::math::negative_infinity());
299  else
300  return operands_and_partials.to_var(0.0);
301  }
302 
303  const double y_dbl = value_of(y_vec[n]);
304  const double mu_dbl = value_of(mu_vec[n]);
305  const double sigma_dbl = value_of(sigma_vec[n]);
306  const double lambda_dbl = value_of(lambda_vec[n]);
307  const double u = lambda_dbl * (y_dbl - mu_dbl);
308  const double v = lambda_dbl * sigma_dbl ;
309  const double v_sq = v * v;
310  const double scaled_diff = (y_dbl - mu_dbl) / (SQRT_2 * sigma_dbl);
311  const double scaled_diff_sq = scaled_diff * scaled_diff;
312  const double erf_calc1 = 0.5 * (1 + erf(u / (v * SQRT_2)));
313  const double erf_calc2 = 0.5 * (1 + erf(u / (v * SQRT_2) - v / SQRT_2));
314  const double deriv_1 = lambda_dbl * exp(0.5 * v_sq - u) * erf_calc2;
315  const double deriv_2 = SQRT_2 / sqrt_pi * 0.5
316  * exp(0.5 * v_sq - (-scaled_diff + (v / SQRT_2))
317  * (-scaled_diff + (v / SQRT_2)) - u) / sigma_dbl;
318  const double deriv_3 = SQRT_2 / sqrt_pi * 0.5 * exp(-scaled_diff_sq)
319  / sigma_dbl;
320 
321  const double denom = erf_calc1 - erf_calc2 * exp(0.5 * v_sq - u);
322  const double cdf_ = erf_calc1 - exp(-u + v_sq * 0.5) * (erf_calc2);
323 
324  cdf_log += log(cdf_);
325 
327  operands_and_partials.d_x1[n] += (deriv_1 - deriv_2 + deriv_3)
328  / denom;
330  operands_and_partials.d_x2[n] += (-deriv_1 + deriv_2 - deriv_3)
331  / denom;
333  operands_and_partials.d_x3[n]
334  += (-deriv_1 * v - deriv_3 * scaled_diff
335  * SQRT_2 - deriv_2 * sigma_dbl * SQRT_2
336  * (-SQRT_2 * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2
337  / sigma_dbl)
338  - SQRT_2 * lambda_dbl))
339  / denom;
341  operands_and_partials.d_x4[n]
342  += exp(0.5 * v_sq - u)
343  * (SQRT_2 / sqrt_pi * 0.5 * sigma_dbl
344  * exp(-(v / SQRT_2 - scaled_diff)
345  * (v / SQRT_2 - scaled_diff))
346  - (v * sigma_dbl + mu_dbl - y_dbl) * erf_calc2)
347  / denom;
348  }
349 
350  return operands_and_partials.to_var(cdf_log);
351  }
352 
353  template <typename T_y, typename T_loc, typename T_scale,
354  typename T_inv_scale>
356  exp_mod_normal_ccdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
357  const T_inv_scale& lambda) {
358  static const char* function = "stan::prob::exp_mod_normal_ccdf_log(%1%)";
359 
364  using stan::math::value_of;
365 
366  double ccdf_log(0.0);
367  //check if any vectors are zero length
368  if (!(stan::length(y)
369  && stan::length(mu)
370  && stan::length(sigma)
371  && stan::length(lambda)))
372  return ccdf_log;
373 
374  check_not_nan(function, y, "Random variable", &ccdf_log);
375  check_finite(function, mu, "Location parameter", &ccdf_log);
376  check_not_nan(function, sigma, "Scale parameter", &ccdf_log);
377  check_positive_finite(function, sigma, "Scale parameter", &ccdf_log);
378  check_positive_finite(function, lambda, "Inv_scale parameter", &ccdf_log);
379  check_not_nan(function, lambda, "Inv_scale parameter", &ccdf_log);
380  check_consistent_sizes(function,
381  y,mu,sigma,lambda,
382  "Random variable","Location parameter",
383  "Scale parameter","Inv_scale paramter",
384  &ccdf_log);
385 
387  operands_and_partials(y, mu, sigma,lambda);
388 
389  using stan::math::SQRT_2;
390  using std::log;
391 
392  VectorView<const T_y> y_vec(y);
393  VectorView<const T_loc> mu_vec(mu);
394  VectorView<const T_scale> sigma_vec(sigma);
395  VectorView<const T_inv_scale> lambda_vec(lambda);
396  size_t N = max_size(y, mu, sigma, lambda);
397  const double sqrt_pi = std::sqrt(stan::math::pi());
398  for (size_t n = 0; n < N; n++) {
399 
400  if(boost::math::isinf(y_vec[n])) {
401  if (y_vec[n] > 0.0)
402  return operands_and_partials.to_var(stan::math::negative_infinity());
403  else
404  return operands_and_partials.to_var(0.0);
405  }
406 
407  const double y_dbl = value_of(y_vec[n]);
408  const double mu_dbl = value_of(mu_vec[n]);
409  const double sigma_dbl = value_of(sigma_vec[n]);
410  const double lambda_dbl = value_of(lambda_vec[n]);
411  const double u = lambda_dbl * (y_dbl - mu_dbl);
412  const double v = lambda_dbl * sigma_dbl ;
413  const double v_sq = v * v;
414  const double scaled_diff = (y_dbl - mu_dbl) / (SQRT_2 * sigma_dbl);
415  const double scaled_diff_sq = scaled_diff * scaled_diff;
416  const double erf_calc1 = 0.5 * (1 + erf(u / (v * SQRT_2)));
417  const double erf_calc2 = 0.5 * (1 + erf(u / (v * SQRT_2) - v / SQRT_2));
418 
419  const double deriv_1 = lambda_dbl * exp(0.5 * v_sq - u) * erf_calc2;
420  const double deriv_2 = SQRT_2 / sqrt_pi * 0.5
421  * exp(0.5 * v_sq
422  - (-scaled_diff + (v / SQRT_2)) * (-scaled_diff
423  + (v / SQRT_2)) - u)
424  / sigma_dbl;
425  const double deriv_3 = SQRT_2 / sqrt_pi * 0.5 * exp(-scaled_diff_sq) / sigma_dbl;
426 
427  const double ccdf_ = 1.0 - erf_calc1 + exp(-u + v_sq * 0.5) * (erf_calc2);
428 
429  ccdf_log += log(ccdf_);
430 
432  operands_and_partials.d_x1[n]
433  -= (deriv_1 - deriv_2 + deriv_3) / ccdf_;
435  operands_and_partials.d_x2[n]
436  -= (-deriv_1 + deriv_2 - deriv_3) / ccdf_;
438  operands_and_partials.d_x3[n]
439  -= (-deriv_1 * v - deriv_3 * scaled_diff * SQRT_2 - deriv_2
440  * sigma_dbl * SQRT_2
441  * (-SQRT_2 * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2
442  / sigma_dbl)
443  - SQRT_2 * lambda_dbl))
444  / ccdf_;
446  operands_and_partials.d_x4[n] -= exp(0.5 * v_sq - u)
447  * (SQRT_2 / sqrt_pi * 0.5 * sigma_dbl
448  * exp(-(v / SQRT_2 - scaled_diff) * (v / SQRT_2 - scaled_diff))
449  - (v * sigma_dbl + mu_dbl - y_dbl) * erf_calc2)
450  / ccdf_;
451  }
452 
453  return operands_and_partials.to_var(ccdf_log);
454  }
455 
456  template <class RNG>
457  inline double
458  exp_mod_normal_rng(const double mu,
459  const double sigma,
460  const double lambda,
461  RNG& rng) {
462 
463  static const char* function = "stan::prob::exp_mod_normal_rng(%1%)";
464 
467 
468  check_finite(function, mu, "Location parameter", (double*)0);
469  check_positive_finite(function, lambda, "Inv_scale parameter",
470  (double*)0);
471  check_positive_finite(function, sigma, "Scale parameter", (double*)0);
472 
473  return stan::prob::normal_rng(mu, sigma,rng) + stan::prob::exponential_rng(lambda, rng);
474  }
475  }
476 }
477 #endif
478 
479 
480 
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_cdf(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
fvar< T > erf(const fvar< T > &x)
Definition: erf.hpp:17
T_return_type to_var(double logp)
bool check_positive_finite(const char *function, const T_y &y, const char *name, T_result *result)
size_t length(const T &)
Definition: traits.hpp:159
fvar< T > erfc(const fvar< T > &x)
Definition: erfc.hpp:17
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
double exponential_rng(const double beta, RNG &rng)
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
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
const double SQRT_2
The value of the square root of 2, .
Definition: constants.hpp:20
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
fvar< T > sqrt(const fvar< T > &x)
Definition: sqrt.hpp:15
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_ccdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
bool check_consistent_sizes(const char *function, const T1 &x1, const T2 &x2, const char *name1, const char *name2, T_result *result)
double normal_rng(const double mu, const double sigma, RNG &rng)
Definition: normal.hpp:377
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.
VectorView< double *, is_vector< T4 >::value, is_constant_struct< T4 >::value > d_x4
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_cdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
VectorView< double *, is_vector< T3 >::value, is_constant_struct< T3 >::value > d_x3
double pi()
Return the value of pi.
Definition: constants.hpp:77
double exp_mod_normal_rng(const double mu, const double sigma, const double lambda, RNG &rng)
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.