/* * SliceInterval.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.inference.operators; import dr.inference.model.Likelihood; import dr.inference.model.Variable; import dr.math.MathUtils; /** * Constructs a univariate slice sampler interval * * @author Marc Suchard */ public interface SliceInterval { public double drawFromInterval(Likelihood likelihood, double cutoffDensity, double width); public void setSliceSampler(SliceOperator sliceSampler); public abstract class Abstract implements SliceInterval { public double drawFromInterval(Likelihood likelihood, double cutoffDensity, double width) { double x0 = variable.getValue(0); Interval interval = constructInterval(likelihood, x0, cutoffDensity, width); double x1 = x0; boolean found = false; while (!found) { x1 = MathUtils.uniform(interval.lower, interval.upper); if (cutoffDensity < evaluate(likelihood, x1) && test(likelihood, x0, x1, cutoffDensity, width)) { found = true; } else { shrinkInterval(interval, x0, x1); } } return x1; } public abstract Interval constructInterval(Likelihood likelihood, double x0, double cutoffDensity, double width); protected abstract boolean test(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(Likelihood likelihood, double x) { variable.setValue(0, x); return sliceSampler.evaluate(likelihood, 1.0); } 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(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(likelihood, L) ) { L -= w; J--; } while (K > 0 && cutoffDensity < evaluate(likelihood, R) ) { R += w; K--; } return new Interval(L,R); } protected boolean test(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(Likelihood likelihood, double x0, double cutoffDensity, double width) { // TODO return new Interval(0,1); } protected boolean test(Likelihood likelihood, double x0, double x1, double cutoffDensity, double width) { // TODO return true; } } }