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
16#include <cmath>
17#include <type_traits>
18#include <vector>
19
20namespace stan {
21namespace math {
22
43template <typename T_x, typename T_sigma, require_st_arithmetic<T_x>* = nullptr,
44 require_stan_scalar_t<T_sigma>* = nullptr>
45inline Eigen::Matrix<var, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(
46 const std::vector<T_x>& x, const T_sigma sigma, const var l, const var p) {
47 const char* fun = "gp_periodic_cov";
48 check_positive(fun, "signal standard deviation", sigma);
49 check_positive(fun, "length-scale", l);
50 check_positive(fun, "period", p);
51 size_t x_size = x.size();
52 for (size_t i = 0; i < x_size; ++i) {
53 check_not_nan(fun, "element of x", x[i]);
54 }
55
56 Eigen::Matrix<var, -1, -1> cov(x_size, x_size);
57 if (x_size == 0) {
58 return cov;
59 }
60 size_t l_tri_size = x_size * (x_size - 1) / 2;
61 arena_matrix<Eigen::VectorXd> dists_lin(l_tri_size);
62 arena_matrix<Eigen::VectorXd> sin_dists_sq_lin(l_tri_size);
63 arena_matrix<Eigen::Matrix<var, -1, 1>> cov_l_tri_lin(l_tri_size);
64 arena_matrix<Eigen::Matrix<var, -1, 1>> cov_diag(
65 is_constant<T_sigma>::value ? 0 : x_size);
66
67 double sigma_sq = square(value_of(sigma));
68 double pi_div_p = pi() / value_of(p);
69 double neg_two_inv_l_sq = -2.0 / square(value_of(l));
70
71 size_t block_size = 10;
72 size_t pos = 0;
73 for (size_t jb = 0; jb < x_size; jb += block_size) {
74 size_t j_end = std::min(x_size, jb + block_size);
75 size_t j_size = j_end - jb;
76 cov.diagonal().segment(jb, j_size)
77 = Eigen::VectorXd::Constant(j_size, sigma_sq);
78
80 cov_diag.segment(jb, j_size) = cov.diagonal().segment(jb, j_size);
81 }
82 for (size_t ib = jb; ib < x_size; ib += block_size) {
83 size_t i_end = std::min(x_size, ib + block_size);
84 for (size_t j = jb; j < j_end; ++j) {
85 for (size_t i = std::max(ib, j + 1); i < i_end; ++i) {
86 double dist = distance(x[i], x[j]);
87 double sin_dist = sin(pi_div_p * dist);
88 double sin_dist_sq = square(sin_dist);
89 dists_lin.coeffRef(pos) = dist;
90 sin_dists_sq_lin.coeffRef(pos) = sin_dist_sq;
91 cov_l_tri_lin.coeffRef(pos) = cov.coeffRef(j, i) = cov.coeffRef(i, j)
92 = sigma_sq * exp(sin_dist_sq * neg_two_inv_l_sq);
93 ++pos;
94 }
95 }
96 }
97 }
98
99 reverse_pass_callback([cov_l_tri_lin, cov_diag, dists_lin, sin_dists_sq_lin,
100 sigma, l, p, x_size]() {
101 size_t l_tri_size = x_size * (x_size - 1) / 2;
102 double l_val = value_of(l);
103 double p_val = value_of(p);
104 double two_pi_div_p = TWO_PI / p_val;
105
106 double adjl = 0;
107 double adjsigma = 0;
108 double adjp = 0;
109
110 for (size_t pos = 0; pos < l_tri_size; ++pos) {
111 double prod_add
112 = cov_l_tri_lin.coeff(pos).val() * cov_l_tri_lin.coeff(pos).adj();
113 adjl += prod_add * sin_dists_sq_lin.coeff(pos);
114 adjsigma += prod_add;
115 double dist = dists_lin.coeff(pos);
116 adjp += prod_add * sin(two_pi_div_p * dist) * dist;
117 }
119 adjsigma += (cov_diag.val().array() * cov_diag.adj().array()).sum();
120 adjoint_of(sigma) += adjsigma * 2 / value_of(sigma);
121 }
122 double l_sq = square(l_val);
123 l.adj() += adjl * 4 / (l_sq * l_val);
124 p.adj() += adjp * TWO_PI / (l_sq * square(p_val));
125 });
126
127 return cov;
128} // namespace math
129
130} // namespace math
131} // namespace stan
132#endif
Equivalent to Eigen::Matrix, except that the data is stored on AD stack.
fvar< T > sin(const fvar< T > &x)
Definition sin.hpp:16
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:15
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 ...