std::pair<double,double> find_slice_boundaries_stepping_out(double x0,slice_function& g,double logy, double w,int m) { assert(g.in_range(x0)); double u = uniform()*w; double L = x0 - u; double R = x0 + (w-u); // Expand the interval until its ends are outside the slice, or until // the limit on steps is reached. // std::cerr<<"!! L0 = "<<L<<" x0 = "<<x0<<" R0 = "<<R<<"\n"; if (m>1) { int J = uniform(0,m-1); int K = (m-1)-J; while (J>0 and (not g.below_lower_bound(L)) and g(L)>logy) { L -= w; J--; // std::cerr<<" g("<<L<<") = "<<g()<<" > "<<logy<<"\n"; // std::cerr<<"<- L0 = "<<L<<" x0 = "<<x0<<" R0 = "<<R<<"\n"; } while (K>0 and (not g.above_upper_bound(R)) and g(R)>logy) { R += w; K--; // std::cerr<<" g("<<R<<") = "<<g()<<" > "<<logy<<"\n"; // std::cerr<<"-> L0 = "<<L<<" x0 = "<<x0<<" R0 = "<<R<<"\n"; } } else { while ((not g.below_lower_bound(L)) and g(L)>logy) L -= w; while ((not g.above_upper_bound(R)) and g(R)>logy) R += w; } // Shrink interval to lower and upper bounds. if (g.below_lower_bound(L)) L = g.lower_bound; if (g.above_upper_bound(R)) R = g.upper_bound; assert(L < R); // std::cerr<<"[] L0 = "<<L<<" x0 = "<<x0<<" R0 = "<<R<<"\n"; return std::pair<double,double>(L,R); }
inline static void inc(double& x, double w, const slice_function& g, bool& hit_upper_bound) { x += w; if (g.above_upper_bound(x)) { x = g.upper_bound; hit_upper_bound = true; } }
std::pair<double,double> find_slice_boundaries_stepping_out(double x0,slice_function& g,double logy, double w,int m) { double u = uniform()*w; double L = x0 - u; double R = x0 + (w-u); // Expand the interval until its ends are outside the slice, or until // the limit on steps is reached. if (m>1) { int J = floor(uniform()*m); int K = (m-1)-J; while (J>0 and (not g.below_lower_bound(L)) and g(L)>logy) { L -= w; J--; } while (K>0 and (not g.above_upper_bound(R)) and g(R)>logy) { R += w; K--; } } else { while ((not g.below_lower_bound(L)) and g(L)>logy) L -= w; while ((not g.above_upper_bound(R)) and g(R)>logy) R += w; } // Shrink interval to lower and upper bounds. if (g.below_lower_bound(L)) L = g.lower_bound; if (g.above_upper_bound(R)) R = g.upper_bound; return std::pair<double,double>(L,R); }
// Assumes uni-modal std::pair<double,double> find_slice_boundaries_search(double& x0,slice_function& g,double logy, double w,int /*m*/) { // the initial point should be within the bounds, if the exist assert(not g.below_lower_bound(x0)); assert(not g.above_upper_bound(x0)); bool hit_lower_bound=false; bool hit_upper_bound=false; double gx0 = g(x0); double L = x0; double R = L; inc(R,w,g,hit_upper_bound); // if (gx > logy) return find_slice_boundaries_stepping_out(x,g,logy,w,m,lower_bound,lower,upper_bound,upper); int state = -1; while(1) { double gL = g(L); double gR = g(R); if (gx0 < logy and gL > gx0) { x0 = L; gx0 = gL; } if (gx0 < logy and gR > gx0) { x0 = R; gx0 = gR; } // below bound, and slopes upwards to the right if (gR < logy and gL < gR) { if (state == 2) break; else if (state == 1) { inc(R,w,g,hit_upper_bound); break; } state = 0; hit_lower_bound=false; L = R; inc(R,w,g,hit_upper_bound); } // below bound, and slopes upwards to the left else if (gL < logy and gR < gL) { if (state == 2) break; if (state == 1) { dec(L,w,g,hit_lower_bound); break; } state = 1; hit_upper_bound=false; R = L; dec(L,w,g,hit_lower_bound); } else { state = 2; bool moved = false; if (gL >= logy and not hit_lower_bound) { moved = true; dec(L,w,g,hit_lower_bound); } if (gR >= logy and not hit_upper_bound) { moved = true; inc(R,w,g,hit_upper_bound); } if (not moved) break; } } return std::pair<double,double>(L,R); }