/* * File Distribution.java * * Copyright (C) 2010 Remco Bouckaert remco@cs.auckland.ac.nz * * 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.core; import java.io.PrintStream; import java.util.List; import java.util.Random; @Description("Probabilistic representation that can produce " + "a log probability for instance for running an MCMC chain.") public abstract class Distribution extends CalculationNode implements Loggable, Function { /** * current and stored log probability/log likelihood/log distribution * */ protected double logP = Double.NaN; protected double storedLogP = Double.NaN; /** * @return the normalised probability (density) for this distribution. * Note that some efficiency can be gained by testing whether the * Distribution is dirty, and if not, call getCurrentLogP() instead * of recalculating. */ public double calculateLogP() { logP = 0; return logP; } /** The beastObject implements f( arguments | conditionals) **/ /** * @return a list of unique ids for the state nodes that form the argument */ public abstract List<String> getArguments(); /** * @return a list of unique ids for the state nodes that make up the conditions */ public abstract List<String> getConditions(); /** * This method draws new values for the arguments conditional on the current value(s) of the conditionals. * <p/> * The new values are overwrite the argument values in the provided state. * * @param state the state * @param random random number generator */ public abstract void sample(State state, Random random); /** * get result from last known calculation, useful for logging * * @return log probability */ public double getCurrentLogP() { return logP; } @Override public void initAndValidate() { // nothing to do } /** * CalculationNode methods * */ @Override public void store() { storedLogP = logP; super.store(); } @Override public void restore() { logP = storedLogP; super.restore(); } /** * Loggable interface implementation follows * */ @Override public void init(final PrintStream out) { out.print(getID() + "\t"); } @Override public void log(final int sample, final PrintStream out) { out.print(getCurrentLogP() + "\t"); } @Override public void close(final PrintStream out) { // nothing to do } /** * Valuable interface implementation follows * */ @Override public int getDimension() { return 1; } @Override public double getArrayValue() { return logP; } @Override public double getArrayValue(final int dim) { if (dim == 0) return getArrayValue(); return 0; } /** * Intended to be overridden by stochastically estimated distributions. * Used to disable target distribution consistency checks implemented in * the MCMC class which do not apply to stochastic distributions. * * @return true if stochastic. */ public boolean isStochastic() { return false; } /** * Return non-stochastic part of a distribution recalculate, if required. * This can be used for debugging purposes to verify that the non-stochastic * part of a distribution is calculated correctly e.g. inside the MCMC loop * * @return logP if not stochastic, zero otherwise */ public double getNonStochasticLogP() { if (isStochastic()) { return 0; } else { if (isDirtyCalculation()) { return calculateLogP(); } else { return getCurrentLogP(); } } } } // class Distribution