/*
* CenteredScaleOperator.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.operators;
import dr.inference.model.Parameter;
import dr.math.MathUtils;
/**
* A generic operator for use with a sum-constrained vector parameter.
*
* @author Alexei Drummond
* @version $Id: CenteredScaleOperator.java,v 1.20 2005/06/14 10:40:34 rambaut Exp $
*/
// AR - I don't see how this can work...
@Deprecated
public class CenteredScaleOperator extends AbstractCoercableOperator {
public CenteredScaleOperator(Parameter parameter) {
super(CoercionMode.DEFAULT);
this.parameter = parameter;
}
public CenteredScaleOperator(Parameter parameter, double scale, int weight, CoercionMode mode) {
super(mode);
this.parameter = parameter;
this.scaleFactor = scale;
setWeight(weight);
}
/**
* @return the parameter this operator acts on.
*/
public Parameter getParameter() {
return parameter;
}
/**
* Change the parameter and return the hastings ratio.
* Performs a centered scale operation on the vector
* and returns the hastings ratio.
* This operator changes the variance but maintains the order
* of the scalars.
*/
public final double doOperation() {
double total = 0.0;
for (int i = 0; i < parameter.getDimension(); i++) {
total += parameter.getParameterValue(i);
}
double mean = total / parameter.getDimension();
double scaleFactor = getRandomScaleFactor();
double logq = parameter.getDimension() * Math.log(1.0 / scaleFactor);
for (int i = 0; i < parameter.getDimension(); i++) {
double newScalar = (parameter.getParameterValue(i) - mean) * scaleFactor + mean;
if (newScalar < parameter.getBounds().getLowerLimit(i) || newScalar > parameter.getBounds().getUpperLimit(i)) {
// throw new OperatorFailedException("Proposed value out of bounds");
return Double.NEGATIVE_INFINITY;
}
parameter.setParameterValue(i, newScalar);
}
// non-symmetrical move
return logq;
}
public final double getRandomScaleFactor() {
return scaleFactor + (MathUtils.nextDouble() * ((1 / scaleFactor) - scaleFactor));
}
// Interface MCMCOperator
public final String getOperatorName() {
return parameter.getParameterName();
}
public double getCoercableParameter() {
return Math.log(1.0 / scaleFactor - 1.0);
}
public void setCoercableParameter(double value) {
scaleFactor = 1.0 / (Math.exp(value) + 1.0);
}
public double getRawParameter() {
return scaleFactor;
}
public double getTargetAcceptanceProbability() {
return 0.234;
}
public final String getPerformanceSuggestion() {
double prob = MCMCOperator.Utils.getAcceptanceProbability(this);
double targetProb = getTargetAcceptanceProbability();
dr.util.NumberFormatter formatter = new dr.util.NumberFormatter(5);
double sf = OperatorUtils.optimizeScaleFactor(scaleFactor, prob, targetProb);
if (prob < getMinimumGoodAcceptanceLevel()) {
return "Try setting scaleFactor to about " + formatter.format(sf);
} else if (prob > getMaximumGoodAcceptanceLevel()) {
return "Try setting scaleFactor to about " + formatter.format(sf);
} else return "";
}
public String toString() {
return getOperatorName() + "(scaleFactor=" + scaleFactor + ")";
}
// Private instance variables
private Parameter parameter = null;
public double scaleFactor = 0.5;
}