1 #ifndef STAN_MATH_PRIM_FUN_COV_DOT_PROD_HPP
2 #define STAN_MATH_PRIM_FUN_COV_DOT_PROD_HPP
3
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/Eigen.hpp>
7 #include <stan/math/prim/fun/dot_product.hpp>
8 #include <stan/math/prim/fun/dot_self.hpp>
9 #include <stan/math/prim/fun/square.hpp>
10 #include <vector>
11
12 namespace stan {
13 namespace math {
14
15 /**
16 * Returns a dot product covariance matrix. A member of Stan's Gaussian Process
17 * Library.
18 *
19 * \f$k(x,x') = \sigma^2 + x \cdot x'\f$
20 *
21 * A dot product covariance matrix is the same covariance matrix
22 * as in bayesian regression with \f$N(0,1)\f$ priors on regression coefficients
23 * and a \f$N(0,\sigma^2)\f$ prior on the constant function. See Rasmussen and
24 * Williams et al 2006, Chapter 4.
25 *
26 * @tparam T_x type of std::vector of elements
27 * @tparam T_sigma type of sigma
28 *
29 * @param x std::vector of elements that can be used in dot product.
30 * This function assumes each element of x is the same size.
31 * @param sigma constant function that can be used in stan::math::square
32 * @return dot product covariance matrix that is positive semi-definite
33 * @throw std::domain_error if sigma < 0, nan, inf or
34 * x is nan or infinite
35 */
36 template <typename T_x, typename T_sigma>
37 Eigen::Matrix<return_type_t<T_x, T_sigma>, Eigen::Dynamic, Eigen::Dynamic>
gp_dot_prod_cov(const std::vector<Eigen::Matrix<T_x,Eigen::Dynamic,1>> & x,const T_sigma & sigma)38 gp_dot_prod_cov(const std::vector<Eigen::Matrix<T_x, Eigen::Dynamic, 1>> &x,
39 const T_sigma &sigma) {
40 check_not_nan("gp_dot_prod_cov", "sigma", sigma);
41 check_nonnegative("gp_dot_prod_cov", "sigma", sigma);
42 check_finite("gp_dot_prod_cov", "sigma", sigma);
43
44 size_t x_size = x.size();
45 for (size_t i = 0; i < x_size; ++i) {
46 check_not_nan("gp_dot_prod_cov", "x", x[i]);
47 check_finite("gp_dot_prod_cov", "x", x[i]);
48 }
49
50 Eigen::Matrix<return_type_t<T_x, T_sigma>, Eigen::Dynamic, Eigen::Dynamic>
51 cov(x_size, x_size);
52 if (x_size == 0) {
53 return cov;
54 }
55
56 T_sigma sigma_sq = square(sigma);
57 size_t block_size = 10;
58
59 for (size_t jb = 0; jb < x_size; jb += block_size) {
60 for (size_t ib = jb; ib < x_size; ib += block_size) {
61 size_t j_end = std::min(x_size, jb + block_size);
62 for (size_t j = jb; j < j_end; ++j) {
63 cov.coeffRef(j, j) = sigma_sq + dot_self(x[j]);
64 size_t i_end = std::min(x_size, ib + block_size);
65 for (size_t i = std::max(ib, j + 1); i < i_end; ++i) {
66 cov.coeffRef(j, i) = cov.coeffRef(i, j)
67 = sigma_sq + dot_product(x[i], x[j]);
68 }
69 }
70 }
71 }
72 cov.coeffRef(x_size - 1, x_size - 1) = sigma_sq + dot_self(x[x_size - 1]);
73 return cov;
74 }
75
76 /**
77 * Returns a dot product covariance matrix. A member of Stan's Gaussian
78 * Process Library.
79 *
80 * \f$k(x,x') = \sigma^2 + x \cdot x'\f$
81 *
82 * A dot product covariance matrix is the same covariance matrix
83 * as in bayesian regression with \f$N(0,1)\f$ priors on regression coefficients
84 * and a \f$N(0,\sigma^2)\f$ prior on the constant function. See Rasmussen and
85 * Williams et al 2006, Chapter 4.
86 *
87 * @tparam T_x type of std::vector of double
88 * @tparam T_sigma type of sigma
89 *
90 * @param x std::vector of elements that can be used in transpose
91 * and multiply
92 * This function assumes each element of x is the same size.
93 * @param sigma constant function that can be used in stan::math::square
94 * @return dot product covariance matrix that is positive semi-definite
95 * @throw std::domain_error if sigma < 0, nan, inf or
96 * x is nan or infinite
97 */
98 template <typename T_x, typename T_sigma>
99 Eigen::Matrix<return_type_t<T_x, T_sigma>, Eigen::Dynamic, Eigen::Dynamic>
gp_dot_prod_cov(const std::vector<T_x> & x,const T_sigma & sigma)100 gp_dot_prod_cov(const std::vector<T_x> &x, const T_sigma &sigma) {
101 check_nonnegative("gp_dot_prod_cov", "sigma", sigma);
102 check_finite("gp_dot_prod_cov", "sigma", sigma);
103
104 size_t x_size = x.size();
105 check_finite("gp_dot_prod_cov", "x", x);
106
107 Eigen::Matrix<return_type_t<T_x, T_sigma>, Eigen::Dynamic, Eigen::Dynamic>
108 cov(x_size, x_size);
109 if (x_size == 0) {
110 return cov;
111 }
112
113 T_sigma sigma_sq = square(sigma);
114 size_t block_size = 10;
115
116 for (size_t jb = 0; jb < x_size; jb += block_size) {
117 for (size_t ib = jb; ib < x_size; ib += block_size) {
118 size_t j_end = std::min(x_size, jb + block_size);
119 for (size_t j = jb; j < j_end; ++j) {
120 cov.coeffRef(j, j) = sigma_sq + x[j] * x[j];
121 size_t i_end = std::min(x_size, ib + block_size);
122 for (size_t i = std::max(ib, j + 1); i < i_end; ++i) {
123 cov.coeffRef(j, i) = cov.coeffRef(i, j) = sigma_sq + x[i] * x[j];
124 }
125 }
126 }
127 }
128 cov(x_size - 1, x_size - 1) = sigma_sq + x[x_size - 1] * x[x_size - 1];
129 return cov;
130 }
131
132 /**
133 * Returns a dot product covariance matrix of differing
134 * x's. A member of Stan's Gaussian Process Library.
135 *
136 * \f$k(x,x') = \sigma^2 + x \cdot x'\f$
137 *
138 * A dot product covariance matrix is the same covariance matrix
139 * as in bayesian regression with \f$N(0,1)\f$ priors on regression coefficients
140 * and a \f$N(0,\sigma^2)\f$ prior on the constant function. See Rasmussen and
141 * Williams et al 2006, Chapter 4.
142 *
143 * @tparam T_x1 type of first std::vector of elements
144 * @tparam T_x2 type of second std::vector of elements
145 * @tparam T_sigma type of sigma
146 *
147 * @param x1 std::vector of elements that can be used in dot_product
148 * @param x2 std::vector of elements that can be used in dot_product
149 * @param sigma constant function that can be used in stan::math::square
150 * @return dot product covariance matrix that is not always symmetric
151 * @throw std::domain_error if sigma < 0, nan or inf
152 * or if x1 or x2 are nan or inf
153 */
154 template <typename T_x1, typename T_x2, typename T_sigma>
155 Eigen::Matrix<return_type_t<T_x1, T_x2, T_sigma>, Eigen::Dynamic,
156 Eigen::Dynamic>
gp_dot_prod_cov(const std::vector<Eigen::Matrix<T_x1,Eigen::Dynamic,1>> & x1,const std::vector<Eigen::Matrix<T_x2,Eigen::Dynamic,1>> & x2,const T_sigma & sigma)157 gp_dot_prod_cov(const std::vector<Eigen::Matrix<T_x1, Eigen::Dynamic, 1>> &x1,
158 const std::vector<Eigen::Matrix<T_x2, Eigen::Dynamic, 1>> &x2,
159 const T_sigma &sigma) {
160 check_nonnegative("gp_dot_prod_cov", "sigma", sigma);
161 check_finite("gp_dot_prod_cov", "sigma", sigma);
162
163 size_t x1_size = x1.size();
164 size_t x2_size = x2.size();
165 for (size_t i = 0; i < x1_size; ++i) {
166 check_finite("gp_dot_prod_cov", "x1", x1[i]);
167 }
168 for (size_t i = 0; i < x2_size; ++i) {
169 check_finite("gp_dot_prod_cov", "x2", x2[i]);
170 }
171 Eigen::Matrix<return_type_t<T_x1, T_x2, T_sigma>, Eigen::Dynamic,
172 Eigen::Dynamic>
173 cov(x1_size, x2_size);
174
175 if (x1_size == 0 || x2_size == 0) {
176 return cov;
177 }
178
179 T_sigma sigma_sq = square(sigma);
180 size_t block_size = 10;
181
182 for (size_t ib = 0; ib < x1_size; ib += block_size) {
183 for (size_t jb = 0; jb < x2_size; jb += block_size) {
184 size_t j_end = std::min(x2_size, jb + block_size);
185 for (size_t j = jb; j < j_end; ++j) {
186 size_t i_end = std::min(x1_size, ib + block_size);
187 for (size_t i = ib; i < i_end; ++i) {
188 cov(i, j) = sigma_sq + dot_product(x1[i], x2[j]);
189 }
190 }
191 }
192 }
193 return cov;
194 }
195
196 /**
197 * Returns a dot product covariance matrix of
198 * differing x's. A member of Stan's Gaussian Process Library.
199 *
200 * \f$k(x,x') = \sigma^2 + x \cdot x'\f$
201 *
202 * A dot product covariance matrix is the same covariance matrix
203 * as in bayesian regression with \f$N(0,1)\f$ priors on regression coefficients
204 * and a \f$N(0,\sigma^2)\f$ prior on the constant function. See Rasmussen and
205 * Williams et al 2006, Chapter 4.
206 *
207 * @tparam T_x1 type of first std::vector of double
208 * @tparam T_x2 type of second std::vector of double
209 * @tparam T_sigma type of sigma
210 *
211 * @param x1 std::vector of elements that can be used in dot_product
212 * @param x2 std::vector of elements that can be used in dot_product
213 * @param sigma is the constant function that can be used in stan::math::square
214 * @return dot product covariance matrix that is not always symmetric
215 * @throw std::domain_error if sigma < 0, nan or inf
216 * or if x1 or x2 are nan or inf
217 */
218 template <typename T_x1, typename T_x2, typename T_sigma>
219 Eigen::Matrix<return_type_t<T_x1, T_x2, T_sigma>, Eigen::Dynamic,
220 Eigen::Dynamic>
gp_dot_prod_cov(const std::vector<T_x1> & x1,const std::vector<T_x2> & x2,const T_sigma & sigma)221 gp_dot_prod_cov(const std::vector<T_x1> &x1, const std::vector<T_x2> &x2,
222 const T_sigma &sigma) {
223 check_nonnegative("gp_dot_prod_cov", "sigma", sigma);
224 check_finite("gp_dot_prod_cov", "sigma", sigma);
225
226 size_t x1_size = x1.size();
227 size_t x2_size = x2.size();
228 check_finite("gp_dot_prod_cov", "x1", x1);
229 check_finite("gp_dot_prod_cov", "x2", x2);
230
231 Eigen::Matrix<return_type_t<T_x1, T_x2, T_sigma>, Eigen::Dynamic,
232 Eigen::Dynamic>
233 cov(x1_size, x2_size);
234
235 if (x1_size == 0 || x2_size == 0) {
236 return cov;
237 }
238
239 T_sigma sigma_sq = square(sigma);
240
241 for (size_t i = 0; i < x1_size; ++i) {
242 for (size_t j = 0; j < x2_size; ++j) {
243 cov(i, j) = sigma_sq + x1[i] * x2[j];
244 }
245 }
246 return cov;
247 }
248
249 } // namespace math
250 } // namespace stan
251
252 #endif
253