package dr.inference.operators; import dr.math.MathUtils; import dr.inference.model.Variable; import dr.inference.model.Likelihood; import dr.inference.prior.Prior; /** * Constructs a univariate slice sampler interval * * @author Marc Suchard */ public interface SliceInterval { public double drawFromInterval(Prior prior, Likelihood likelihood, double cutoffDensity, double width); public void setSliceSampler(SliceOperator sliceSampler); public abstract class Abstract implements SliceInterval { public double drawFromInterval(Prior prior, Likelihood likelihood, double cutoffDensity, double width) { double x0 = variable.getValue(0); Interval interval = constructInterval(prior, likelihood, x0, cutoffDensity, width); double x1 = x0; boolean found = false; while (!found) { x1 = MathUtils.uniform(interval.lower, interval.upper); if (cutoffDensity < evaluate(prior, likelihood, x1) && test(prior, likelihood, x0, x1, cutoffDensity, width)) { found = true; } else { shrinkInterval(interval, x0, x1); } } return x1; } public abstract Interval constructInterval(Prior prior, Likelihood likelihood, double x0, double cutoffDensity, double width); protected abstract boolean test(Prior prior, Likelihood likelihood, double x0, double x1, double cutoffDensity, double width); public void shrinkInterval(Interval interval, double x0, double x1) { // Taken from Fig 5 in Neal (2003) if (x1 < x0) { interval.lower = x1; } else { interval.upper = x1; } } protected class Interval { double lower; double upper; Interval(double lower, double upper) { this.lower = lower; this.upper = upper; } } public void setSliceSampler(SliceOperator sliceSampler) { this.sliceSampler = sliceSampler; this.variable = sliceSampler.getVariable(); } protected double evaluate(Prior prior, Likelihood likelihood, double x) { variable.setValue(0, x); return sliceSampler.evaluate(likelihood, prior); } protected Variable<Double> variable; protected SliceOperator sliceSampler; } public class SteppingOut extends Abstract { public SteppingOut() { this(10); // TODO Pick better default } public SteppingOut(int m) { this.m = m; } public Interval constructInterval(Prior prior, Likelihood likelihood, double x0, double cutoffDensity, double w) { // Taken from Fig 3 in Neal (2003) double L = x0 - w * MathUtils.nextDouble(); double R = L + w; int J = MathUtils.nextInt(m); int K = (m - 1) - J; while (J > 0 && cutoffDensity < evaluate(prior, likelihood, L) ) { L -= w; J--; } while (K > 0 && cutoffDensity < evaluate(prior, likelihood, R) ) { R += w; K--; } return new Interval(L,R); } protected boolean test(Prior prior, Likelihood likelihood, double x0, double x1, double cutoffDensity, double width) { return true; } private int m; // Maximum number of stepping out intervals to explore } public class Doubling extends Abstract { public Interval constructInterval(Prior prior, Likelihood likelihood, double x0, double cutoffDensity, double width) { // TODO return new Interval(0,1); } protected boolean test(Prior prior, Likelihood likelihood, double x0, double x1, double cutoffDensity, double width) { // TODO return true; } } }