/* * RateExchangeOperator.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.evomodel.operators; import dr.evolution.tree.NodeRef; import dr.evomodel.tree.TreeModel; import dr.evomodelxml.operators.RateExchangeOperatorParser; import dr.inference.operators.MCMCOperator; import dr.inference.operators.SimpleMCMCOperator; import dr.math.MathUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Implements the RateExchange move. * * @author Alexei Drummond * @version $Id: RateExchangeOperator.java,v 1.3 2005/01/06 14:46:36 rambaut Exp $ */ public class RateExchangeOperator extends SimpleMCMCOperator { private static final String TRAIT = "trait"; private final TreeModel tree; private final boolean swapRates; private final boolean swapTraits; private final boolean swapAtRoot; private final boolean moveHeight; public RateExchangeOperator(TreeModel tree, double weight, boolean swapRates, boolean swapTraits, boolean swapAtRoot, boolean moveHeight) { this.tree = tree; setWeight(weight); this.swapRates = swapRates; this.swapTraits = swapTraits; this.swapAtRoot = swapAtRoot; this.moveHeight = moveHeight; } /** * Do a probablistic subtree slide move. * * @return the log-transformed hastings ratio */ public double doOperation() { NodeRef node0 = tree.getInternalNode(MathUtils.nextInt(tree.getInternalNodeCount())); NodeRef node1 = tree.getChild(node0, 0); NodeRef node2 = tree.getChild(node0, 1); if (swapRates) { if (swapAtRoot) { double[] rates = new double[]{tree.getNodeRate(node0), tree.getNodeRate(node1), tree.getNodeRate(node2)}; int r1 = MathUtils.nextInt(3); tree.setNodeRate(node0, rates[r1]); // swap down the top trait rates[r1] = rates[2]; int r2 = MathUtils.nextInt(2); tree.setNodeRate(node1, rates[r2]); // swap down the top trait rates[r2] = rates[1]; tree.setNodeRate(node2, rates[0]); } else { // just swap the two child rates... double tmp = tree.getNodeRate(node1); tree.setNodeRate(node1, tree.getNodeRate(node2)); tree.setNodeRate(node2, tmp); } } if (swapTraits) { if (swapAtRoot) { double[] traits = new double[]{tree.getNodeTrait(node0, TRAIT), tree.getNodeTrait(node1, TRAIT), tree.getNodeTrait(node2, TRAIT)}; int r1 = MathUtils.nextInt(3); tree.setNodeTrait(node0, TRAIT, traits[r1]); // swap down the top trait traits[r1] = traits[2]; int r2 = MathUtils.nextInt(2); tree.setNodeTrait(node1, TRAIT, traits[r2]); // swap down the top trait traits[r2] = traits[1]; tree.setNodeTrait(node2, TRAIT, traits[0]); } else { // just swap the two child traits... double tmp = tree.getNodeTrait(node1, TRAIT); tree.setNodeTrait(node1, TRAIT, tree.getNodeTrait(node2, TRAIT)); tree.setNodeTrait(node2, TRAIT, tmp); } } // If the node is not the root, do a uniform pick of its height if (!tree.isRoot(node0) && moveHeight) { double lower = tree.getNodeHeightLower(node0); double upper = tree.getNodeHeightUpper(node0); double newValue = (MathUtils.nextDouble() * (upper - lower)) + lower; tree.setNodeHeight(node0, newValue); } return 0.0; } public double getTargetAcceptanceProbability() { return 0.234; } public String getPerformanceSuggestion() { if (MCMCOperator.Utils.getAcceptanceProbability(this) < getMinimumAcceptanceLevel()) { return ""; } else if (MCMCOperator.Utils.getAcceptanceProbability(this) > getMaximumAcceptanceLevel()) { return ""; } else { return ""; } } public String getOperatorName() { return RateExchangeOperatorParser.RATE_EXCHANGE; } public Element createOperatorElement(Document d) { return d.createElement(RateExchangeOperatorParser.RATE_EXCHANGE); } }