/* * SlidingPatternsOperator.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.arg.operators; import dr.evolution.alignment.SitePatterns; import dr.inference.model.Parameter; import dr.inference.model.ParameterParser; import dr.inference.operators.*; import dr.math.MathUtils; import dr.xml.*; import java.util.ArrayList; import java.util.List; /** * Created by IntelliJ IDEA. * User: msuchard * Date: Jan 18, 2007 * Time: 8:01:56 PM * To change this template use File | Settings | File Templates. */ public class SlidingPatternsOperator extends AbstractCoercableOperator { // // SimpleMCMCOperator implements CoercableMCMCOperator { public static final String WINDOW_SIZE = "windowSize"; public static final String OPERATOR_NAME = "slidingPatternsOperator"; public static final String BREAK_POINTS = "breakPoints"; public SlidingPatternsOperator(List<SitePatterns> list, Parameter breakPoints, int windowSize, int weight, CoercionMode mode) { super(mode); this.partitions = list; this.windowSize = windowSize; // this.weight = weight; // this.mode = mode; this.breakPoints = breakPoints; // System.err.println("Starting values: "+currentBreakPointsString() ); // System.exit(-1) ; } public String currentBreakPointsString() { StringBuilder sb = new StringBuilder(); sb.append("["); boolean first = true; for (double value : breakPoints.getParameterValues()) { int pt = (int) value; if (!first) { sb.append(","); first = false; } sb.append(pt); } sb.append("]"); return sb.toString(); } // http://www.google.com/search?client=safari&rls=en&q=The+week+renewal+add+a+friend&ie=UTF-8&oe=UTF-8 public void addNewSitePatterns(SitePatterns addPatterns) { // todo need to implement for a variable number of partitions } public String getOperatorName() { return OPERATOR_NAME; } public double doOperation() { // Select boundary to update, 0 => btw partition 0 and 1, 1 => btw partition 1 and 2, etc. int whichBoundary = MathUtils.nextInt(breakPoints.getDimension()); int cBreakPt = (int) breakPoints.getParameterValue(whichBoundary); SitePatterns left = partitions.get(whichBoundary); SitePatterns right = partitions.get(whichBoundary + 1); int min = left.getFrom(); int max = right.getTo(); int pBreakPt = min; while (pBreakPt <= min || pBreakPt >= max) { // cBreakPt + [windowSize-1, windowSize+1] (and not 0) if (MathUtils.nextBoolean()) pBreakPt = cBreakPt + MathUtils.nextInt(windowSize) + 1; else pBreakPt = cBreakPt - MathUtils.nextInt(windowSize) - 1; } return 0; } public double getCoercableParameter() { return Math.log(windowSize); } public void setCoercableParameter(double value) { windowSize = (int) Math.exp(value); } public double getRawParameter() { return windowSize; } // public int getMode() { // return mode; // } public static boolean arePartitionsContiguous(List<SitePatterns> list) { int current = -1; int index = 0; for (SitePatterns patterns : list) { int start = patterns.getFrom(); int end = patterns.getTo(); /* System.err.println(start+" -> "+end+" : "+patterns.getSiteCount()+" "+patterns.getPatternCount()); int[] data = patterns.getSitePattern(0); System.err.print("Data 0:"); for (int i : data) System.err.print(" "+i); System.err.println("");*/ // if (current == -1) // current = end; if (current != -1 && start != (current + 1)) // throw new NonContiguousPartitionsException("Partition #"+0+" does not start contiguously"); return false; current = end; } return true; } public double getTargetAcceptanceProbability() { return 0.234; } public double getMinimumAcceptanceLevel() { return 0.1; } public double getMaximumAcceptanceLevel() { return 0.4; } public double getMinimumGoodAcceptanceLevel() { return 0.20; } public double getMaximumGoodAcceptanceLevel() { return 0.30; } // public int getWeight() { // return weight; // } // public void setWeight(int w) { // weight = w; // } public final String getPerformanceSuggestion() { double prob = MCMCOperator.Utils.getAcceptanceProbability(this); double targetProb = getTargetAcceptanceProbability(); double ws = OperatorUtils.optimizeWindowSize(windowSize, totalAlignmentLength, prob, targetProb); if (prob < getMinimumGoodAcceptanceLevel()) { return "Try decreasing windowSize to about " + ws; } else if (prob > getMaximumGoodAcceptanceLevel()) { return "Try increasing windowSize to about " + ws; } else return ""; } public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return OPERATOR_NAME; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { // int mode = CoercableMCMCOperator.DEFAULT; // if (xo.hasAttribute(AUTO_OPTIMIZE)) { // if (xo.getBooleanAttribute(AUTO_OPTIMIZE)) { // mode = CoercableMCMCOperator.COERCION_ON; // } else { // mode = CoercableMCMCOperator.COERCION_OFF; // } // } CoercionMode mode = CoercionMode.parseMode(xo); int weight = xo.getIntegerAttribute(WEIGHT); int windowSize = xo.getIntegerAttribute(WINDOW_SIZE); List<SitePatterns> list = new ArrayList<SitePatterns>(); final int numChild = xo.getChildCount(); for (int i = 0; i < numChild; i++) { Object obj = xo.getChild(i); if (obj instanceof SitePatterns) { // System.err.println("Found: "+((SitePatterns)obj).getId()) ; list.add((SitePatterns) obj); } } if (!arePartitionsContiguous(list)) throw new XMLParseException("Only contiguous partitions are allowed"); // Set current breakpoints int dim = list.size() - 1; XMLObject cxo = xo.getChild(BREAK_POINTS); Parameter breakPoints = new Parameter.Default(dim); ParameterParser.replaceParameter(cxo, breakPoints); breakPoints.setDimension(dim); for (int index = 0; index < dim; index++) breakPoints.setParameterValueQuietly(index, list.get(index + 1).getFrom()); // Parameter parameter = (Parameter)xo.getChild(Parameter.class); return new SlidingPatternsOperator(list, breakPoints, windowSize, weight, mode); } //************************************************************************ // AbstractXMLObjectParser implementation //************************************************************************ public String getParserDescription() { return "This element returns a sliding window operator on alignment sites."; } public Class getReturnType() { return MCMCOperator.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { AttributeRule.newIntegerRule(WINDOW_SIZE), AttributeRule.newIntegerRule(WEIGHT), AttributeRule.newBooleanRule(AUTO_OPTIMIZE, true), new ElementRule(BREAK_POINTS, Parameter.class), new ElementRule(SitePatterns.class, 2, 100) // todo fix hard-coded 100 }; }; private int totalAlignmentLength; private final List<SitePatterns> partitions; private int windowSize = 10; // private int mode = CoercableMCMCOperator.DEFAULT; // private int weight = 1; private final Parameter breakPoints; }