/* * MixedDistributionLikelihood.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.distribution; import dr.inference.model.CompoundModel; import dr.inference.model.Likelihood; import dr.inference.model.Model; import dr.inference.model.Statistic; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * A class that returns the log likelihood of a multidimensional statistic * being distributed according to a mixture of parametric distributions, where * the distribution membership of each element is determined by a separate vector * of indices. * * @author Alexei Drummond * @version $Id: DistributionLikelihood.java,v 1.11 2005/05/25 09:35:28 rambaut Exp $ */ public class MixedDistributionLikelihood extends Likelihood.Abstract { public MixedDistributionLikelihood(ParametricDistributionModel[] distributions, Statistic data, Statistic indicators) { // Mixed Distribution Likelihood contains two distribution models, not necessarily constant. // To cater for that, they need to be returned as the "Model" of this likelyhood so that their state is correctly // restored when an operation involving their parameters fails. super(new CompoundModel("MixedDistributions")); final CompoundModel cm = (CompoundModel) this.getModel(); for (ParametricDistributionModel m : distributions) { cm.addModel(m); } this.distributions = distributions; this.data = data; this.indicators = indicators; if (indicators.getDimension() == data.getDimension() - 1) { impliedOne = true; } else if (indicators.getDimension() != data.getDimension()) { throw new IllegalArgumentException("Indicators length (" + indicators.getDimension() + ") != data length (" + data.getDimension() + ")"); } } // ************************************************************** // Likelihood IMPLEMENTATION // ************************************************************** /** * Calculate the log likelihood of the current state. * * @return the log likelihood. */ public final double calculateLogLikelihood() { double logL = 0.0; for (int j = 0; j < data.getDimension(); j++) { int index; if (impliedOne) { if (j == 0) { index = 1; } else { index = (int) indicators.getStatisticValue(j - 1); } } else { index = (int) indicators.getStatisticValue(j); } logL += distributions[index].logPdf(data.getStatisticValue(j)); } //System.err.println("mixed: " + logL); return logL; } /** * Overridden to always return false. */ protected boolean getLikelihoodKnown() { return false; } // ************************************************************** // XMLElement IMPLEMENTATION // ************************************************************** public Element createElement(Document d) { throw new RuntimeException("Not implemented yet!"); } private final ParametricDistributionModel[] distributions; private final Statistic data; private final Statistic indicators; private boolean impliedOne = false; public Model[] getUniqueModels() { Model[] m = new Model[distributions[0] == distributions[1] ? 1 : 2]; m[0] = distributions[0]; if (m.length > 1) m[1] = distributions[1]; return m; } }