Automatic Differentiation
 
Loading...
Searching...
No Matches
gp_periodic_cov.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_FUN_GP_PERIODIC_COV_HPP
2#define STAN_MATH_REV_FUN_GP_PERIODIC_COV_HPP
3
13#include <cmath>
14#include <type_traits>
15#include <vector>
16
17namespace stan {
18namespace math {
19
40template <typename T_x, typename T_sigma, require_st_arithmetic<T_x>* = nullptr,
41 require_stan_scalar_t<T_sigma>* = nullptr>
42inline Eigen::Matrix<var, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(
43 const std::vector<T_x>& x, const T_sigma sigma, const var l, const var p) {
44 using std::exp;
45 using std::sin;
46 const char* fun = "gp_periodic_cov";
47 check_positive(fun, "signal standard deviation", sigma);
48 check_positive(fun, "length-scale", l);
49 check_positive(fun, "period", p);
50 size_t x_size = x.size();
51 for (size_t i = 0; i < x_size; ++i) {
52 check_not_nan(fun, "element of x", x[i]);
53 }
54
55 Eigen::Matrix<var, -1, -1> cov(x_size, x_size);
56 if (x_size == 0) {
57 return cov;
58 }
59 size_t l_tri_size = x_size * (x_size - 1) / 2;
60 arena_matrix<Eigen::VectorXd> dists_lin(l_tri_size);
61 arena_matrix<Eigen::VectorXd> sin_dists_sq_lin(l_tri_size);
62 arena_matrix<Eigen::Matrix<var, -1, 1>> cov_l_tri_lin(l_tri_size);
63 arena_matrix<Eigen::Matrix<var, -1, 1>> cov_diag(
64 is_constant<T_sigma>::value ? 0 : x_size);
65
66 double sigma_sq = square(value_of(sigma));
67 double pi_div_p = pi() / value_of(p);
68 double neg_two_inv_l_sq = -2.0 / square(value_of(l));
69
70 size_t block_size = 10;
71 size_t pos = 0;
72 for (size_t jb = 0; jb < x_size; jb += block_size) {
73 size_t j_end = std::min(x_size, jb + block_size);
74 size_t j_size = j_end - jb;
75 cov.diagonal().segment(jb, j_size)
76 = Eigen::VectorXd::Constant(j_size, sigma_sq);
77
79 cov_diag.segment(jb, j_size) = cov.diagonal().segment(jb, j_size);
80 }
81 for (size_t ib = jb; ib < x_size; ib += block_size) {
82 size_t i_end = std::min(x_size, ib + block_size);
83 for (size_t j = jb; j < j_end; ++j) {
84 for (size_t i = std::max(ib, j + 1); i < i_end; ++i) {
85 double dist = distance(x[i], x[j]);
86 double sin_dist = sin(pi_div_p * dist);
87 double sin_dist_sq = square(sin_dist);
88 dists_lin.coeffRef(pos) = dist;
89 sin_dists_sq_lin.coeffRef(pos) = sin_dist_sq;
90 cov_l_tri_lin.coeffRef(pos) = cov.coeffRef(j, i) = cov.coeffRef(i, j)
91 = sigma_sq * exp(sin_dist_sq * neg_two_inv_l_sq);
92 ++pos;
93 }
94 }
95 }
96 }
97
98 reverse_pass_callback([cov_l_tri_lin, cov_diag, dists_lin, sin_dists_sq_lin,
99 sigma, l, p, x_size]() {
100 size_t l_tri_size = x_size * (x_size - 1) / 2;
101 double l_val = value_of(l);
102 double p_val = value_of(p);
103 double two_pi_div_p = TWO_PI / p_val;
104
105 double adjl = 0;
106 double adjsigma = 0;
107 double adjp = 0;
108
109 for (size_t pos = 0; pos < l_tri_size; ++pos) {
110 double prod_add
111 = cov_l_tri_lin.coeff(pos).val() * cov_l_tri_lin.coeff(pos).adj();
112 adjl += prod_add * sin_dists_sq_lin.coeff(pos);
113 adjsigma += prod_add;
114 double dist = dists_lin.coeff(pos);
115 adjp += prod_add * sin(two_pi_div_p * dist) * dist;
116 }
118 adjsigma += (cov_diag.val().array() * cov_diag.adj().array()).sum();
119 adjoint_of(sigma) += adjsigma * 2 / value_of(sigma);
120 }
121 double l_sq = square(l_val);
122 l.adj() += adjl * 4 / (l_sq * l_val);
123 p.adj() += adjp * TWO_PI / (l_sq * square(p_val));
124 });
125
126 return cov;
127} // namespace math
128
129} // namespace math
130} // namespace stan
131#endif
Equivalent to Eigen::Matrix, except that the data is stored on AD stack.
fvar< T > sin(const fvar< T > &x)
Definition sin.hpp:14
auto distance(const T_a &a, const T_b &b)
Returns the distance between the specified vectors.
Definition distance.hpp:33
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
auto & adjoint_of(const T &x)
Returns a reference to a variable's adjoint.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
Eigen::Matrix< return_type_t< T_x, T_sigma, T_l, T_p >, Eigen::Dynamic, Eigen::Dynamic > gp_periodic_cov(const std::vector< T_x > &x, const T_sigma &sigma, const T_l &l, const T_p &p)
Returns a periodic covariance matrix using the input .
auto sum(const std::vector< T > &m)
Return the sum of the entries of the specified standard vector.
Definition sum.hpp:23
static constexpr double TWO_PI
Twice the value of , .
Definition constants.hpp:62
var_value< double > var
Definition var.hpp:1187
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
static constexpr double pi()
Return the value of pi.
Definition constants.hpp:36
fvar< T > square(const fvar< T > &x)
Definition square.hpp:12
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:13
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Metaprogramming struct to detect whether a given type is constant in the mathematical sense (not the ...