Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
skew_normal.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__SKEW__NORMAL__HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__SKEW__NORMAL__HPP
3 
4 #include <boost/random/variate_generator.hpp>
5 #include <boost/math/distributions.hpp>
7 
11 #include <stan/meta/traits.hpp>
12 #include <stan/prob/constants.hpp>
13 #include <stan/prob/traits.hpp>
15 
16 namespace stan {
17 
18  namespace prob {
19 
20  template <bool propto,
21  typename T_y, typename T_loc, typename T_scale, typename T_shape>
22  typename return_type<T_y,T_loc,T_scale,T_shape>::type
23  skew_normal_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
24  const T_shape& alpha) {
25  static const char* function = "stan::prob::skew_normal_log(%1%)";
26 
27  using std::log;
35 
36  // check if any vectors are zero length
37  if (!(stan::length(y)
38  && stan::length(mu)
39  && stan::length(sigma)
40  && stan::length(alpha)))
41  return 0.0;
42 
43  // set up return value accumulator
44  double logp(0.0);
45 
46  // validate args (here done over var, which should be OK)
47  check_not_nan(function, y, "Random variable", &logp);
48  check_finite(function, mu, "Location parameter", &logp);
49  check_finite(function, alpha, "Shape parameter", &logp);
50  check_positive(function, sigma, "Scale parameter", &logp);
51  check_consistent_sizes(function,
52  y,mu,sigma,alpha,
53  "Random variable","Location parameter",
54  "Scale parameter", "Shape paramter",
55  &logp);
56 
57  // check if no variables are involved and prop-to
59  return 0.0;
60 
61  // set up template expressions wrapping scalars into vector views
63  operands_and_partials(y, mu, sigma, alpha);
64 
65  VectorView<const T_y> y_vec(y);
66  VectorView<const T_loc> mu_vec(mu);
67  VectorView<const T_scale> sigma_vec(sigma);
68  VectorView<const T_shape> alpha_vec(alpha);
69  size_t N = max_size(y, mu, sigma, alpha);
70 
73  is_vector<T_scale>::value> log_sigma(length(sigma));
74  for (size_t i = 0; i < length(sigma); i++) {
75  inv_sigma[i] = 1.0 / value_of(sigma_vec[i]);
77  log_sigma[i] = log(value_of(sigma_vec[i]));
78  }
79 
80  for (size_t n = 0; n < N; n++) {
81  // pull out values of arguments
82  const double y_dbl = value_of(y_vec[n]);
83  const double mu_dbl = value_of(mu_vec[n]);
84  const double sigma_dbl = value_of(sigma_vec[n]);
85  const double alpha_dbl = value_of(alpha_vec[n]);
86 
87  // reusable subexpression values
88  const double y_minus_mu_over_sigma
89  = (y_dbl - mu_dbl) * inv_sigma[n];
90  const double pi_dbl = boost::math::constants::pi<double>();
91 
92  // log probability
94  logp -= 0.5 * log(2.0 * pi_dbl);
96  logp -= log(sigma_dbl);
98  logp -= y_minus_mu_over_sigma * y_minus_mu_over_sigma / 2.0;
100  logp += log(boost::math::erfc(-alpha_dbl * y_minus_mu_over_sigma
101  / std::sqrt(2.0)));
102 
103  // gradients
104  double deriv_logerf
105  = 2.0 / std::sqrt(pi_dbl)
106  * exp(-alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0)
107  * alpha_dbl * y_minus_mu_over_sigma / std::sqrt(2.0))
108  / (1 + boost::math::erf(alpha_dbl * y_minus_mu_over_sigma
109  / std::sqrt(2.0)));
111  operands_and_partials.d_x1[n]
112  += -y_minus_mu_over_sigma / sigma_dbl
113  + deriv_logerf * alpha_dbl / (sigma_dbl * std::sqrt(2.0)) ;
115  operands_and_partials.d_x2[n]
116  += y_minus_mu_over_sigma / sigma_dbl
117  + deriv_logerf * -alpha_dbl / (sigma_dbl * std::sqrt(2.0));
119  operands_and_partials.d_x3[n]
120  += -1.0 / sigma_dbl
121  + y_minus_mu_over_sigma * y_minus_mu_over_sigma / sigma_dbl
122  - deriv_logerf * y_minus_mu_over_sigma * alpha_dbl
123  / (sigma_dbl * std::sqrt(2.0));
125  operands_and_partials.d_x4[n]
126  += deriv_logerf * y_minus_mu_over_sigma / std::sqrt(2.0);
127  }
128  return operands_and_partials.to_var(logp);
129  }
130 
131  template <typename T_y, typename T_loc, typename T_scale, typename T_shape>
132  inline
134  skew_normal_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
135  const T_shape& alpha) {
136  return skew_normal_log<false>(y,mu,sigma,alpha);
137  }
138 
139  template <typename T_y, typename T_loc, typename T_scale, typename T_shape>
141  skew_normal_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma,
142  const T_shape& alpha) {
143  static const char* function = "stan::prob::skew_normal_cdf(%1%)";
144 
149  using stan::math::owens_t;
150  using stan::math::value_of;
151 
152  double cdf(1.0);
153 
154  // check if any vectors are zero length
155  if (!(stan::length(y)
156  && stan::length(mu)
157  && stan::length(sigma)
158  && stan::length(alpha)))
159  return cdf;
160 
161  check_not_nan(function, y, "Random variable", &cdf);
162  check_finite(function, mu, "Location parameter", &cdf);
163  check_not_nan(function, sigma, "Scale parameter", &cdf);
164  check_positive(function, sigma, "Scale parameter", &cdf);
165  check_finite(function, alpha, "Shape parameter", &cdf);
166  check_not_nan(function, alpha, "Shape parameter", &cdf);
167  check_consistent_sizes(function,
168  y,mu,sigma,alpha,
169  "Random variable","Location parameter",
170  "Scale parameter","Shape paramter",
171  &cdf);
172 
174  operands_and_partials(y, mu, sigma, alpha);
175 
176  using stan::math::SQRT_2;
177  using stan::math::pi;
178 
179  VectorView<const T_y> y_vec(y);
180  VectorView<const T_loc> mu_vec(mu);
181  VectorView<const T_scale> sigma_vec(sigma);
182  VectorView<const T_shape> alpha_vec(alpha);
183  size_t N = max_size(y, mu, sigma, alpha);
184  const double SQRT_TWO_OVER_PI = std::sqrt(2.0 / stan::math::pi());
185 
186  for (size_t n = 0; n < N; n++) {
187  const double y_dbl = value_of(y_vec[n]);
188  const double mu_dbl = value_of(mu_vec[n]);
189  const double sigma_dbl = value_of(sigma_vec[n]);
190  const double alpha_dbl = value_of(alpha_vec[n]);
191  const double alpha_dbl_sq = alpha_dbl * alpha_dbl;
192  const double diff = (y_dbl - mu_dbl) / sigma_dbl;
193  const double diff_sq = diff * diff;
194  const double scaled_diff = diff / SQRT_2;
195  const double scaled_diff_sq = diff_sq * 0.5;
196  const double cdf_ = 0.5 * erfc(-scaled_diff) - 2 * owens_t(diff,
197  alpha_dbl);
198  //cdf
199  cdf *= cdf_;
200 
201  //gradients
202  const double deriv_erfc = SQRT_TWO_OVER_PI * 0.5 * exp(-scaled_diff_sq)
203  / sigma_dbl;
204  const double deriv_owens = erf(alpha_dbl * scaled_diff)
205  * exp(-scaled_diff_sq) / SQRT_TWO_OVER_PI / (-2.0 * pi()) / sigma_dbl;
206  const double rep_deriv = (-2.0 * deriv_owens + deriv_erfc) / cdf_;
207 
209  operands_and_partials.d_x1[n] += rep_deriv;
211  operands_and_partials.d_x2[n] -= rep_deriv;
213  operands_and_partials.d_x3[n] -= rep_deriv * diff;
215  operands_and_partials.d_x4[n] += -2.0 * exp(-0.5 * diff_sq * (1.0
216  + alpha_dbl_sq)) / ((1 + alpha_dbl_sq) * 2.0 * pi()) / cdf_;
217  }
218 
220  for (size_t n = 0; n < stan::length(y); ++n)
221  operands_and_partials.d_x1[n] *= cdf;
223  for (size_t n = 0; n < stan::length(mu); ++n)
224  operands_and_partials.d_x2[n] *= cdf;
226  for (size_t n = 0; n < stan::length(sigma); ++n)
227  operands_and_partials.d_x3[n] *= cdf;
229  for (size_t n = 0; n < stan::length(alpha); ++n)
230  operands_and_partials.d_x4[n] *= cdf;
231 
232  return operands_and_partials.to_var(cdf);
233  }
234 
235  template <typename T_y, typename T_loc, typename T_scale, typename T_shape>
237  skew_normal_cdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
238  const T_shape& alpha) {
239  static const char* function = "stan::prob::skew_normal_cdf_log(%1%)";
240 
244  using stan::math::value_of;
246  using stan::math::owens_t;
247 
248  double cdf_log(0.0);
249 
250  // check if any vectors are zero length
251  if (!(stan::length(y)
252  && stan::length(mu)
253  && stan::length(sigma)
254  && stan::length(alpha)))
255  return cdf_log;
256 
257  check_not_nan(function, y, "Random variable", &cdf_log);
258  check_finite(function, mu, "Location parameter", &cdf_log);
259  check_not_nan(function, sigma, "Scale parameter", &cdf_log);
260  check_positive(function, sigma, "Scale parameter", &cdf_log);
261  check_finite(function, alpha, "Shape parameter", &cdf_log);
262  check_not_nan(function, alpha, "Shape parameter", &cdf_log);
263  check_consistent_sizes(function,
264  y,mu,sigma,alpha,
265  "Random variable","Location parameter",
266  "Scale parameter","Shape paramter",
267  &cdf_log);
268 
270  operands_and_partials(y, mu, sigma, alpha);
271 
272  using stan::math::SQRT_2;
273  using stan::math::pi;
274 
275  VectorView<const T_y> y_vec(y);
276  VectorView<const T_loc> mu_vec(mu);
277  VectorView<const T_scale> sigma_vec(sigma);
278  VectorView<const T_shape> alpha_vec(alpha);
279  size_t N = max_size(y, mu, sigma, alpha);
280  const double SQRT_TWO_OVER_PI = std::sqrt(2.0 / stan::math::pi());
281 
282  for (size_t n = 0; n < N; n++) {
283  const double y_dbl = value_of(y_vec[n]);
284  const double mu_dbl = value_of(mu_vec[n]);
285  const double sigma_dbl = value_of(sigma_vec[n]);
286  const double alpha_dbl = value_of(alpha_vec[n]);
287  const double alpha_dbl_sq = alpha_dbl * alpha_dbl;
288  const double diff = (y_dbl - mu_dbl) / sigma_dbl;
289  const double diff_sq = diff * diff;
290  const double scaled_diff = diff / SQRT_2;
291  const double scaled_diff_sq = diff_sq * 0.5;
292  const double cdf_log_ = 0.5 * erfc(-scaled_diff) - 2 * owens_t(diff,
293  alpha_dbl);
294  //cdf_log
295  cdf_log += log(cdf_log_);
296 
297  //gradients
298  const double deriv_erfc = SQRT_TWO_OVER_PI * 0.5 * exp(-scaled_diff_sq)
299  / sigma_dbl;
300  const double deriv_owens = erf(alpha_dbl * scaled_diff)
301  * exp(-scaled_diff_sq) / SQRT_TWO_OVER_PI / (-2.0 * pi()) / sigma_dbl;
302  const double rep_deriv = (-2.0 * deriv_owens + deriv_erfc) / cdf_log_;
303 
305  operands_and_partials.d_x1[n] += rep_deriv;
307  operands_and_partials.d_x2[n] -= rep_deriv;
309  operands_and_partials.d_x3[n] -= rep_deriv * diff;
311  operands_and_partials.d_x4[n] += -2.0 * exp(-0.5 * diff_sq * (1.0
312  + alpha_dbl_sq)) / ((1 + alpha_dbl_sq) * 2.0 * pi()) / cdf_log_;
313  }
314 
315  return operands_and_partials.to_var(cdf_log);
316  }
317 
318  template <typename T_y, typename T_loc, typename T_scale, typename T_shape>
320  skew_normal_ccdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
321  const T_shape& alpha) {
322  static const char* function = "stan::prob::skew_normal_ccdf_log(%1%)";
323 
328  using stan::math::owens_t;
329  using stan::math::value_of;
330 
331  double ccdf_log(0.0);
332 
333  // check if any vectors are zero length
334  if (!(stan::length(y)
335  && stan::length(mu)
336  && stan::length(sigma)
337  && stan::length(alpha)))
338  return ccdf_log;
339 
340  check_not_nan(function, y, "Random variable", &ccdf_log);
341  check_finite(function, mu, "Location parameter", &ccdf_log);
342  check_not_nan(function, sigma, "Scale parameter", &ccdf_log);
343  check_positive(function, sigma, "Scale parameter", &ccdf_log);
344  check_finite(function, alpha, "Shape parameter", &ccdf_log);
345  check_not_nan(function, alpha, "Shape parameter", &ccdf_log);
346  check_consistent_sizes(function,
347  y,mu,sigma,alpha,
348  "Random variable","Location parameter",
349  "Scale parameter","Shape paramter",
350  &ccdf_log);
351 
353  operands_and_partials(y, mu, sigma, alpha);
354 
355  using stan::math::SQRT_2;
356  using stan::math::pi;
357 
358  VectorView<const T_y> y_vec(y);
359  VectorView<const T_loc> mu_vec(mu);
360  VectorView<const T_scale> sigma_vec(sigma);
361  VectorView<const T_shape> alpha_vec(alpha);
362  size_t N = max_size(y, mu, sigma, alpha);
363  const double SQRT_TWO_OVER_PI = std::sqrt(2.0 / stan::math::pi());
364 
365  for (size_t n = 0; n < N; n++) {
366  const double y_dbl = value_of(y_vec[n]);
367  const double mu_dbl = value_of(mu_vec[n]);
368  const double sigma_dbl = value_of(sigma_vec[n]);
369  const double alpha_dbl = value_of(alpha_vec[n]);
370  const double alpha_dbl_sq = alpha_dbl * alpha_dbl;
371  const double diff = (y_dbl - mu_dbl) / sigma_dbl;
372  const double diff_sq = diff * diff;
373  const double scaled_diff = diff / SQRT_2;
374  const double scaled_diff_sq = diff_sq * 0.5;
375  const double ccdf_log_ = 1.0 - 0.5 * erfc(-scaled_diff) + 2 * owens_t(diff,
376  alpha_dbl);
377  //ccdf_log
378  ccdf_log += log(ccdf_log_);
379 
380  //gradients
381  const double deriv_erfc = SQRT_TWO_OVER_PI * 0.5 * exp(-scaled_diff_sq)
382  / sigma_dbl;
383  const double deriv_owens = erf(alpha_dbl * scaled_diff)
384  * exp(-scaled_diff_sq) / SQRT_TWO_OVER_PI / (-2.0 * pi()) / sigma_dbl;
385  const double rep_deriv = (-2.0 * deriv_owens + deriv_erfc) / ccdf_log_;
386 
388  operands_and_partials.d_x1[n] -= rep_deriv;
390  operands_and_partials.d_x2[n] += rep_deriv;
392  operands_and_partials.d_x3[n] += rep_deriv * diff;
394  operands_and_partials.d_x4[n] -= -2.0 * exp(-0.5 * diff_sq * (1.0
395  + alpha_dbl_sq)) / ((1 + alpha_dbl_sq) * 2.0 * pi()) / ccdf_log_;
396  }
397 
398  return operands_and_partials.to_var(ccdf_log);
399  }
400 
401  template <class RNG>
402  inline double
403  skew_normal_rng(const double mu,
404  const double sigma,
405  const double alpha,
406  RNG& rng) {
407  boost::math::skew_normal_distribution<>dist (mu, sigma, alpha);
408 
409  static const char* function = "stan::prob::skew_normal_rng(%1%)";
410 
413 
414  check_finite(function, mu, "Location parameter", (double*)0);
415  check_finite(function, alpha, "Shape parameter", (double*)0);
416  check_positive(function, sigma, "Scale parameter", (double*)0);
417 
418  return quantile(dist, stan::prob::uniform_rng(0.0,1.0,rng));
419  }
420  }
421 }
422 #endif
423 
fvar< T > erf(const fvar< T > &x)
Definition: erf.hpp:17
T_return_type to_var(double logp)
size_t length(const T &)
Definition: traits.hpp:159
fvar< T > erfc(const fvar< T > &x)
Definition: erfc.hpp:17
DoubleVectorView allocates double values to be used as intermediate values.
Definition: traits.hpp:358
return_type< T_y, T_loc, T_scale, T_shape >::type skew_normal_cdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_shape &alpha)
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
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
return_type< T_y, T_loc, T_scale, T_shape >::type skew_normal_cdf(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_shape &alpha)
boost::math::tools::promote_args< T1, T2 >::type owens_t(const T1 &h, const T2 &a)
The Owen's T function of h and a.
Definition: owens_t.hpp:64
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
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
Definition: traits.hpp:35
double skew_normal_rng(const double mu, const double sigma, const double alpha, RNG &rng)
const double SQRT_2
The value of the square root of 2, .
Definition: constants.hpp:20
fvar< T > owens_t(const fvar< T > &x1, const fvar< T > &x2)
Definition: owens_t.hpp:17
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_shape >::type skew_normal_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_shape &alpha)
Definition: skew_normal.hpp:23
double uniform_rng(const double alpha, const double beta, RNG &rng)
Definition: uniform.hpp:339
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_positive(const char *function, const T_y &y, const char *name, T_result *result)
return_type< T_y, T_loc, T_scale, T_shape >::type skew_normal_ccdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_shape &alpha)
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
VectorView< double *, is_vector< T3 >::value, is_constant_struct< T3 >::value > d_x3
double pi()
Return the value of pi.
Definition: constants.hpp:77
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 dist(const std::vector< double > &x, const std::vector< double > &y)
Definition: dist.hpp:11

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