void Bs_integrator::extrapol( Cluster &cl_exp, vector<mpreal> &h, vector<Cluster> &cl ) { int M = h.size(); int N = cl[0].get_N(); vector< Star* > st(M); for(int i=0; i<M; i++) st[i] = cl[i].get_pointer_to_star(); Star* st_exp = cl_exp.get_pointer_to_star(); for(int i=0; i<N; i++) { vector<mpreal> x_sample(M), y_sample(M), z_sample(M), vx_sample(M), vy_sample(M), vz_sample(M); for(int j=0; j<M; j++) { x_sample[j] = st[j]->x; y_sample[j] = st[j]->y; z_sample[j] = st[j]->z; vx_sample[j] = st[j]->vx; vy_sample[j] = st[j]->vy; vz_sample[j] = st[j]->vz; } st_exp->x = extrapolate(h, x_sample, "0.0"); st_exp->y = extrapolate(h, y_sample, "0.0"); st_exp->z = extrapolate(h, z_sample, "0.0"); st_exp->vx = extrapolate(h, vx_sample, "0.0"); st_exp->vy = extrapolate(h, vy_sample, "0.0"); st_exp->vz = extrapolate(h, vz_sample, "0.0"); for(int j=0; j<M; j++) st[j]++; st_exp++; } }
sample transition(sample& init_sample) { // Initialize the algorithm this->sample_stepsize(); nuts_util util; this->seed(init_sample.cont_params()); this->_hamiltonian.sample_p(this->_z, this->_rand_int); this->_hamiltonian.init(this->_z); ps_point z_plus(this->_z); ps_point z_minus(z_plus); ps_point z_sample(z_plus); ps_point z_propose(z_plus); int n_cont = init_sample.cont_params().size(); Eigen::VectorXd rho_init = this->_z.p; Eigen::VectorXd rho_plus(n_cont); rho_plus.setZero(); Eigen::VectorXd rho_minus(n_cont); rho_minus.setZero(); util.H0 = this->_hamiltonian.H(this->_z); // Sample the slice variable util.log_u = std::log(this->_rand_uniform()); // Build a balanced binary tree until the NUTS criterion fails util.criterion = true; int n_valid = 0; this->_depth = 0; this->_n_divergent = 0; util.n_tree = 0; util.sum_prob = 0; while (util.criterion && (this->_depth <= this->_max_depth) ) { // Randomly sample a direction in time ps_point* z = 0; Eigen::VectorXd* rho = 0; if (this->_rand_uniform() > 0.5) { z = &z_plus; rho = &rho_plus; util.sign = 1; } else { z = &z_minus; rho = &rho_minus; util.sign = -1; } // And build a new subtree in that direction this->_z.ps_point::operator=(*z); int n_valid_subtree = build_tree(_depth, *rho, 0, z_propose, util); *z = this->_z; // Metropolis-Hastings sample the fresh subtree if (!util.criterion) break; double subtree_prob = 0; if (n_valid) { subtree_prob = static_cast<double>(n_valid_subtree) / static_cast<double>(n_valid); } else { subtree_prob = n_valid_subtree ? 1 : 0; } if (this->_rand_uniform() < subtree_prob) z_sample = z_propose; n_valid += n_valid_subtree; // Check validity of completed tree this->_z.ps_point::operator=(z_plus); Eigen::VectorXd delta_rho = rho_minus + rho_init + rho_plus; util.criterion = compute_criterion(z_minus, this->_z, delta_rho); ++(this->_depth); } --(this->_depth); // Correct for increment at end of loop double accept_prob = util.sum_prob / static_cast<double>(util.n_tree); this->_z.ps_point::operator=(z_sample); return sample(this->_z.q, - this->_z.V, accept_prob); }
sample transition(sample& init_sample, interface_callbacks::writer::base_writer& info_writer, interface_callbacks::writer::base_writer& error_writer) { // Initialize the algorithm this->sample_stepsize(); nuts_util util; this->seed(init_sample.cont_params()); this->hamiltonian_.sample_p(this->z_, this->rand_int_); this->hamiltonian_.init(this->z_, info_writer, error_writer); ps_point z_plus(this->z_); ps_point z_minus(z_plus); ps_point z_sample(z_plus); ps_point z_propose(z_plus); int n_cont = init_sample.cont_params().size(); Eigen::VectorXd rho_init = this->z_.p; Eigen::VectorXd rho_plus(n_cont); rho_plus.setZero(); Eigen::VectorXd rho_minus(n_cont); rho_minus.setZero(); util.H0 = this->hamiltonian_.H(this->z_); // Sample the slice variable util.log_u = std::log(this->rand_uniform_()); // Build a balanced binary tree until the NUTS criterion fails util.criterion = true; int n_valid = 0; this->depth_ = 0; this->divergent_ = 0; util.n_tree = 0; util.sum_prob = 0; while (util.criterion && (this->depth_ <= this->max_depth_)) { // Randomly sample a direction in time ps_point* z = 0; Eigen::VectorXd* rho = 0; if (this->rand_uniform_() > 0.5) { z = &z_plus; rho = &rho_plus; util.sign = 1; } else { z = &z_minus; rho = &rho_minus; util.sign = -1; } // And build a new subtree in that direction this->z_.ps_point::operator=(*z); int n_valid_subtree = build_tree(depth_, *rho, 0, z_propose, util, info_writer, error_writer); ++(this->depth_); *z = this->z_; // Metropolis-Hastings sample the fresh subtree if (!util.criterion) break; double subtree_prob = 0; if (n_valid) { subtree_prob = static_cast<double>(n_valid_subtree) / static_cast<double>(n_valid); } else { subtree_prob = n_valid_subtree ? 1 : 0; } if (this->rand_uniform_() < subtree_prob) z_sample = z_propose; n_valid += n_valid_subtree; // Check validity of completed tree this->z_.ps_point::operator=(z_plus); Eigen::VectorXd delta_rho = rho_minus + rho_init + rho_plus; util.criterion = compute_criterion(z_minus, this->z_, delta_rho); } this->n_leapfrog_ = util.n_tree; double accept_prob = util.sum_prob / static_cast<double>(util.n_tree); this->z_.ps_point::operator=(z_sample); this->energy_ = this->hamiltonian_.H(this->z_); return sample(this->z_.q, - this->z_.V, accept_prob); }