package beast.evolution.operators;
import beast.core.Description;
import beast.core.Input;
import beast.core.Input.Validate;
import beast.core.Operator;
import beast.core.parameter.IntegerParameter;
import beast.util.Randomizer;
@Description("A random walk operator that selects a random dimension of the integer parameter and perturbs the value a " +
"random amount within +/- windowSize.")
public class IntRandomWalkOperator extends Operator {
final public Input<Integer> windowSizeInput =
new Input<>("windowSize", "the size of the window both up and down", Validate.REQUIRED);
final public Input<IntegerParameter> parameterInput =
new Input<>("parameter", "the parameter to operate a random walk on.", Validate.REQUIRED);
int windowSize = 1;
@Override
public void initAndValidate() {
windowSize = windowSizeInput.get();
}
/**
* override this for proposals,
* returns log of hastingRatio, or Double.NEGATIVE_INFINITY if proposal should not be accepted *
*/
@Override
public double proposal() {
final IntegerParameter param = parameterInput.get(this);
final int i = Randomizer.nextInt(param.getDimension());
final int value = param.getValue(i);
final int newValue = value + Randomizer.nextInt(2 * windowSize + 1) - windowSize;
if (newValue < param.getLower() || newValue > param.getUpper()) {
// invalid move, can be rejected immediately
return Double.NEGATIVE_INFINITY;
}
if (newValue == value) {
// this saves calculating the posterior
return Double.NEGATIVE_INFINITY;
}
param.setValue(i, newValue);
return 0.0;
}
@Override
public void optimize(final double logAlpha) {
// nothing to optimise
}
} // class IntRandomWalkOperator