/*
* BayesianStochasticSearchVariableSelection.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 cern.colt.bitvector.BitVector;
import dr.math.MathUtils;
import dr.oldevomodel.substmodel.SubstitutionModel;
/**
* @author Marc Suchard
*/
public interface BayesianStochasticSearchVariableSelection {
public Parameter getIndicators();
public boolean validState();
public class Utils {
public static boolean connectedAndWellConditioned(double[] probability,
dr.evomodel.substmodel.SubstitutionModel substModel) {
if (probability == null) {
int stateCount = substModel.getDataType().getStateCount();
probability = new double[stateCount*stateCount];
}
try {
substModel.getTransitionProbabilities(defaultExpectedMutations,probability);
return connectedAndWellConditioned(probability);
} catch (Exception e) { // Any numerical error is bad news
return false;
}
}
public static boolean connectedAndWellConditioned(double[] probability,
SubstitutionModel substModel) {
if (probability == null) {
int stateCount = substModel.getDataType().getStateCount();
probability = new double[stateCount*stateCount];
}
try {
substModel.getTransitionProbabilities(defaultExpectedMutations,probability);
return connectedAndWellConditioned(probability);
} catch (Exception e) { // Any numerical error is bad news
return false;
}
}
public static boolean connectedAndWellConditioned(double[] probability) {
for(double prob : probability) {
if(prob < tolerance || prob >= 1.0) {
return false;
}
}
return true;
}
public static void randomize(Parameter indicators,int dim, boolean reversible) {
do {
for (int i = 0; i < indicators.getDimension(); i++)
indicators.setParameterValue(i,
(MathUtils.nextDouble() < 0.5) ? 0.0 : 1.0);
} while (!(isStronglyConnected(indicators.getParameterValues(),
dim, reversible)));
}
public static void setTolerance(double newTolerance) {
tolerance = newTolerance;
}
public static double getTolerance() {
return tolerance;
}
public static void setScalar(double newScalar) {
defaultExpectedMutations = newScalar;
}
public static double getScalar() {
return defaultExpectedMutations;
}
/* Determines if the graph is strongly connected, such that there exists
* a directed path from any vertex to any other vertex
*
*/
public static boolean isStronglyConnected(double[] indicatorValues, int dim, boolean reversible) {
BitVector visited = new BitVector(dim);
boolean connected = true;
for (int i = 0; i < dim && connected; i++) {
visited.clear();
depthFirstSearch(i, visited, indicatorValues, dim, reversible);
connected = visited.cardinality() == dim;
}
return connected;
}
private static boolean hasEdge(int i, int j, double[] indicatorValues,
int dim, boolean reversible) {
return i != j && indicatorValues[getEntry(i, j, dim, reversible)] == 1;
}
private static int getEntry(int i, int j, int dim, boolean reversible) {
if (reversible) {
if (j < i) {
return getEntry(j,i,dim,reversible);
}
int entry = i * dim - i * (i + 1) / 2 + j - 1 -i;
return entry;
}
int entry = i * (dim - 1) + j;
if (j > i)
entry--;
return entry;
}
private static void depthFirstSearch(int node, BitVector visited, double[] indicatorValues,
int dim, boolean reversible) {
visited.set(node);
for (int v = 0; v < dim; v++) {
if (hasEdge(node, v, indicatorValues, dim, reversible) && !visited.get(v))
depthFirstSearch(v, visited, indicatorValues, dim, reversible);
}
}
private static double defaultExpectedMutations = 1.0;
private static double tolerance = 1E-20;
}
}