示例#1
0
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);
}
示例#2
0
double slice_sample(double x0, slice_function& g,double w, int m)
{
  assert(g.in_range(x0));

  double gx0 = g();
  volatile double diff = gx0 - g(x0);
  assert(std::abs(diff) < 1.0e-9);

  // Determine the slice level, in log terms.

  double logy = gx0 - exponential(1);

  // Find the initial interval to sample from.

  std::pair<double,double> interval = find_slice_boundaries_stepping_out(x0,g,logy,w,m);
  double L = interval.first;
  double R = interval.second;

  // Sample from the interval, shrinking it on each rejection

  return search_interval(x0,L,R,g,logy);
}