/* * JointOperator.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.math.MathUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.util.ArrayList; /** * @author Marc A. Suchard */ public class JointOperator extends SimpleMCMCOperator implements CoercableMCMCOperator { private final ArrayList<SimpleMCMCOperator> operatorList; private final ArrayList<Integer> operatorToOptimizeList; private int currentOptimizedOperator; private final double targetProbability; public JointOperator(double weight, double targetProb) { operatorList = new ArrayList<SimpleMCMCOperator>(); operatorToOptimizeList = new ArrayList<Integer>(); targetProbability = targetProb; setWeight(weight); } public void addOperator(SimpleMCMCOperator operation) { operatorList.add(operation); if (operation instanceof CoercableMCMCOperator) { if (((CoercableMCMCOperator) operation).getMode() == CoercionMode.COERCION_ON) operatorToOptimizeList.add(operatorList.size() - 1); } } public final double doOperation() { double logP = 0; for (SimpleMCMCOperator operation : operatorList) { logP += operation.doOperation(); // todo After a failure, should not have to complete remaining operations, need to fake their operate(); } return logP; } // private double old; public double getCoercableParameter() { if (operatorToOptimizeList.size() > 0) { currentOptimizedOperator = operatorToOptimizeList.get(MathUtils.nextInt(operatorToOptimizeList.size())); return ((CoercableMCMCOperator) operatorList.get(currentOptimizedOperator)).getCoercableParameter(); } throw new IllegalArgumentException(); } public void setCoercableParameter(double value) { if (operatorToOptimizeList.size() > 0) { ((CoercableMCMCOperator) operatorList.get(currentOptimizedOperator)).setCoercableParameter(value); return; } throw new IllegalArgumentException(); } public int getNumberOfSubOperators() { return operatorList.size(); } public double getRawParamter(int i) { if (i < 0 || i >= operatorList.size()) throw new IllegalArgumentException(); return ((CoercableMCMCOperator) operatorList.get(i)).getRawParameter(); } public double getRawParameter() { throw new RuntimeException("More than one raw parameter for a joint operator"); } public CoercionMode getMode() { if (operatorToOptimizeList.size() > 0) return CoercionMode.COERCION_ON; return CoercionMode.COERCION_OFF; } public MCMCOperator getSubOperator(int i) { return operatorList.get(i); } public CoercionMode getSubOperatorMode(int i) { if (i < 0 || i >= operatorList.size()) throw new IllegalArgumentException(); if (operatorList.get(i) instanceof CoercableMCMCOperator) return ((CoercableMCMCOperator) operatorList.get(i)).getMode(); return CoercionMode.COERCION_OFF; } public String getSubOperatorName(int i) { if (i < 0 || i >= operatorList.size()) throw new IllegalArgumentException(); return "Joint." + operatorList.get(i).getOperatorName(); } public String getOperatorName() { // StringBuffer sb = new StringBuffer("Joint(\n"); // for(SimpleMCMCOperator operation : operatorList) // sb.append("\t"+operation.getOperatorName()+"\n"); // sb.append(") opt = "+optimizedOperator.getOperatorName()); // return sb.toString(); return "JointOperator"; } public Element createOperatorElement(Document d) { throw new RuntimeException("not implemented"); } public double getTargetAcceptanceProbability() { return targetProbability; } public double getMinimumAcceptanceLevel() { double min = targetProbability - 0.2; if (min < 0) min = 0.01; return min; } public double getMaximumAcceptanceLevel() { double max = targetProbability + 0.2; if (max > 1) max = 0.9; return max; } public double getMinimumGoodAcceptanceLevel() { double min = targetProbability - 0.1; if (min < 0) min = 0.01; return min; } public double getMaximumGoodAcceptanceLevel() { double max = targetProbability + 0.2; if (max > 1) max = 0.9; return max; } public final String getPerformanceSuggestion() { // double prob = MCMCOperator.Utils.getAcceptanceProbability(this); // double targetProb = getTargetAcceptanceProbability(); // dr.util.NumberFormatter formatter = new dr.util.NumberFormatter(5); // double sf = OperatorUtils.optimizeScaleFactor(scaleFactor, prob, targetProb); // if (prob < getMinimumGoodAcceptanceLevel()) { // return "Try setting scaleFactor to about " + formatter.format(sf); // } else if (prob > getMaximumGoodAcceptanceLevel()) { // return "Try setting scaleFactor to about " + formatter.format(sf); // } else return ""; return ""; } }