/*
* SimpleOperatorSchedule.java
*
* Copyright (C) 2002-2006 Alexei Drummond and Andrew Rambaut
*
* 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.operators;
import dr.inference.loggers.LogColumn;
import dr.inference.loggers.Loggable;
import dr.inference.loggers.NumberColumn;
import dr.math.MathUtils;
import java.util.List;
import java.util.Vector;
/**
* This class implements a simple operator schedule.
*
* @author Alexei Drummond
* @version $Id: SimpleOperatorSchedule.java,v 1.5 2005/06/14 10:40:34 rambaut Exp $
*/
public class SimpleOperatorSchedule implements OperatorSchedule, Loggable {
List<MCMCOperator> operators = null;
double totalWeight = 0;
int current = 0;
boolean sequential = false;
int optimizationSchedule = OperatorSchedule.DEFAULT_SCHEDULE;
public SimpleOperatorSchedule() {
operators = new Vector<MCMCOperator>();
}
public void addOperators(List<MCMCOperator> operators) {
for (MCMCOperator operator : operators) {
operators.add(operator);
totalWeight += operator.getWeight();
}
}
public void operatorsHasBeenUpdated() {
totalWeight = 0.0;
for (MCMCOperator operator : operators) {
totalWeight += operator.getWeight();
}
}
public void addOperator(MCMCOperator op) {
operators.add(op);
totalWeight += op.getWeight();
}
public double getWeight(int index) {
return operators.get(index).getWeight();
}
public int getNextOperatorIndex() {
if (sequential) {
int index = getWeightedOperatorIndex(current);
current += 1;
if (current >= totalWeight) {
current = 0;
}
return index;
}
final double v = MathUtils.nextDouble();
//System.err.println("v=" + v);
return getWeightedOperatorIndex(v * totalWeight);
}
public void setSequential(boolean seq) {
sequential = seq;
}
private int getWeightedOperatorIndex(double q) {
int index = 0;
double weight = getWeight(index);
while (weight <= q) {
index += 1;
weight += getWeight(index);
}
return index;
}
public MCMCOperator getOperator(int index) {
return operators.get(index);
}
public int getOperatorCount() {
return operators.size();
}
public double getOptimizationTransform(double d) {
switch( optimizationSchedule ) {
case LOG_SCHEDULE: return Math.log(d);
case SQRT_SCHEDULE: return Math.sqrt(d);
}
return d;
}
public void setOptimizationSchedule(int schedule) {
optimizationSchedule = schedule;
}
public int getMinimumAcceptAndRejectCount() {
int minCount = Integer.MAX_VALUE;
for( MCMCOperator op : operators ) {
if( op.getAcceptCount() < minCount || op.getRejectCount() < minCount ) {
minCount = op.getCount();
}
}
return minCount;
}
// **************************************************************
// Loggable IMPLEMENTATION
// **************************************************************
/**
* @return the log columns.
*/
public LogColumn[] getColumns() {
LogColumn[] columns = new LogColumn[getOperatorCount()];
for (int i = 0; i < getOperatorCount(); i++) {
MCMCOperator op = getOperator(i);
columns[i] = new OperatorColumn(op.getOperatorName(), op);
}
return columns;
}
private class OperatorColumn extends NumberColumn {
private final MCMCOperator op;
public OperatorColumn(String label, MCMCOperator op) {
super(label);
this.op = op;
}
public double getDoubleValue() {
return MCMCOperator.Utils.getAcceptanceProbability(op);
}
}
}