Пример #1
0
double search_interval(double x0,double& L, double& R, slice_function& g,double logy)
{
  //  assert(g(x0) > g(L) and g(x0) > g(R));
  assert(g(x0) >= logy);
  assert(L < R);
  assert(L <= x0 and x0 <= R);

  double L0 = L, R0 = R;

  // std::cerr<<"**    L0 = "<<L0<<"   x0 = "<<x0<<"   R0 = "<<R0<<std::endl;
  for(int i=0;i<200;i++)
  {
    double x1 = L + uniform()*(R-L);
    double gx1 = g(x1);
    //   std::cerr<<"    L  = "<<L <<"   x = "<<g.current_value()<<"   R  = "<<R<<std::endl;
    //   std::cerr<<"    logy  = "<<logy<<"\n"; //  logy_x0 = "<<logy_x0<<" logy_current = "<<g()<<std::endl;

    if (gx1 >= logy) return x1;

    if (x1 > x0) 
      R = x1;
    else
      L = x1;
  }
  std::cerr<<"Warning!  Is size of the interval really ZERO?"<<std::endl;
  double logy_x0 = g(x0);  
  std::cerr<<"    L0 = "<<L0<<"   x0 = "<<x0<<"   R0 = "<<R0<<std::endl;
  std::cerr<<"    L  = "<<L <<"   x = "<<g.current_value()<<"   R  = "<<R<<std::endl;
  std::cerr<<"    logy  = "<<logy<<"  logy_x0 = "<<logy_x0<<"  logy_current = "<<g()<<std::endl;

  std::abort();

  return x0;
}
Пример #2
0
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;
  }
}
Пример #3
0
inline static void dec(double& x, double w, const slice_function& g, bool& hit_lower_bound)
{
  x -= w;
  if (g.below_lower_bound(x)) {
    x = g.lower_bound;
    hit_lower_bound=true;
  }
}
Пример #4
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);
}
Пример #5
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);
}
Пример #6
0
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);
}
Пример #7
0
// 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);
}
Пример #8
0
double slice_sample(slice_function& g, double w, int m)
{
  double x0 = g.current_value();
  return slice_sample(x0,g,w,m);
}