//---------------------------------------------------------------------- // univariate slice sampling to set each element void CS::draw_one() { double oldr = R_(i_, j_); double logp_star = logp(R_(i_, j_)); double u = logp_star - rexp_mt(rng(), 1); find_limits(); if (lo_ >= hi_) { set_r(0); return; } // const double eps(100*std::numeric_limits<double>::epsilon()); const double eps(1e-6); check_limits(oldr, eps); while (1) { double cand = runif_mt(rng(), lo_, hi_); double logp_cand = logp(cand); if (logp_cand > u) { // found something inside slice set_r(cand); return; } else { // contract slice if (cand > oldr) { hi_ = cand; } else { lo_ = cand; } } if (fabs(hi_ - lo_) < eps) { set_r(hi_); return; } } }
// Driver function to find the limits of a slice containing 'x'. // Logic varies according to whether the distribution is bounded // above, below, both, or neither. void SSS::find_limits(double x){ logp_slice_ = logf_(x) - rexp_mt(rng(), 1.0); check_finite(x,logp_slice_); bool limits_successfully_found = true; if(doubly_bounded()){ lo_ = lower_bound_; logplo_ = logf_(lo_); hi_ = upper_bound_; logphi_ = logf_(hi_); }else if (lower_bounded()){ lo_ = lower_bound_; logplo_ = logf_(lo_); limits_successfully_found = find_upper_limit(x); }else if(upper_bounded()){ limits_successfully_found = find_lower_limit(x); hi_ = upper_bound_; logphi_ = logf_(hi_); }else{ // unbounded limits_successfully_found = find_limits_unbounded(x); } check_slice(x); if (limits_successfully_found) { check_probs(x); } }
double DBARS::draw(RNG &rng){ double u= runif_mt(rng, 0, cdf.back()); IT pos = std::lower_bound(cdf.begin(), cdf.end(), u); uint k = pos - cdf.begin(); // draw from the doubly truncated exponential distribution double lo = knots[k]; double hi = knots[k+1]; double lam = -1*dlogf[k]; double cand = rtrun_exp_mt(rng, lam, lo, hi); double target = f(cand); double hull = h(cand, k); double logu = hull - rexp_mt(rng, 1); if(logu < target) return cand; add_point(cand); return draw(rng); }
// To be called as part of draw(). Set up the bits that define the // slice, and make sure everything is finite. void SliceSampler::initialize() { // Check that logp_slice_ has a finite value. log_p_slice_ = logp_(last_position_); if (!std::isfinite(log_p_slice_)) { std::string msg = "invalid condition used to initialize SliceSampler"; report_error(msg); } log_p_slice_ -= rexp_mt(rng(), 1); // Reset scale_ if something has gone wrong. if (scale_ < .0001 * fabs(mean(last_position_))) { // Very small values of scale_ can make the algorithm take // forever. scale_ = .1 * fabs(mean(last_position_)); } if (scale_ <= 0.0 || !std::isfinite(scale_)) { // Infinite or NaN values of scale can result in an infinite // loop. scale_ = 1.0; } lo_ = scale_; hi_ = scale_; set_random_direction(); logplo_ = logp_(last_position_ - lo_ * random_direction_); // If necessary, shrink the lower bound until the log density is // finite. while (!std::isfinite(logplo_)) { lo_ /= 2.0; logplo_ = logp_(last_position_ - lo_ * random_direction_); } logphi_ = logp_(last_position_ + hi_ * random_direction_); // If necessary, shrink the upper bound until the log density is // finite. while (!std::isfinite(logphi_)) { hi_ /= 2.0; logphi_ = logp_(last_position_ + hi_ * random_direction_); } }
double ExponentialModel::sim(RNG &rng) const { return rexp_mt(rng, lam()); }