diff --git a/src/stan/analyze/mcmc/autocovariance.hpp b/src/stan/analyze/mcmc/autocovariance.hpp index ae360141d4..36130732dc 100644 --- a/src/stan/analyze/mcmc/autocovariance.hpp +++ b/src/stan/analyze/mcmc/autocovariance.hpp @@ -1,7 +1,7 @@ #ifndef STAN_ANALYZE_MCMC_AUTOCOVARIANCE_HPP #define STAN_ANALYZE_MCMC_AUTOCOVARIANCE_HPP -#include +#include #include #include #include diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index d4987ebbb5..22ff44c2eb 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -1,7 +1,7 @@ #ifndef STAN_ANALYZE_MCMC_COMPUTE_POTENTIAL_SCALE_REDUCTION_HPP #define STAN_ANALYZE_MCMC_COMPUTE_POTENTIAL_SCALE_REDUCTION_HPP -#include +#include #include #include #include diff --git a/src/stan/io/dump.hpp b/src/stan/io/dump.hpp index 81c0bf2805..99f7592afd 100644 --- a/src/stan/io/dump.hpp +++ b/src/stan/io/dump.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/io/reader.hpp b/src/stan/io/reader.hpp index c294509152..912f23e747 100644 --- a/src/stan/io/reader.hpp +++ b/src/stan/io/reader.hpp @@ -2,7 +2,7 @@ #define STAN_IO_READER_HPP #include -#include +#include #include #include #include diff --git a/src/stan/io/stan_csv_reader.hpp b/src/stan/io/stan_csv_reader.hpp index fb4a75ead2..454dbbadb0 100644 --- a/src/stan/io/stan_csv_reader.hpp +++ b/src/stan/io/stan_csv_reader.hpp @@ -2,7 +2,7 @@ #define STAN_IO_STAN_CSV_READER_HPP #include -#include +#include #include #include #include diff --git a/src/stan/io/writer.hpp b/src/stan/io/writer.hpp index 8f424d4b88..d534716bf6 100644 --- a/src/stan/io/writer.hpp +++ b/src/stan/io/writer.hpp @@ -1,7 +1,7 @@ #ifndef STAN_IO_WRITER_HPP #define STAN_IO_WRITER_HPP -#include +#include #include #include diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index a0c8e78972..c42e48f9fd 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -2,7 +2,7 @@ #define STAN_MCMC_CHAINS_HPP #include -#include +#include #include #include #include diff --git a/src/stan/mcmc/covar_adaptation.hpp b/src/stan/mcmc/covar_adaptation.hpp index 6c21c63e33..ef01301ccc 100644 --- a/src/stan/mcmc/covar_adaptation.hpp +++ b/src/stan/mcmc/covar_adaptation.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MCMC_COVAR_ADAPTATION_HPP #define STAN_MCMC_COVAR_ADAPTATION_HPP -#include +#include #include #include diff --git a/src/stan/mcmc/hmc/hamiltonians/auto_e_metric.hpp b/src/stan/mcmc/hmc/hamiltonians/auto_e_metric.hpp new file mode 100644 index 0000000000..a81699d7ce --- /dev/null +++ b/src/stan/mcmc/hmc/hamiltonians/auto_e_metric.hpp @@ -0,0 +1,76 @@ +#ifndef STAN_MCMC_HMC_HAMILTONIANS_AUTO_E_METRIC_HPP +#define STAN_MCMC_HMC_HAMILTONIANS_AUTO_E_METRIC_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace stan { + namespace mcmc { + + // Euclidean manifold with dense metric + template + class auto_e_metric + : public base_hamiltonian { + public: + explicit auto_e_metric(const Model& model) + : base_hamiltonian(model) {} + + double T(auto_e_point& z) { + return 0.5 * z.p.transpose() * z.inv_e_metric_ * z.p; + } + + double tau(auto_e_point& z) { + return T(z); + } + + double phi(auto_e_point& z) { + return this->V(z); + } + + double dG_dt(auto_e_point& z, callbacks::logger& logger) { + return 2 * T(z) - z.q.dot(z.g); + } + + Eigen::VectorXd dtau_dq(auto_e_point& z, callbacks::logger& logger) { + return Eigen::VectorXd::Zero(this->model_.num_params_r()); + } + + Eigen::VectorXd dtau_dp(auto_e_point& z) { + if(z.is_diagonal_) { + return z.inv_e_metric_.diagonal().cwiseProduct(z.p); + } else { + return z.inv_e_metric_ * z.p; + } + } + + Eigen::VectorXd dphi_dq(auto_e_point& z, callbacks::logger& logger) { + return z.g; + } + + void sample_p(auto_e_point& z, BaseRNG& rng) { + typedef typename stan::math::index_type::type idx_t; + boost::variate_generator > + rand_gaus(rng, boost::normal_distribution<>()); + + if(z.is_diagonal_) { + for (int i = 0; i < z.p.size(); ++i) + z.p(i) = rand_gaus() / sqrt(z.inv_e_metric_(i, i)); + } else { + Eigen::VectorXd u(z.p.size()); + + for (idx_t i = 0; i < u.size(); ++i) + u(i) = rand_gaus(); + + z.p = z.inv_e_metric_.llt().matrixU().solve(u); + } + } + }; + + } // mcmc +} // stan +#endif diff --git a/src/stan/mcmc/hmc/hamiltonians/auto_e_point.hpp b/src/stan/mcmc/hmc/hamiltonians/auto_e_point.hpp new file mode 100644 index 0000000000..d882f1a391 --- /dev/null +++ b/src/stan/mcmc/hmc/hamiltonians/auto_e_point.hpp @@ -0,0 +1,69 @@ +#ifndef STAN_MCMC_HMC_HAMILTONIANS_AUTO_E_POINT_HPP +#define STAN_MCMC_HMC_HAMILTONIANS_AUTO_E_POINT_HPP + +#include +#include + +namespace stan { + namespace mcmc { + /** + * Point in a phase space with a base + * Euclidean manifold with auto metric + */ + class auto_e_point: public ps_point { + public: + /** + * Inverse mass matrix. + */ + Eigen::MatrixXd inv_e_metric_; + + /** + * Is inv_e_metric_ diagonal or not + */ + bool is_diagonal_; + + /** + * Construct a auto point in n-dimensional phase space + * with identity matrix as inverse mass matrix. + * + * @param n number of dimensions + */ + explicit auto_e_point(int n) + : ps_point(n), inv_e_metric_(n, n), is_diagonal_(true) { + inv_e_metric_.setIdentity(); + } + + /** + * Set elements of mass matrix + * + * @param inv_e_metric initial mass matrix + */ + void + set_metric(const Eigen::MatrixXd& inv_e_metric) { + inv_e_metric_ = inv_e_metric; + is_diagonal_ = false; + } + + /** + * Write elements of mass matrix to string and handoff to writer. + * + * @param writer Stan writer callback + */ + inline + void + write_metric(stan::callbacks::writer& writer) { + writer("Elements of inverse mass matrix:"); + for (int i = 0; i < inv_e_metric_.rows(); ++i) { + std::stringstream inv_e_metric_ss; + inv_e_metric_ss << inv_e_metric_(i, 0); + for (int j = 1; j < inv_e_metric_.cols(); ++j) + inv_e_metric_ss << ", " << inv_e_metric_(i, j); + writer(inv_e_metric_ss.str()); + } + } + }; + + } // mcmc +} // stan + +#endif diff --git a/src/stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp b/src/stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp index 3f177b5a13..09de489815 100644 --- a/src/stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp +++ b/src/stan/mcmc/hmc/hamiltonians/dense_e_metric.hpp @@ -2,7 +2,7 @@ #define STAN_MCMC_HMC_HAMILTONIANS_DENSE_E_METRIC_HPP #include -#include +#include #include #include #include diff --git a/src/stan/mcmc/hmc/nuts/adapt_auto_e_nuts.hpp b/src/stan/mcmc/hmc/nuts/adapt_auto_e_nuts.hpp new file mode 100644 index 0000000000..c6deef4f4d --- /dev/null +++ b/src/stan/mcmc/hmc/nuts/adapt_auto_e_nuts.hpp @@ -0,0 +1,79 @@ +#ifndef STAN_MCMC_HMC_NUTS_ADAPT_AUTO_E_NUTS_HPP +#define STAN_MCMC_HMC_NUTS_ADAPT_AUTO_E_NUTS_HPP + +#include +#include +#include +#include + +namespace stan { +namespace mcmc { +/** + * The No-U-Turn sampler (NUTS) with multinomial sampling + * with a Gaussian-Euclidean disintegration and adaptive + * dense or diagonal metric and adaptive step size + */ +template +class adapt_auto_e_nuts : public auto_e_nuts, + public mpi_cross_chain_adapter>, + public stepsize_covar_adapter { +protected: + const Model& model_; +public: + adapt_auto_e_nuts(const Model& model, BaseRNG& rng) + : model_(model), auto_e_nuts(model, rng), + stepsize_covar_adapter(model.num_params_r()) {} + + ~adapt_auto_e_nuts() {} + + sample + transition(sample& init_sample, callbacks::logger& logger) { + sample s = auto_e_nuts::transition(init_sample, + logger); + + if (this->adapt_flag_) { + this->stepsize_adaptation_.learn_stepsize(this->nom_epsilon_, + s.accept_stat()); + + if (this -> use_cross_chain_adapt()) { + this -> add_cross_chain_sample(s.log_prob()); + bool update = this -> cross_chain_adaptation(logger); + if (this -> is_cross_chain_adapted()) { + update = false; + } + + if (update) { + this->z_.is_diagonal_ = reinterpret_cast *>(this->metric_adapt)->is_diagonal_; + + this->init_stepsize(logger); + + this->stepsize_adaptation_.set_mu(log(10 * this->nom_epsilon_)); + this->stepsize_adaptation_.restart(); + + this->set_cross_chain_stepsize(); + } + } else { + bool update = this->covar_adaptation_.learn_covariance(this->z_.inv_e_metric_, + this->z_.q); + if (update) { + this->init_stepsize(logger); + + this->stepsize_adaptation_.set_mu(log(10 * this->nom_epsilon_)); + this->stepsize_adaptation_.restart(); + } + } + } + return s; + } + + void disengage_adaptation() { + base_adapter::disengage_adaptation(); + if (!this -> is_cross_chain_adapted()) { + this->stepsize_adaptation_.complete_adaptation(this->nom_epsilon_); + } + } +}; + +} // mcmc +} // stan +#endif diff --git a/src/stan/mcmc/hmc/nuts/adapt_diag_e_nuts.hpp b/src/stan/mcmc/hmc/nuts/adapt_diag_e_nuts.hpp index e3ae02e905..4369910700 100644 --- a/src/stan/mcmc/hmc/nuts/adapt_diag_e_nuts.hpp +++ b/src/stan/mcmc/hmc/nuts/adapt_diag_e_nuts.hpp @@ -30,7 +30,6 @@ class adapt_diag_e_nuts : public diag_e_nuts, if (this->adapt_flag_) { this->stepsize_adaptation_.learn_stepsize(this->nom_epsilon_, s.accept_stat()); - if (this -> use_cross_chain_adapt()) { this -> add_cross_chain_sample(s.log_prob()); diff --git a/src/stan/mcmc/hmc/nuts/auto_e_nuts.hpp b/src/stan/mcmc/hmc/nuts/auto_e_nuts.hpp new file mode 100644 index 0000000000..4ed11dff61 --- /dev/null +++ b/src/stan/mcmc/hmc/nuts/auto_e_nuts.hpp @@ -0,0 +1,26 @@ +#ifndef STAN_MCMC_HMC_NUTS_AUTO_E_NUTS_HPP +#define STAN_MCMC_HMC_NUTS_AUTO_E_NUTS_HPP + +#include +#include +#include +#include + +namespace stan { + namespace mcmc { + /** + * The No-U-Turn sampler (NUTS) with multinomial sampling + * with a Gaussian-Euclidean disintegration and dense metric + */ + template + class auto_e_nuts : public base_nuts { + public: + auto_e_nuts(const Model& model, BaseRNG& rng) + : base_nuts(model, rng) { } + }; + + } // mcmc +} // stan +#endif diff --git a/src/stan/mcmc/hmc/nuts/base_nuts.hpp b/src/stan/mcmc/hmc/nuts/base_nuts.hpp index 7b08ff8ce5..b8912e69f7 100644 --- a/src/stan/mcmc/hmc/nuts/base_nuts.hpp +++ b/src/stan/mcmc/hmc/nuts/base_nuts.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/mcmc/mpi_auto_adaptation.hpp b/src/stan/mcmc/mpi_auto_adaptation.hpp new file mode 100644 index 0000000000..76d5b06624 --- /dev/null +++ b/src/stan/mcmc/mpi_auto_adaptation.hpp @@ -0,0 +1,328 @@ +#ifndef STAN_MCMC_MPI_AUTO_ADAPTATION_HPP +#define STAN_MCMC_MPI_AUTO_ADAPTATION_HPP + +#include +#include +#include + +namespace stan { + +namespace mcmc { + template + struct log_prob_wrapper_covar { + const Model& model_; + log_prob_wrapper_covar(const Model& model) : model_(model) {} + + template + T operator()(const Eigen::Matrix& q) const { + return model_.template log_prob(const_cast& >(q), &std::cout); + } + }; + + namespace internal { + /** + * Compute the covariance of data in Y. + * + * Columns of Y are different variables. Rows are different samples. + * + * When there is only one row in Y, return a covariance matrix of the expected + * size filled with zeros. + * + * @param Y Data + * @return Covariance of Y + */ + Eigen::MatrixXd covariance(const Eigen::MatrixXd& Y) { + stan::math::check_nonzero_size("covariance", "Y", Y); + + Eigen::MatrixXd centered = Y.rowwise() - Y.colwise().mean(); + return centered.transpose() * centered / std::max(centered.rows() - 1.0, 1.0); + } + + /** + * Compute the largest magnitude eigenvalue of a symmetric matrix using the power method. The function f + * should return the product of that matrix with an abitrary vector. + * + * f should take one Eigen::VectorXd argument, x, and return the product of a matrix with x as + * an Eigen::VectorXd argument of the same size. + * + * The eigenvalue is estimated iteratively. If the kth estimate is e_k, then the function returns when + * either abs(e_{k + 1} - e_k) < tol * abs(e_k) or the maximum number of iterations have been performed + * + * This means the returned eigenvalue might not be computed to full precision + * + * @param initial_guess Initial guess of the eigenvector of the largest eigenvalue + * @param[in,out] max_iterations Maximum number of power iterations, on return number of iterations used + * @param[in,out] tol Relative tolerance, on return the relative error in the eigenvalue estimate + * @return Largest magnitude eigenvalue of operator f + */ + template + double power_method(F& f, const Eigen::VectorXd& initial_guess, int& max_iterations, double& tol) { + Eigen::VectorXd v = initial_guess; + double eval = 0.0; + Eigen::VectorXd Av = f(v); + stan::math::check_matching_sizes("power_method", "matrix vector product", Av, "vector", v); + + int i = 0; + for(; i < max_iterations; ++i) { + double v_norm = v.norm(); + double new_eval = v.dot(Av) / (v_norm * v_norm); + if(i == max_iterations - 1 || std::abs(new_eval - eval) <= tol * std::abs(eval)) { + tol = std::abs(new_eval - eval) / std::abs(eval); + eval = new_eval; + max_iterations = i + 1; + break; + } + + eval = new_eval; + v = Av / Av.norm(); + + Av = f(v); + } + + return eval; + } + + /** + * Compute the largest eigenvalue of the sample covariance rescaled by a metric, + * that is, the largest eigenvalue of L^{-1} \Sigma L^{-T} + * + * @param L Cholesky decomposition of Metric + * @param Sigma Sample covariance + * @return Largest eigenvalue + */ + double eigenvalue_scaled_covariance(const Eigen::MatrixXd& L, const Eigen::MatrixXd& Sigma) { + Eigen::MatrixXd S = L.template triangularView(). + solve(L.template triangularView().solve(Sigma).transpose()).transpose(); + + auto Sx = [&](Eigen::VectorXd x) -> Eigen::VectorXd { + return S * x; + }; + + int max_iterations = 100; + double tol = 1e-3; + + return internal::power_method(Sx, Eigen::VectorXd::Random(Sigma.cols()), max_iterations, tol); + } + + /** + * Compute the largest eigenvalue of the Hessian of the log density rescaled by a metric, + * that is, the largest eigenvalue of L^T \nabla^2_{qq} H(q) L + * + * @tparam Model Type of model + * @param model Defines the log density + * @param q Point around which to compute the Hessian + * @param L Cholesky decomposition of Metric + * @return Largest eigenvalue + */ + template + double eigenvalue_scaled_hessian(const Model& model, const Eigen::MatrixXd& L, const Eigen::VectorXd& q) { + Eigen::VectorXd eigenvalues; + Eigen::MatrixXd eigenvectors; + + auto hessian_vector = [&](const Eigen::VectorXd& x) -> Eigen::VectorXd { + double lp; + Eigen::VectorXd grad1; + Eigen::VectorXd grad2; + //stan::math::hessian_times_vector(log_prob_wrapper_covar(model), q, x, lp, Ax); + double dx = 1e-5; + Eigen::VectorXd dr = L * x * dx; + stan::math::gradient(log_prob_wrapper_covar(model), q + dr / 2.0, lp, grad1); + stan::math::gradient(log_prob_wrapper_covar(model), q - dr / 2.0, lp, grad2); + return L.transpose() * (grad1 - grad2) / dx; + }; + + int max_iterations = 100; + double tol = 1e-3; + + return internal::power_method(hessian_vector, Eigen::VectorXd::Random(q.size()), max_iterations, tol); + } + } + +template +class mpi_auto_adaptation : public mpi_metric_adaptation { +#ifdef STAN_LANG_MPI + using est_t = stan::math::mpi::mpi_covar_estimator; + + int num_chains_; + int n_params_; + int window_size_; + int init_buffer_; + int init_draw_counter_; + int num_iterations_; + int draw_req_counter_; + int draws_collected_counter_; + Model& model_; + std::deque last_qs_; +public: + std::vector reqs; + std::vector draws; + std::vector num_draws; + Eigen::MatrixXd Y_; + bool is_diagonal_; + + mpi_auto_adaptation(Model& model, int n_params, int num_chains, + int num_iterations, int window_size, int init_buffer) + : num_chains_(num_chains), + window_size_(window_size), + init_buffer_(init_buffer), + init_draw_counter_(0), + draw_req_counter_(0), + draws_collected_counter_(0), + n_params_(n_params), + reqs(window_size), + num_iterations_(num_iterations), + model_(model), + draws(window_size, Eigen::MatrixXd(n_params, num_chains)), + Y_(num_chains * num_iterations, n_params), + is_diagonal_(false) { + std::cout << "numchains " << num_chains_ << + ", n_params " << n_params_ << + ", num_iter " << num_iterations_ << + ", window_size " << window_size_ << + ", init_buffer " << init_buffer_ << std::endl; + } + + void reset_req() { + draw_req_counter_ = 0; + reqs.clear(); + reqs.resize(window_size_); + } + + virtual void add_sample(const Eigen::VectorXd& q, int curr_win_count) { + const stan::math::mpi::Communicator& comm = + stan::math::mpi::Session::inter_chain_comm(num_chains_); + + MPI_Iallgather(q.data(), q.size(), MPI_DOUBLE, + draws[draw_req_counter_].data(), q.size(), MPI_DOUBLE, + comm.comm(), &reqs[draw_req_counter_]); + draw_req_counter_++; + + last_qs_.push_back(q); + if(last_qs_.size() > 5) { + last_qs_.pop_front(); + } + } + + virtual void learn_metric(Eigen::MatrixXd& covar, int win, int curr_win_count, + const stan::math::mpi::Communicator& comm) { + //std::cout << "win: " << win << ", current_win_count: " << curr_win_count << std::endl << std::flush; + collect_draws(win, comm); + + int first_draw = num_chains_ * (std::max(win - 1, 0) * window_size_ + (win > 0) * (window_size_ - init_buffer_)); + int num_draws = std::max(num_chains_ * draws_collected_counter_ - first_draw, 0); + //std::cout << "first_draw: " << first_draw << ", num_draws: " << num_draws << std::endl << std::flush; + + int M = n_params_; + + try { + bool use_dense = false; + for(auto state : { "selection", "refinement" }) { + Eigen::MatrixXd cov_train = Eigen::MatrixXd::Zero(M, M); + Eigen::MatrixXd cov_test = Eigen::MatrixXd::Zero(M, M); + + int Ntest; + if(state == "selection") { + Ntest = int(0.2 * num_draws); + if(Ntest < 5) { + Ntest = 5; + } + + if(num_draws < 10) { + throw std::runtime_error("Each warmup stage must have at least 10 samples"); + } + + Eigen::MatrixXd Ytrain = Y_.block(first_draw, 0, num_draws - Ntest, n_params_); + Eigen::MatrixXd Ytest = Y_.block(first_draw + num_draws - Ntest, 0, Ntest, n_params_); + cov_train = internal::covariance(Ytrain); + cov_test = internal::covariance(Ytest); + } else { + Ntest = 0; + Eigen::MatrixXd Ytrain = Y_.block(first_draw, 0, num_draws, n_params_); + cov_train = internal::covariance(Ytrain); + } + + Eigen::MatrixXd dense = ((num_draws - Ntest) / ((num_draws - Ntest) + 5.0)) * cov_train + + 1e-3 * (5.0 / ((num_draws - Ntest) + 5.0)) * Eigen::MatrixXd::Identity(cov_train.rows(), cov_train.cols()); + + Eigen::MatrixXd diag = dense.diagonal().asDiagonal(); + + covar = dense; + + if(state == "selection") { + Eigen::MatrixXd L_dense = dense.llt().matrixL(); + Eigen::MatrixXd L_diag = diag.diagonal().array().sqrt().matrix().asDiagonal(); + + double low_eigenvalue_dense = -1.0 / internal::eigenvalue_scaled_covariance(L_dense, cov_test); + double low_eigenvalue_diag = -1.0 / internal::eigenvalue_scaled_covariance(L_diag, cov_test); + + double c_dense = 0.0; + double c_diag = 0.0; + for(int i = 0; i < last_qs_.size(); i++) { + double high_eigenvalue_dense = internal::eigenvalue_scaled_hessian(model_, L_dense, last_qs_[i]); + double high_eigenvalue_diag = internal::eigenvalue_scaled_hessian(model_, L_diag, last_qs_[i]); + + c_dense = std::max(c_dense, std::sqrt(high_eigenvalue_dense / low_eigenvalue_dense)); + c_diag = std::max(c_diag, std::sqrt(high_eigenvalue_diag / low_eigenvalue_diag)); + } + + std::cout << "adapt dense, max: " << c_dense << std::endl; + std::cout << "adapt diag, max: " << c_diag << std::endl; + + if(c_dense < c_diag) { + use_dense = true; + } else { + use_dense = false; + } + } else { + if(use_dense) { + covar = dense; + is_diagonal_ = false; + } else { + covar = diag; + is_diagonal_ = true; + } + } + } + } catch(const std::exception& e) { + std::cout << e.what() << std::endl; + std::cout << "Exception while using auto adaptation, falling back to diagonal" << std::endl; + Eigen::MatrixXd cov = Eigen::MatrixXd::Zero(M, M); + covar = ((num_draws / (num_draws + 5.0)) * cov.diagonal() + + 1e-3 * (5.0 / (num_draws + 5.0)) * Eigen::VectorXd::Ones(cov.cols())).asDiagonal(); + is_diagonal_ = true; + } + } + + void collect_draws(int win, const stan::math::mpi::Communicator& comm) { + int finished = 0; + int index; + int flag = 0; + + while(finished < draw_req_counter_) { + MPI_Testany(draw_req_counter_, reqs.data(), &index, &flag, MPI_STATUS_IGNORE); + if (flag) { + finished++; + for (int chain = 0; chain < num_chains_; ++chain) { + Eigen::RowVectorXd draw = draws[index].col(chain).transpose(); + Y_.block((draws_collected_counter_ + index) * num_chains_ + chain, 0, 1, n_params_) = draw; + } + } + } + + draws_collected_counter_ += draw_req_counter_; + + reset_req(); + } + + virtual void restart() { + } +#else +public: + mpi_auto_adaptation(int n_params, int num_iterations, int window_size) {} +#endif +}; + +} // namespace mcmc +} // namespace stan + +#endif diff --git a/src/stan/mcmc/mpi_covar_adaptation.hpp b/src/stan/mcmc/mpi_covar_adaptation.hpp index 8733a361ed..aa1e4a6465 100644 --- a/src/stan/mcmc/mpi_covar_adaptation.hpp +++ b/src/stan/mcmc/mpi_covar_adaptation.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MCMC_MPI_COVAR_ADAPTATION_HPP #define STAN_MCMC_MPI_COVAR_ADAPTATION_HPP +#include #include #include @@ -12,7 +13,7 @@ namespace stan { namespace mcmc { - class mpi_covar_adaptation : public mpi_metric_adaptation { +class mpi_covar_adaptation : public mpi_metric_adaptation { #ifdef STAN_LANG_MPI // using est_t = stan::math::mpi::mpi_covar_estimator; using est_t = stan::math::welford_covar_estimator; @@ -36,23 +37,23 @@ namespace mcmc { num_draws(num_iterations / window_size, 0) {} - void reset_req() { - draw_req_counter_ = 0; - reqs.clear(); - reqs.resize(window_size_); - } + void reset_req() { + draw_req_counter_ = 0; + reqs.clear(); + reqs.resize(window_size_); + } - virtual void add_sample(const Eigen::VectorXd& q, int curr_win_count) { - const stan::math::mpi::Communicator& comm = - stan::math::mpi::Session::inter_chain_comm(num_chains_); - MPI_Iallgather(q.data(), q.size(), MPI_DOUBLE, - draws[draw_req_counter_].data(), q.size(), MPI_DOUBLE, - comm.comm(), &reqs[draw_req_counter_]); - draw_req_counter_++; - for (int win = 0; win < curr_win_count; ++win) { - num_draws[win]++; - } + virtual void add_sample(const Eigen::VectorXd& q, int curr_win_count) { + const stan::math::mpi::Communicator& comm = + stan::math::mpi::Session::inter_chain_comm(num_chains_); + MPI_Iallgather(q.data(), q.size(), MPI_DOUBLE, + draws[draw_req_counter_].data(), q.size(), MPI_DOUBLE, + comm.comm(), &reqs[draw_req_counter_]); + draw_req_counter_++; + for (int win = 0; win < curr_win_count; ++win) { + num_draws[win]++; } + } virtual void learn_metric(Eigen::MatrixXd& covar, int win, int curr_win_count, const stan::math::mpi::Communicator& comm) { diff --git a/src/stan/mcmc/mpi_metric_adaptation.hpp b/src/stan/mcmc/mpi_metric_adaptation.hpp index f7eb3e7662..f2b5160373 100644 --- a/src/stan/mcmc/mpi_metric_adaptation.hpp +++ b/src/stan/mcmc/mpi_metric_adaptation.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MCMC_MPI_METRIC_ADAPTATION_HPP #define STAN_MCMC_MPI_METRIC_ADAPTATION_HPP +#include #include #ifdef STAN_LANG_MPI diff --git a/src/stan/mcmc/mpi_var_adaptation.hpp b/src/stan/mcmc/mpi_var_adaptation.hpp index dc767d14f1..33a6f21436 100644 --- a/src/stan/mcmc/mpi_var_adaptation.hpp +++ b/src/stan/mcmc/mpi_var_adaptation.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MCMC_MPI_VAR_ADAPTATION_HPP #define STAN_MCMC_MPI_VAR_ADAPTATION_HPP +#include #include #include diff --git a/src/stan/mcmc/var_adaptation.hpp b/src/stan/mcmc/var_adaptation.hpp index c81de41d98..c9ca255bad 100644 --- a/src/stan/mcmc/var_adaptation.hpp +++ b/src/stan/mcmc/var_adaptation.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MCMC_VAR_ADAPTATION_HPP #define STAN_MCMC_VAR_ADAPTATION_HPP -#include +#include #include #include diff --git a/src/stan/model/gradient.hpp b/src/stan/model/gradient.hpp index 12a3f318a3..be7cf47f9b 100644 --- a/src/stan/model/gradient.hpp +++ b/src/stan/model/gradient.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/model/indexing/lvalue.hpp b/src/stan/model/indexing/lvalue.hpp index d0d8ea46a9..30c4a0eecf 100644 --- a/src/stan/model/indexing/lvalue.hpp +++ b/src/stan/model/indexing/lvalue.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 90c20d5835..9f7e65e953 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/model/log_prob_grad.hpp b/src/stan/model/log_prob_grad.hpp index ee02eb7b7b..6e5eb11771 100644 --- a/src/stan/model/log_prob_grad.hpp +++ b/src/stan/model/log_prob_grad.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MODEL_LOG_PROB_GRAD_HPP #define STAN_MODEL_LOG_PROB_GRAD_HPP -#include +#include #include #include diff --git a/src/stan/model/log_prob_propto.hpp b/src/stan/model/log_prob_propto.hpp index 96e71a9619..bde538d15d 100644 --- a/src/stan/model/log_prob_propto.hpp +++ b/src/stan/model/log_prob_propto.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MODEL_LOG_PROB_PROPTO_HPP #define STAN_MODEL_LOG_PROB_PROPTO_HPP -#include +#include #include #include diff --git a/src/stan/optimization/bfgs.hpp b/src/stan/optimization/bfgs.hpp index 7e8a7bd40c..beee8ecb64 100644 --- a/src/stan/optimization/bfgs.hpp +++ b/src/stan/optimization/bfgs.hpp @@ -1,7 +1,7 @@ #ifndef STAN_OPTIMIZATION_BFGS_HPP #define STAN_OPTIMIZATION_BFGS_HPP -#include +#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_auto_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_auto_e_adapt.hpp new file mode 100644 index 0000000000..30d32f6dde --- /dev/null +++ b/src/stan/services/sample/hmc_nuts_auto_e_adapt.hpp @@ -0,0 +1,197 @@ +#ifndef STAN_SERVICES_SAMPLE_HMC_NUTS_AUTO_E_ADAPT_HPP +#define STAN_SERVICES_SAMPLE_HMC_NUTS_AUTO_E_ADAPT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace stan { + namespace services { + namespace sample { + + /** + * Runs HMC with NUTS with adaptation using dense Euclidean metric + * with a pre-specified Euclidean metric. + * + * @tparam Model Model class + * @param[in] model Input model to test (with data already instantiated) + * @param[in] init var context for initialization + * @param[in] init_inv_metric var context exposing an initial dense + inverse Euclidean metric (must be positive definite) + * @param[in] random_seed random seed for the random number generator + * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_radius radius to initialize + * @param[in] num_warmup Number of warmup samples + * @param[in] num_samples Number of samples + * @param[in] num_thin Number to thin the samples + * @param[in] save_warmup Indicates whether to save the warmup iterations + * @param[in] refresh Controls the output + * @param[in] stepsize initial stepsize for discrete evolution + * @param[in] stepsize_jitter uniform random jitter of stepsize + * @param[in] max_depth Maximum tree depth + * @param[in] delta adaptation target acceptance statistic + * @param[in] gamma adaptation regularization scale + * @param[in] kappa adaptation relaxation exponent + * @param[in] t0 adaptation iteration offset + * @param[in] init_buffer width of initial fast adaptation interval + * @param[in] term_buffer width of final fast adaptation interval + * @param[in] window initial width of slow adaptation interval + * @param[in,out] interrupt Callback for interrupts + * @param[in,out] logger Logger for messages + * @param[in,out] init_writer Writer callback for unconstrained inits + * @param[in,out] sample_writer Writer for draws + * @param[in,out] diagnostic_writer Writer for diagnostic information + * @return error_codes::OK if successful + */ + template + int hmc_nuts_auto_e_adapt(Model& model, stan::io::var_context& init, + stan::io::var_context& init_inv_metric, + unsigned int random_seed, unsigned int chain, + double init_radius, + int num_cross_chains, int cross_chain_window, double cross_chain_rhat, int cross_chain_ess, + int num_warmup, + int num_samples, int num_thin, + bool save_warmup, int refresh, double stepsize, + double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, + double t0, unsigned int init_buffer, + unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, + callbacks::logger& logger, + callbacks::writer& init_writer, + callbacks::writer& sample_writer, + callbacks::writer& diagnostic_writer) { + boost::ecuyer1988 rng = util::create_rng(random_seed, chain); + + std::vector disc_vector; + std::vector cont_vector + = util::initialize(model, init, rng, init_radius, true, + logger, init_writer); + + Eigen::MatrixXd inv_metric; + try { + inv_metric = + util::read_dense_inv_metric(init_inv_metric, model.num_params_r(), + logger); + util::validate_dense_inv_metric(inv_metric, logger); + } catch (const std::domain_error& e) { + return error_codes::CONFIG; + } + + stan::mcmc::adapt_auto_e_nuts + sampler(model, rng); + + sampler.set_metric(inv_metric); + + sampler.set_nominal_stepsize(stepsize); + sampler.set_stepsize_jitter(stepsize_jitter); + sampler.set_max_depth(max_depth); + + sampler.get_stepsize_adaptation().set_mu(log(10 * stepsize)); + sampler.get_stepsize_adaptation().set_delta(delta); + sampler.get_stepsize_adaptation().set_gamma(gamma); + sampler.get_stepsize_adaptation().set_kappa(kappa); + sampler.get_stepsize_adaptation().set_t0(t0); + + sampler.set_window_params(num_warmup, init_buffer, term_buffer, + window, logger); + + // cross chain adaptation + sampler.set_cross_chain_adaptation_params(num_warmup, init_buffer, term_buffer, + cross_chain_window, num_cross_chains, + cross_chain_rhat, cross_chain_ess); + std::cout << "num warmup: " << num_warmup << std::endl; + std::cout << "cross chain window: " << cross_chain_window << std::endl; + mcmc::mpi_auto_adaptation var_adapt(model, model.num_params_r(), + num_cross_chains, num_warmup, + cross_chain_window, init_buffer); + sampler.set_cross_chain_metric_adaptation(&var_adapt); + + util::run_adaptive_sampler(sampler, model, cont_vector, num_warmup, + num_samples, num_thin, refresh, save_warmup, + rng, interrupt, logger, + sample_writer, diagnostic_writer); + + return error_codes::OK; + } + + /** + * Runs HMC with NUTS with adaptation using dense Euclidean metric, + * with identity matrix as initial inv_metric. + * + * @tparam Model Model class + * @param[in] model Input model to test (with data already instantiated) + * @param[in] init var context for initialization + * @param[in] random_seed random seed for the random number generator + * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_radius radius to initialize + * @param[in] num_warmup Number of warmup samples + * @param[in] num_samples Number of samples + * @param[in] num_thin Number to thin the samples + * @param[in] save_warmup Indicates whether to save the warmup iterations + * @param[in] refresh Controls the output + * @param[in] stepsize initial stepsize for discrete evolution + * @param[in] stepsize_jitter uniform random jitter of stepsize + * @param[in] max_depth Maximum tree depth + * @param[in] delta adaptation target acceptance statistic + * @param[in] gamma adaptation regularization scale + * @param[in] kappa adaptation relaxation exponent + * @param[in] t0 adaptation iteration offset + * @param[in] init_buffer width of initial fast adaptation interval + * @param[in] term_buffer width of final fast adaptation interval + * @param[in] window initial width of slow adaptation interval + * @param[in,out] interrupt Callback for interrupts + * @param[in,out] logger Logger for messages + * @param[in,out] init_writer Writer callback for unconstrained inits + * @param[in,out] sample_writer Writer for draws + * @param[in,out] diagnostic_writer Writer for diagnostic information + * @return error_codes::OK if successful + */ + template + int hmc_nuts_auto_e_adapt(Model& model, stan::io::var_context& init, + unsigned int random_seed, unsigned int chain, + double init_radius, + int num_cross_chains, int cross_chain_window, double cross_chain_rhat, int cross_chain_ess, + int num_warmup, + int num_samples, int num_thin, + bool save_warmup, int refresh, double stepsize, + double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, + double t0, unsigned int init_buffer, + unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, + callbacks::logger& logger, + callbacks::writer& init_writer, + callbacks::writer& sample_writer, + callbacks::writer& diagnostic_writer) { + stan::io::dump dmp = + util::create_unit_e_dense_inv_metric(model.num_params_r()); + stan::io::var_context& unit_e_metric = dmp; + + return hmc_nuts_auto_e_adapt(model, init, unit_e_metric, + random_seed, chain, init_radius, + num_cross_chains, cross_chain_window, cross_chain_rhat, cross_chain_ess, + num_warmup, num_samples, num_thin, + save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, + init_buffer, term_buffer, window, + interrupt, logger, + init_writer, sample_writer, + diagnostic_writer); + } + + } + } +} +#endif diff --git a/src/stan/services/sample/hmc_nuts_dense_e.hpp b/src/stan/services/sample/hmc_nuts_dense_e.hpp index f57466503d..93d23b5dbe 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index ac93aec165..6c34b65a45 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -1,7 +1,7 @@ #ifndef STAN_SERVICES_SAMPLE_HMC_NUTS_DENSE_E_ADAPT_HPP #define STAN_SERVICES_SAMPLE_HMC_NUTS_DENSE_E_ADAPT_HPP -#include +#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_diag_e.hpp b/src/stan/services/sample/hmc_nuts_diag_e.hpp index 3932a870db..5630a042af 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e.hpp @@ -1,7 +1,7 @@ #ifndef STAN_SERVICES_SAMPLE_HMC_NUTS_DIAG_E_HPP #define STAN_SERVICES_SAMPLE_HMC_NUTS_DIAG_E_HPP -#include +#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index f58f7c5845..26ba0aca3e 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -1,7 +1,7 @@ #ifndef STAN_SERVICES_SAMPLE_HMC_NUTS_DIAG_E_ADAPT_HPP #define STAN_SERVICES_SAMPLE_HMC_NUTS_DIAG_E_ADAPT_HPP -#include +#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_unit_e.hpp b/src/stan/services/sample/hmc_nuts_unit_e.hpp index e3e6cf1cc2..5f4127a7df 100644 --- a/src/stan/services/sample/hmc_nuts_unit_e.hpp +++ b/src/stan/services/sample/hmc_nuts_unit_e.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_nuts_unit_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_unit_e_adapt.hpp index 4c3ecc3ba2..bccead5088 100644 --- a/src/stan/services/sample/hmc_nuts_unit_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_unit_e_adapt.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_static_dense_e.hpp b/src/stan/services/sample/hmc_static_dense_e.hpp index 5ddb3d224e..f9382fb5ee 100644 --- a/src/stan/services/sample/hmc_static_dense_e.hpp +++ b/src/stan/services/sample/hmc_static_dense_e.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_static_dense_e_adapt.hpp b/src/stan/services/sample/hmc_static_dense_e_adapt.hpp index 979e5ded1b..26b3d1d2b6 100644 --- a/src/stan/services/sample/hmc_static_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_static_dense_e_adapt.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_static_diag_e.hpp b/src/stan/services/sample/hmc_static_diag_e.hpp index 57109395f5..72f78bcf75 100644 --- a/src/stan/services/sample/hmc_static_diag_e.hpp +++ b/src/stan/services/sample/hmc_static_diag_e.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/stan/services/sample/hmc_static_diag_e_adapt.hpp b/src/stan/services/sample/hmc_static_diag_e_adapt.hpp index f374f205c6..1d24f72291 100644 --- a/src/stan/services/sample/hmc_static_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_static_diag_e_adapt.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index a1ccb19214..f9747b5e4a 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/stan/services/util/mpi_cross_chain.hpp b/src/stan/services/util/mpi_cross_chain.hpp index 0a7a4ca640..86b693b69b 100644 --- a/src/stan/services/util/mpi_cross_chain.hpp +++ b/src/stan/services/util/mpi_cross_chain.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #ifdef STAN_LANG_MPI @@ -38,6 +39,11 @@ namespace util { static const bool value = true; }; + template + struct has_cross_chain_warmup> { + static const bool value = true; + }; + /* * Helper functions for samplers with MPI WARMUP. Other * samplers have dummy implmenentation. @@ -119,9 +125,9 @@ namespace util { using stan::math::mpi::Session; using stan::math::mpi::Communicator; - if (Session::is_in_inter_chain_comm(num_chains)) { + if (file_name.size() > 0 && Session::is_in_inter_chain_comm(num_chains)) { const Communicator& comm = Session::inter_chain_comm(num_chains); - file_name = "mpi." + std::to_string(comm.rank()) + "." + file_name; + file_name = file_name + "." + "mpi." + std::to_string(comm.rank()); } #endif } diff --git a/src/stan/services/util/read_dense_inv_metric.hpp b/src/stan/services/util/read_dense_inv_metric.hpp index 11d2e77066..4597d0721d 100644 --- a/src/stan/services/util/read_dense_inv_metric.hpp +++ b/src/stan/services/util/read_dense_inv_metric.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/stan/services/util/validate_dense_inv_metric.hpp b/src/stan/services/util/validate_dense_inv_metric.hpp index ad75fc517a..c6d0188ff4 100644 --- a/src/stan/services/util/validate_dense_inv_metric.hpp +++ b/src/stan/services/util/validate_dense_inv_metric.hpp @@ -2,7 +2,7 @@ #define STAN_SERVICES_UTIL_VALIDATE_DENSE_INV_METRIC_HPP #include -#include +#include namespace stan { namespace services { diff --git a/src/stan/services/util/validate_diag_inv_metric.hpp b/src/stan/services/util/validate_diag_inv_metric.hpp index aa61247912..4f88bff95d 100644 --- a/src/stan/services/util/validate_diag_inv_metric.hpp +++ b/src/stan/services/util/validate_diag_inv_metric.hpp @@ -2,7 +2,7 @@ #define STAN_SERVICES_UTIL_VALIDATE_DIAG_INV_METRIC_HPP #include -#include +#include namespace stan { namespace services { diff --git a/src/stan/variational/base_family.hpp b/src/stan/variational/base_family.hpp index 1235a75a34..5e2d3d7a3d 100644 --- a/src/stan/variational/base_family.hpp +++ b/src/stan/variational/base_family.hpp @@ -2,7 +2,7 @@ #define STAN_VARIATIONAL_BASE_FAMILY_HPP #include -#include +#include #include #include diff --git a/src/stan/variational/families/normal_fullrank.hpp b/src/stan/variational/families/normal_fullrank.hpp index 631f46e3e5..8775e376ac 100644 --- a/src/stan/variational/families/normal_fullrank.hpp +++ b/src/stan/variational/families/normal_fullrank.hpp @@ -2,7 +2,7 @@ #define STAN_VARIATIONAL_NORMAL_FULLRANK_HPP #include -#include +#include #include #include #include diff --git a/src/stan/variational/families/normal_meanfield.hpp b/src/stan/variational/families/normal_meanfield.hpp index d4498268b9..fbc41488e3 100644 --- a/src/stan/variational/families/normal_meanfield.hpp +++ b/src/stan/variational/families/normal_meanfield.hpp @@ -2,7 +2,7 @@ #define STAN_VARIATIONAL_NORMAL_MEANFIELD_HPP #include -#include +#include #include #include #include diff --git a/src/stan/variational/print_progress.hpp b/src/stan/variational/print_progress.hpp index 7a640bd013..6558e672aa 100644 --- a/src/stan/variational/print_progress.hpp +++ b/src/stan/variational/print_progress.hpp @@ -2,7 +2,8 @@ #define STAN_VARIATIONAL_PRINT_PROGRESS_HPP #include -#include +#include +#include #include #include #include diff --git a/src/test/test-models/good/model/correlated_gaussian.stan b/src/test/test-models/good/model/correlated_gaussian.stan new file mode 100644 index 0000000000..fc55ebd83e --- /dev/null +++ b/src/test/test-models/good/model/correlated_gaussian.stan @@ -0,0 +1,7 @@ +parameters { + vector[2] x; +} + +model { + x ~ multi_normal([0.0, 0.0], [[1.0, 0.99], [0.99, 1.0]]); +} diff --git a/src/test/test-models/good/model/independent_gaussian.stan b/src/test/test-models/good/model/independent_gaussian.stan new file mode 100644 index 0000000000..451a1251c8 --- /dev/null +++ b/src/test/test-models/good/model/independent_gaussian.stan @@ -0,0 +1,7 @@ +parameters { + vector[2] x; +} + +model { + x ~ normal(0.0, 1.0); +} diff --git a/src/test/test-models/good/model/known_hessian.stan b/src/test/test-models/good/model/known_hessian.stan new file mode 100644 index 0000000000..da35f67443 --- /dev/null +++ b/src/test/test-models/good/model/known_hessian.stan @@ -0,0 +1,7 @@ +parameters { + real x[3]; +} + +model { + x ~ normal(0, 1); +}