package beast.evolution.tree.coalescent; import beast.core.Description; import beast.core.Input; import beast.core.Operator; import beast.core.parameter.BooleanParameter; import beast.core.parameter.RealParameter; import beast.math.distributions.ParametricDistribution; import beast.util.Randomizer; /** * @author Joseph Heled * Date: 2/03/2011 */ @Description("Sample values from a distribution") public class SampleOffValues extends Operator { final public Input<RealParameter> valuesInput = new Input<>("values", "vector of target values", Input.Validate.REQUIRED); final public Input<BooleanParameter> indicatorsInput = new Input<>("indicators", "Sample only entries which are 'off'"); final public Input<ParametricDistribution> distInput = new Input<>("dist", "distribution to sample from.", Input.Validate.REQUIRED); public final Input<Boolean> scaleAll = new Input<>("all", "if true, sample all off values in one go.", false); @Override public void initAndValidate() { } @Override public double proposal() { final BooleanParameter indicators = indicatorsInput.get(this); final RealParameter data = valuesInput.get(this); final ParametricDistribution distribution = distInput.get(); final int idim = indicators.getDimension(); final int offset = (data.getDimension() - 1) == idim ? 1 : 0; assert offset == 1 || data.getDimension() == idim : "" + idim + " (?+1) != " + data.getDimension(); double hr = Double.NEGATIVE_INFINITY; if( scaleAll.get() ) { for (int i = offset; i < idim; ++i) { if( !indicators.getValue(i-offset) ) { try { final double val = distribution.inverseCumulativeProbability(Randomizer.nextDouble()); hr += distribution.logDensity(data.getValue(i)); data.setValue(i, val); } catch (Exception e) { // some distributions fail on extreme values - currently gamma return Double.NEGATIVE_INFINITY; } } } } else { // available locations for direct sampling int[] loc = new int[idim]; int locIndex = 0; for (int i = 0; i < idim; ++i) { if( !indicators.getValue(i) ) { loc[locIndex] = i + offset; ++locIndex; } } if( locIndex > 0 ) { final int index = loc[Randomizer.nextInt(locIndex)]; try { final double val = distribution.inverseCumulativeProbability(Randomizer.nextDouble()); hr = distribution.logDensity(data.getValue(index)); data.setValue(index, val); } catch (Exception e) { // some distributions fail on extreme values - currently gamma return Double.NEGATIVE_INFINITY; //throw new OperatorFailedException(e.getMessage()); } } else { // no non-active indicators //return Double.NEGATIVE_INFINITY; } } return hr; } }