/* * MonotonicStatistic.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.model; import dr.xml.*; import java.util.ArrayList; /** * A class that returns a log likelihood of a series of statistics. * If all the statistics are in increasing (decreasing) order then it returns 0.0 otherwise -INF. * * @author Marc Suchard */ public class MonotonicStatistic extends BooleanStatistic { public static final String MONOTONIC_STATISTIC = "monotonicStatistic"; public static final String STRICTLY = "strictlyMonotic"; public static final String ORDER = "order"; public MonotonicStatistic(boolean strict, boolean increasing) { super(MONOTONIC_STATISTIC); this.strict = strict; this.increasing = increasing; } public int getDimension() { return 1; } public void addStatistic(Statistic stat) { dataList.add(stat); } public boolean getBoolean(int dim) { double currentValue; if (increasing) currentValue = Double.NEGATIVE_INFINITY; else currentValue = Double.POSITIVE_INFINITY; for (Statistic statistic : dataList) { for (int j = 0; j < statistic.getDimension(); j++) { final double newValue = statistic.getStatisticValue(j); if (strict) { if( (increasing && newValue <= currentValue) || (!increasing && newValue >= currentValue) ) return false; } else { // not strict if( (increasing && newValue < currentValue) || (!increasing && newValue > currentValue) ) return false; } currentValue = newValue; } } return true; } /** * Reads a distribution likelihood from a DOM Document element. */ public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return MONOTONIC_STATISTIC; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { boolean increasing = true; String order = xo.getAttribute(ORDER, "increasing"); if (order.compareToIgnoreCase("decreasing") == 0) increasing = false; boolean strictly = xo.getAttribute(STRICTLY, false); MonotonicStatistic monotonicStatistic = new MonotonicStatistic(strictly, increasing); for(int i=0; i<xo.getChildCount(); i++) { if (xo.getChild(i) instanceof Statistic) { monotonicStatistic.addStatistic((Statistic)xo.getChild(i)); } } return monotonicStatistic; } //************************************************************************ // AbstractXMLObjectParser implementation //************************************************************************ public String getParserDescription() { return ""; } public Class getReturnType() { return MonotonicStatistic.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[]{ AttributeRule.newStringRule(ORDER, true), AttributeRule.newBooleanRule(STRICTLY,true), new ElementRule(Statistic.class, 1, Integer.MAX_VALUE) }; }; private boolean strict; private boolean increasing; protected ArrayList<Statistic> dataList = new ArrayList<Statistic>(); }