package statalign.mcmc; import java.util.List; import java.util.ArrayList; import statalign.base.Tree; import statalign.mcmc.ParameterInterface; import statalign.mcmc.PriorDistribution; import statalign.mcmc.ProposalDistribution; import statalign.model.ext.plugins.StructAlign; import statalign.utils.GammaDistribution; import statalign.model.ext.plugins.structalign.StructAlignParameterInterface.*; public abstract class ContinuousPositiveParameterMove extends McmcMove { protected Tree tree = null; protected ProposalDistribution<Double> proposalDistribution; protected double oldpar; protected double oldll; protected double minValue = 0.0; protected double maxValue = Double.POSITIVE_INFINITY; // If the proposal takes the parameter below/above these values, // the move is rejected. public ContinuousPositiveParameterMove (McmcModule m, ParameterInterface p, PriorDistribution<Double> pr, ProposalDistribution<Double> prop, String n) { owner = m; param = p; prior = pr; name = n; proposalDistribution = prop; autoTune = true; } public void setMinValue(double x) { minValue = x; } public void setMaxValue(double x) { maxValue = x; } public void copyState(Object externalState) { if (externalState instanceof Tree) { if (tree == null) { tree = (Tree) externalState; } } else { throw new IllegalArgumentException("ContinuousPositiveParameterMove.copyState must take an argument of type Tree."); } oldpar = param.get(); oldll = owner.getLogLike(); } public double proposal(Object externalState) { if (externalState instanceof Tree) { if (tree == null) { tree = (Tree) externalState; } } else { throw new IllegalArgumentException("ContinuousPositiveParameterMove.proposal must take an argument of type Tree."); } proposalDistribution.updateProposal(proposalWidthControlVariable,param.get()); param.set(proposalDistribution.sample()); if (param.get() < minValue || param.get() > maxValue) { return(Double.NEGATIVE_INFINITY); } /** - log p(new | old) */ double logProposalDensity = -proposalDistribution.logDensity(param.get()); proposalDistribution.updateProposal(proposalWidthControlVariable,param.get()); /** + log p(old | new) */ logProposalDensity += proposalDistribution.logDensity(oldpar); return logProposalDensity; } public double logPriorDensity(Object externalState) { if (param.get() < minValue || param.get() > maxValue) { return(Double.NEGATIVE_INFINITY); } else { // return 0; double logDensity = prior.logDensityUnnormalised(param.get()); // Since we're only using this in ratios, there's no // need to compute the normalising constant, which is good, // because some priors may be improper. // NB be careful with this though -- an improper prior should // only be used if the posterior can be shown to be proper. return logDensity; } } public abstract void updateLikelihood(Object externalState); public void restoreState(Object externalState) { param.set(oldpar); owner.setLogLike(oldll); } public void updateProposal(double proposalWidthControlVariable, Double currentParam) { proposalDistribution.updateProposal(proposalWidthControlVariable, currentParam); } @Override public String getParameterString() { String s = "" + param.get(); return s; } }