// Simulate a WeeklyCyclePoissonProcess by thinning PointProcess WP::simulate(RNG &rng, const DateTime &t0, const DateTime &t1, std::function<Data *()> mark_generator) const { PointProcess ans(t0, t1); double max_rate = 0; for (int d = 0; d < 7; ++d) { for (int h = 0; h < 24; ++h) { max_rate = std::max(max_rate, event_rate(DayNames(d), h)); } } double duration = t1 - t0; int number_of_candidate_events = rpois_mt(rng, max_rate * duration); Vector times(number_of_candidate_events); for (int i = 0; i < number_of_candidate_events; ++i) { times[i] = runif_mt(rng, 0, duration); } times.sort(); for (int i = 0; i < times.size(); ++i) { DateTime cand = t0 + times[i]; double prob = event_rate(cand) / max_rate; if (runif_mt(rng, 0, 1) < prob) { Data *mark = mark_generator(); if (mark) { ans.add_event(cand, Ptr<Data>(mark)); } else { ans.add_event(cand); } } } return ans; }
// Args: // rng: The random number generator. // binary_inputs: The value of the inputs to the terminal layer (i.e. the // outputs from the final hidden layer). These will be updated by the // imputation. // logprob: On input this is a vector giving the marginal (un-logged) // probability that each input node is active. These values will be // over-written by their logarithms. // logprob_complement: On input this is any vector with size matching // logprob. On output its elements contain log(1 - exp(logprob)). // // Effects: // The latent data for the terminal layer is imputed, and the sufficient // statistics for the latent regression model in the terminal layer are // updated to included the imputed data. void GFFPS::impute_terminal_layer_inputs( RNG &rng, double response, std::vector<bool> &binary_inputs, Vector &logprob, Vector &logprob_complement) { for (int i = 0; i < logprob.size(); ++i) { logprob_complement[i] = log(1 - logprob[i]); logprob[i] = log(logprob[i]); } Vector terminal_layer_inputs(binary_inputs.size()); Nnet::to_numeric(binary_inputs, terminal_layer_inputs); double logp_original = terminal_inputs_log_full_conditional( response, terminal_layer_inputs, logprob, logprob_complement); for (int i = 0; i < terminal_layer_inputs.size(); ++i) { terminal_layer_inputs[i] = 1 - terminal_layer_inputs[i]; double logp = terminal_inputs_log_full_conditional( response, terminal_layer_inputs, logprob, logprob_complement); double log_input_prob = logp - lse2(logp, logp_original); double logu = log(runif_mt(rng)); if (logu < log_input_prob) { logp_original = logp; } else { terminal_layer_inputs[i] = 1 - terminal_layer_inputs[i]; } } model_->terminal_layer()->suf()->add_mixture_data( response, terminal_layer_inputs, 1.0); Nnet::to_binary(terminal_layer_inputs, binary_inputs); }
//---------------------------------------------------------------------- // 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; } } }
double rtriangle_mt(RNG & rng, double x0, double x1, double xm){ /* simulates from the noncentral triangle distribution on the interval (x0, x1) with a break at xm. If xm < x0 || xm > x1 then xm is taken to be the midpoint of the interval. */ double y, m0, m1, a0, u; if(x1 < x0) { std::ostringstream err; err << "error in rtriangle_mt: called with" << std::endl << "x0 = " << x0 << std::endl << "x1 = " << x1 << std::endl << "xm = " << xm << std::endl << "x0 must be less than x1"; throw_exception<std::runtime_error>(err.str()); } else if(x0 == x1) return x0; if(xm < x0 || xm > x1) xm=(x0 + x1)/2.0; y = 2.0/(x1-x0); m0 = y/(xm-x0); m1= y/(xm-x1); a0 = 0.5*y*(xm-x0); u=runif_mt(rng,0,1); double ans =0; if(u<a0) ans = x0 + sqrt(2*u/m0); /* area of left right triangle */ else if(u>=a0) ans = x1-sqrt(-2.0*(1-u)/m1); /* area of right right triangle */ else throw_exception<std::runtime_error>("an unknown error occurred in rtriangle_mt"); return ans; }
// Find the upper and lower limits of a slice containing x for a // potentially multimodal distribution. Uses Neal's (2003 Annals of // Statistics) doubling algorithm. bool SSS::find_limits_unbounded(double x){ hi_ = x + suggested_dx_; lo_ = x - suggested_dx_; logphi_ = logf_(hi_); logplo_ = logf_(lo_); if(unimodal_){ find_limits_unbounded_unimodal(x); return true; }else{ int doubling_count = 0; while(!done_doubling()){ double u = runif_mt(rng(), -1, 1); if(u>0) double_hi(x); else double_lo(x); if (++doubling_count > 100) { // The slice has been doubled 100 times. This is almost // certainly beecause of an error in the target distribution // or a crazy starting value. return false; } } } check_upper_limit(x); check_lower_limit(x); return true; }
//---------------------------------------------------------------------- void BLCSSS::rwm_draw_chunk(int chunk){ clock_t start = clock(); const Selector &inc(m_->coef().inc()); int nvars = inc.nvars(); Vec full_nonzero_beta = m_->beta(); // only nonzero components // Compute information matrix for proposal distribution. For // efficiency, also compute the log-posterior of the current beta. Vec mu(inc.select(pri_->mu())); Spd siginv(inc.select(pri_->siginv())); double original_logpost = dmvn(full_nonzero_beta, mu, siginv, 0, true); const std::vector<Ptr<BinomialRegressionData> > &data(m_->dat()); int nobs = data.size(); int full_chunk_size = compute_chunk_size(); int chunk_start = chunk * full_chunk_size; int elements_remaining = nvars - chunk_start; int this_chunk_size = std::min(elements_remaining, full_chunk_size); Selector chunk_selector(nvars, false); for(int i = chunk_start; i< chunk_start + this_chunk_size; ++i) { chunk_selector.add(i); } Spd proposal_ivar = chunk_selector.select(siginv); for(int i = 0; i < nobs; ++i){ Vec x = inc.select(data[i]->x()); double eta = x.dot(full_nonzero_beta); double prob = plogis(eta); double weight = prob * (1-prob); VectorView x_chunk(x, chunk_start, this_chunk_size); // Only upper triangle is accessed. Need to reflect at end of loop. proposal_ivar.add_outer(x_chunk, weight, false); int yi = data[i]->y(); int ni = data[i]->n(); original_logpost += dbinom(yi, ni, prob, true); } proposal_ivar.reflect(); VectorView beta_chunk(full_nonzero_beta, chunk_start, this_chunk_size); if(tdf_ > 0){ beta_chunk = rmvt_ivar_mt( rng(), beta_chunk, proposal_ivar / rwm_variance_scale_factor_, tdf_); }else{ beta_chunk = rmvn_ivar_mt( rng(), beta_chunk, proposal_ivar / rwm_variance_scale_factor_); } double logpost = dmvn(full_nonzero_beta, mu, siginv, 0, true); Vec full_beta(inc.expand(full_nonzero_beta)); logpost += m_->log_likelihood(full_beta, 0, 0, false); double log_alpha = logpost - original_logpost; double logu = log(runif_mt(rng())); ++rwm_chunk_attempts_; if(logu < log_alpha){ m_->set_beta(full_nonzero_beta); ++rwm_chunk_successes_; } clock_t end = clock(); rwm_chunk_times_ += double(end - start) / CLOCKS_PER_SEC; }
void SliceSampler::find_limits(){ if(unimodal){ while(phi > pstar) doubling(true); while(plo > pstar) doubling(false); }else{ while(phi > pstar || plo > pstar){ double tmp = runif_mt(rng(), -1,1); doubling(tmp>0);}}}
//---------------------------------------------------------------------- void BLCSSS::rwm_draw_chunk(int chunk){ const Selector &inc(m_->coef().inc()); int nvars = inc.nvars(); Vector full_nonzero_beta = m_->included_coefficients(); // Compute information matrix for proposal distribution. For // efficiency, also compute the log-posterior of the current beta. Vector mu(inc.select(pri_->mu())); SpdMatrix siginv(inc.select(pri_->siginv())); double original_logpost = dmvn(full_nonzero_beta, mu, siginv, 0, true); const std::vector<Ptr<BinomialRegressionData> > &data(m_->dat()); int nobs = data.size(); int full_chunk_size = compute_chunk_size(max_rwm_chunk_size_); int chunk_start = chunk * full_chunk_size; int elements_remaining = nvars - chunk_start; int this_chunk_size = std::min(elements_remaining, full_chunk_size); Selector chunk_selector(nvars, false); for(int i = chunk_start; i< chunk_start + this_chunk_size; ++i) { chunk_selector.add(i); } SpdMatrix proposal_ivar = chunk_selector.select(siginv); for(int i = 0; i < nobs; ++i){ Vector x = inc.select(data[i]->x()); double eta = x.dot(full_nonzero_beta); double prob = plogis(eta); double weight = prob * (1-prob); VectorView x_chunk(x, chunk_start, this_chunk_size); // Only upper triangle is accessed. Need to reflect at end of loop. proposal_ivar.add_outer(x_chunk, weight, false); original_logpost += dbinom(data[i]->y(), data[i]->n(), prob, true); } proposal_ivar.reflect(); VectorView beta_chunk(full_nonzero_beta, chunk_start, this_chunk_size); if(tdf_ > 0){ beta_chunk = rmvt_ivar_mt( rng(), beta_chunk, proposal_ivar / rwm_variance_scale_factor_, tdf_); }else{ beta_chunk = rmvn_ivar_mt( rng(), beta_chunk, proposal_ivar / rwm_variance_scale_factor_); } double logpost = dmvn(full_nonzero_beta, mu, siginv, 0, true); Vector full_beta(inc.expand(full_nonzero_beta)); logpost += m_->log_likelihood(full_beta, 0, 0, false); double log_alpha = logpost - original_logpost; double logu = log(runif_mt(rng())); if (logu < log_alpha) { m_->set_included_coefficients(full_nonzero_beta); move_accounting_.record_acceptance("rwm_chunk"); } else { move_accounting_.record_rejection("rwm_chunk"); } }
double BLSSS::mcmc_one_flip(Selector &mod, uint which_var, double logp_old) { mod.flip(which_var); double logp_new = log_model_prob(mod); double u = runif_mt(rng(), 0,1); if(log(u) > logp_new - logp_old) { mod.flip(which_var); // reject draw return logp_old; } return logp_new; }
double Tn2Sampler::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; if(lam==0){ cand = runif_mt(rng, lo, hi); }else{ cand = rtrun_exp_mt(rng, lam, lo, hi); } double target = f(cand); double logu = hull(cand, k) - rexp_mt(rng, 1); if(logu < target) return cand; add_point(cand); return draw(rng); }
double rig_mt(RNG & rng, double mu, double lambda){ double y = rnorm_mt(rng); y = y * y; double mu2 = mu * mu; double muy = mu * y; double mu2lam = .5 * mu/lambda; double x = mu + muy * mu2lam - mu2lam * sqrt(muy * (4*lambda + muy)); double z = runif_mt(rng); if(z > mu/(mu+x)) return mu2/x; return x; }
double rtrun_exp_mt(RNG & rng, double lam, double lo, double hi){ // samples a random variable from the exponential distribution with // rate lam, with support truncated between lo and hi double Fmax = 1-exp(-lam*(hi-lo)); double u = runif_mt(rng, 0, 1); double x = lo - log(1-u*Fmax)/lam; return x; }
Vector SliceSampler::draw(const Vector &theta) { last_position_ = theta; initialize(); find_limits(); Vector candidate; double logp_candidate = log_p_slice_ - 1; do { double lambda = runif_mt(rng(), -lo_, hi_); candidate = last_position_ + lambda * random_direction_; logp_candidate = logp_(candidate); if (logp_candidate < log_p_slice_) contract(lambda, logp_candidate); } while (logp_candidate < log_p_slice_); scale_ = hi_ + lo_; // both hi_ and lo_ > 0 return candidate; }
bool SSS::find_lower_limit(double x){ lo_ = x - suggested_dx_; logplo_ = logf_(lo_); int doubling_count = 0; while(logplo_ >= logp_slice_ || (!unimodal_ && runif_mt(rng()) > .5)){ double_lo(x); if (++doubling_count > 100) { // The slice has been doubled over 100 times. This is almost // certainly because of an error in the implementation of the // target distribution, or a crazy starting value. return false; } } check_lower_limit(x); return true; }
void SliceSampler::find_limits() { if (unimodal_) { // If the posterior is unimodal then expand each endpoint until it // is out of the slice. while (logphi_ > log_p_slice_) doubling(true); while (logplo_ > log_p_slice_) doubling(false); } else { // If the posterior is not known to be unimodal, then randomly // pick an endpoint and double it until both ends are out of the // slice. This will sometimes result in unnecessary doubling, // but this algorithm has the right stationary distribution // (Neal 2003). while (logphi_ > log_p_slice_ || logplo_ > log_p_slice_) { double tmp = runif_mt(rng(), -1, 1); doubling(tmp > 0); } } }
Vec SliceSampler::draw(const Vec &t){ theta = t; z = t; initialize(); pstar = f(theta) - rexp(1); find_limits(); Vec tstar(theta.size(), 0.0); double p = pstar -1; do{ double lam = runif_mt(rng(), -lo, hi); tstar = theta + lam*z; // randomly chosen point in the slice p = f(tstar); if(p<pstar) contract(lam,p); else theta = tstar; }while(p < pstar); scale = hi+lo; // both hi and lo >0 return theta; }
//---------------------------------------------------------------------- void BLCSSS::draw(){ double u = runif_mt(rng()); clock_t start = clock(); if(u < .333){ ++auxmix_tries_; BinomialLogitSpikeSlabSampler::draw(); clock_t end = clock(); auxmix_times_ += double(end - start) / CLOCKS_PER_SEC; }else if(u < .6667){ ++rwm_tries_; rwm_draw(); clock_t end = clock(); rwm_times_ += double(end - start) / CLOCKS_PER_SEC; }else{ ++tim_tries_; tim_draw(); clock_t end = clock(); tim_times_ += double (end - start) / CLOCKS_PER_SEC; } }
double SSS::draw(double x){ find_limits(x); double logp_cand = 0; int number_of_tries = 0; do{ double x_cand = runif_mt(rng(), lo_, hi_); logp_cand = logf_(x_cand); if(logp_cand < logp_slice_){ contract(x,x_cand, logp_cand); ++number_of_tries; } else return x_cand; if(number_of_tries > 100){ ostringstream err; err << "number of tries exceeded. candidate value is " << x_cand << " with logp_cand = " << logp_cand << endl; handle_error(err.str(), x); } }while(logp_cand < logp_slice_); handle_error("should never get here", x); return 0; }
int random_int_mt(RNG & rng, int lo, int hi){ double tmp = runif_mt(rng, lo, hi+1); return static_cast<int>(std::floor(tmp)); }
double ZIGM::sim(RNG &rng) const { if (runif_mt(rng) < positive_probability()) { return gamma_->sim(rng); } return 0; }
double runif(double a, double b){ return runif_mt(BOOM::GlobalRng::rng, a, b); }
int rmulti_mt(RNG & rng, int lo, int hi){ // draw a random integer between lo and hi with equal probability double tmp = runif_mt(rng, lo+0.0,hi+1.0); return (int)floor(tmp); }
double UM::sim(RNG &rng) const { return runif_mt(rng, lo(), hi()); }
double OrdinalLogitImputer::impute( RNG &rng, double eta, double lower_cutpoint, double upper_cutpoint) { return eta + qlogis(runif_mt( rng, plogis(lower_cutpoint - eta), plogis(upper_cutpoint - eta))); }