typename boost::math::tools::promote_args<T_y, T_covar, T_w>::type multi_gp_cholesky_log(const Eigen::Matrix <T_y, Eigen::Dynamic, Eigen::Dynamic>& y, const Eigen::Matrix <T_covar, Eigen::Dynamic, Eigen::Dynamic>& L, const Eigen::Matrix<T_w, Eigen::Dynamic, 1>& w) { static const char* function("multi_gp_cholesky_log"); typedef typename boost::math::tools::promote_args<T_y, T_covar, T_w>::type T_lp; T_lp lp(0.0); check_size_match(function, "Size of random variable (rows y)", y.rows(), "Size of kernel scales (w)", w.size()); check_size_match(function, "Size of random variable", y.cols(), "rows of covariance parameter", L.rows()); check_finite(function, "Kernel scales", w); check_positive(function, "Kernel scales", w); check_finite(function, "Random variable", y); if (y.rows() == 0) return lp; if (include_summand<propto>::value) { lp += NEG_LOG_SQRT_TWO_PI * y.rows() * y.cols(); } if (include_summand<propto, T_covar>::value) { lp -= L.diagonal().array().log().sum() * y.rows(); } if (include_summand<propto, T_w>::value) { lp += 0.5 * y.cols() * sum(log(w)); } if (include_summand<propto, T_y, T_w, T_covar>::value) { T_lp sum_lp_vec(0.0); for (int i = 0; i < y.rows(); i++) { Eigen::Matrix<T_y, Eigen::Dynamic, 1> y_row(y.row(i)); Eigen::Matrix<typename boost::math::tools::promote_args <T_y, T_covar>::type, Eigen::Dynamic, 1> half(mdivide_left_tri_low(L, y_row)); sum_lp_vec += w(i) * dot_self(half); } lp -= 0.5*sum_lp_vec; } return lp; }
typename boost::math::tools::promote_args<T_y, T_covar, T_w>::type multi_gp_log(const Eigen::Matrix<T_y, Eigen::Dynamic, Eigen::Dynamic>& y, const Eigen::Matrix <T_covar, Eigen::Dynamic, Eigen::Dynamic>& Sigma, const Eigen::Matrix<T_w, Eigen::Dynamic, 1>& w) { static const char* function("multi_gp_log"); typedef typename boost::math::tools::promote_args<T_y, T_covar, T_w>::type T_lp; T_lp lp(0.0); check_positive(function, "Kernel rows", Sigma.rows()); check_finite(function, "Kernel", Sigma); check_symmetric(function, "Kernel", Sigma); LDLT_factor<T_covar, Eigen::Dynamic, Eigen::Dynamic> ldlt_Sigma(Sigma); check_ldlt_factor(function, "LDLT_Factor of Sigma", ldlt_Sigma); check_size_match(function, "Size of random variable (rows y)", y.rows(), "Size of kernel scales (w)", w.size()); check_size_match(function, "Size of random variable", y.cols(), "rows of covariance parameter", Sigma.rows()); check_positive_finite(function, "Kernel scales", w); check_finite(function, "Random variable", y); if (y.rows() == 0) return lp; if (include_summand<propto>::value) { lp += NEG_LOG_SQRT_TWO_PI * y.rows() * y.cols(); } if (include_summand<propto, T_covar>::value) { lp -= 0.5 * log_determinant_ldlt(ldlt_Sigma) * y.rows(); } if (include_summand<propto, T_w>::value) { lp += (0.5 * y.cols()) * sum(log(w)); } if (include_summand<propto, T_y, T_w, T_covar>::value) { Eigen::Matrix<T_w, Eigen::Dynamic, Eigen::Dynamic> w_mat(w.asDiagonal()); Eigen::Matrix<T_y, Eigen::Dynamic, Eigen::Dynamic> yT(y.transpose()); lp -= 0.5 * trace_gen_inv_quad_form_ldlt(w_mat, ldlt_Sigma, yT); } return lp; }
inline bool check_corr_matrix(const char* function, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y, const char* name, T_result* result, const Policy&) { if (!check_size_match(function, y.rows(), "Rows of correlation matrix", y.cols(), "columns of correlation matrix", result, Policy())) return false; if (!check_positive(function, y.rows(), "rows", result, Policy())) return false; if (!check_symmetric(function, y, "y", result, Policy())) return false; for (typename Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>::size_type k = 0; k < y.rows(); ++k) { if (fabs(y(k,k) - 1.0) > CONSTRAINT_TOLERANCE) { std::ostringstream message; message << name << " is not a valid correlation matrix. " << name << "(" << k << "," << k << ") is %1%, but should be near 1.0"; T_result tmp = policies::raise_domain_error<T_y>(function, message.str().c_str(), y(k,k), Policy()); if (result != 0) *result = tmp; return false; } } if (!check_pos_definite(function, y, "y", result, Policy())) return false; return true; }
inline bool check_square(const char* function, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y, const char* name, T_result* result) { check_size_match(function, y.rows(), "Rows of matrix", y.cols(), "columns of matrix", result); return true; }
inline bool check_matching_sizes(const char* function, const char* name1, const T_y1& y1, const char* name2, const T_y2& y2) { check_size_match(function, "size of ", name1, y1.size(), "size of ", name2, y2.size()); return true; }
inline bool check_cov_matrix(const std::string& function, const std::string& name, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y) { check_size_match(function, "Rows of covariance matrix", y.rows(), "columns of covariance matrix", y.cols()); check_positive(function, "rows", y.rows()); check_symmetric(function, name, y); check_pos_definite(function, name, y); return true; }
inline Eigen::Matrix<typename boost::math::tools::promote_args<T1, T2>::type, Eigen::Dynamic, 1> csr_matrix_times_vector(const int& m, const int& n, const Eigen::Matrix<T1, Eigen::Dynamic, 1>& w, const std::vector<int>& v, const std::vector<int>& u, const Eigen::Matrix<T2, Eigen::Dynamic, 1>& b) { typedef typename boost::math::tools::promote_args<T1, T2>::type result_t; check_positive("csr_matrix_times_vector", "m", m); check_positive("csr_matrix_times_vector", "n", n); check_size_match("csr_matrix_times_vector", "n", n, "b", b.size()); check_size_match("csr_matrix_times_vector", "m", m, "u", u.size() - 1); check_size_match("csr_matrix_times_vector", "w", w.size(), "v", v.size()); check_size_match("csr_matrix_times_vector", "u/z", u[m - 1] + csr_u_to_z(u, m - 1) - 1, "v", v.size()); for (unsigned int i = 0; i < v.size(); ++i) check_range("csr_matrix_times_vector", "v[]", n, v[i]); Eigen::Matrix<result_t, Eigen::Dynamic, 1> result(m); result.setZero(); for (int row = 0; row < m; ++row) { int idx = csr_u_to_z(u, row); int row_end_in_w = (u[row] - stan::error_index::value) + idx; int i = 0; // index into dot-product segment entries. Eigen::Matrix<result_t, Eigen::Dynamic, 1> b_sub(idx); b_sub.setZero(); for (int nze = u[row] - stan::error_index::value; nze < row_end_in_w; ++nze, ++i) { check_range("csr_matrix_times_vector", "j", n, v[nze]); b_sub.coeffRef(i) = b.coeffRef(v[nze] - stan::error_index::value); } // loop skipped when z is zero. Eigen::Matrix<T1, Eigen::Dynamic, 1> w_sub(w.segment(u[row] - stan::error_index::value, idx)); result.coeffRef(row) = dot_product(w_sub, b_sub); } return result; }
inline bool check_multiplicable(const char* function, const char* name1, const T1& y1, const char* name2, const T2& y2) { check_positive_size(function, name1, "rows()", y1.rows()); check_positive_size(function, name2, "cols()", y2.cols()); check_size_match(function, "Columns of ", name1, y1.cols(), "Rows of ", name2, y2.rows()); check_positive_size(function, name1, "cols()", y1.cols()); return true; }
inline bool check_cov_matrix(const char* function, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y, const char* name, T_result* result) { check_size_match(function, y.rows(), "Rows of covariance matrix", y.cols(), "columns of covariance matrix", result); check_positive(function, y.rows(), "rows", result); check_symmetric(function, y, name, result); check_pos_definite(function, y, name, result); return true; }
typename return_type<T_y, T_loc, T_covar>::type multi_normal_cholesky_log(const T_y& y, const T_loc& mu, const T_covar& L) { static const char* function("multi_normal_cholesky_log"); typedef typename scalar_type<T_covar>::type T_covar_elem; typedef typename return_type<T_y, T_loc, T_covar>::type lp_type; lp_type lp(0.0); VectorViewMvt<const T_y> y_vec(y); VectorViewMvt<const T_loc> mu_vec(mu); size_t size_vec = max_size_mvt(y, mu); int size_y = y_vec[0].size(); int size_mu = mu_vec[0].size(); if (size_vec > 1) { int size_y_old = size_y; int size_y_new; for (size_t i = 1, size_ = length_mvt(y); i < size_; i++) { int size_y_new = y_vec[i].size(); check_size_match(function, "Size of one of the vectors of " "the random variable", size_y_new, "Size of another vector of the " "random variable", size_y_old); size_y_old = size_y_new; } int size_mu_old = size_mu; int size_mu_new; for (size_t i = 1, size_ = length_mvt(mu); i < size_; i++) { int size_mu_new = mu_vec[i].size(); check_size_match(function, "Size of one of the vectors of " "the location variable", size_mu_new, "Size of another vector of the " "location variable", size_mu_old); size_mu_old = size_mu_new; } (void) size_y_old; (void) size_y_new; (void) size_mu_old; (void) size_mu_new; } check_size_match(function, "Size of random variable", size_y, "size of location parameter", size_mu); check_size_match(function, "Size of random variable", size_y, "rows of covariance parameter", L.rows()); check_size_match(function, "Size of random variable", size_y, "columns of covariance parameter", L.cols()); for (size_t i = 0; i < size_vec; i++) { check_finite(function, "Location parameter", mu_vec[i]); check_not_nan(function, "Random variable", y_vec[i]); } if (size_y == 0) return lp; if (include_summand<propto>::value) lp += NEG_LOG_SQRT_TWO_PI * size_y * size_vec; if (include_summand<propto, T_covar_elem>::value) lp -= L.diagonal().array().log().sum() * size_vec; if (include_summand<propto, T_y, T_loc, T_covar_elem>::value) { lp_type sum_lp_vec(0.0); for (size_t i = 0; i < size_vec; i++) { Eigen::Matrix<typename return_type<T_y, T_loc>::type, Eigen::Dynamic, 1> y_minus_mu(size_y); for (int j = 0; j < size_y; j++) y_minus_mu(j) = y_vec[i](j)-mu_vec[i](j); Eigen::Matrix<typename return_type<T_y, T_loc, T_covar>::type, Eigen::Dynamic, 1> half(mdivide_left_tri_low(L, y_minus_mu)); // FIXME: this code does not compile. revert after fixing subtract() // Eigen::Matrix<typename // boost::math::tools::promote_args<T_covar, // typename value_type<T_loc>::type, // typename value_type<T_y>::type>::type>::type, // Eigen::Dynamic, 1> // half(mdivide_left_tri_low(L, subtract(y, mu))); sum_lp_vec += dot_self(half); } lp -= 0.5*sum_lp_vec; } return lp; }