/* * File BitFlipOperator.java * * Copyright (C) 2010 Joseph Heled jheled@gmail.com * This file is part of BEAST2. * 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 beast.evolution.operators; import beast.core.Description; import beast.core.Input; import beast.core.Input.Validate; import beast.core.Operator; import beast.core.parameter.BooleanParameter; import beast.util.Randomizer; /** * @author Joseph Heled */ @Description("Flip one bit in an array of boolean bits. The hastings ratio is designed so that all subsets of vectors with the" + " same number of 'on' bits are equiprobable.") public class BitFlipOperator extends Operator { final public Input<Boolean> uniformInput = new Input<>("uniform", "when on, total probability of combinations with k" + " 'on' bits is equal. Otherwise uniform on all combinations (default true)", true); final public Input<BooleanParameter> parameterInput = new Input<>("parameter", "the parameter to operate a flip on.", Validate.REQUIRED); private boolean usesPriorOnSum = true; @Override public void initAndValidate() { final Boolean b = uniformInput.get(); if (b != null) { usesPriorOnSum = b; } } /** * Change the parameter and return the hastings ratio. * Flip (Switch a 0 to 1 or 1 to 0) for a random bit in a bit vector. * Return the hastings ratio which makes all subsets of vectors with the same number of 1 bits * equiprobable, unless !usesPriorOnSum , then all configurations are equiprobable */ @Override public double proposal() { final BooleanParameter p = parameterInput.get(this); final int dim = p.getDimension(); double sum = 0.0; if (usesPriorOnSum) { for (int i = 0; i < dim; i++) { if (p.getValue(i)) sum += 1; } } final int pos = Randomizer.nextInt(dim); final boolean value = p.getValue(pos); double logq = 0.0; if (!value) { p.setValue(pos, true); if (usesPriorOnSum) { logq = -Math.log((dim - sum) / (sum + 1)); } } else { //assert value; p.setValue(pos, false); if (usesPriorOnSum) { logq = -Math.log(sum / (dim - sum + 1)); } } return logq; } }