package beast.math.distributions; import org.apache.commons.math.MathException; import org.apache.commons.math.distribution.ContinuousDistribution; import org.apache.commons.math.distribution.Distribution; import beast.core.Description; import beast.core.Input; import beast.core.parameter.RealParameter; @Description("Inverse Gamma distribution, used as prior. for x>0 f(x; alpha, beta) = \frac{beta^alpha}{Gamma(alpha)} (1/x)^{alpha + 1}exp(-beta/x) " + "If the input x is a multidimensional parameter, each of the dimensions is considered as a " + "separate independent component.") public class InverseGamma extends ParametricDistribution { final public Input<RealParameter> alphaInput = new Input<>("alpha", "shape parameter, defaults to 2"); final public Input<RealParameter> betaInput = new Input<>("beta", "scale parameter, defaults to 2"); InverseGammaImpl dist = new InverseGammaImpl(2, 2); @Override public void initAndValidate() { refresh(); } /** * ensure internal state is up to date * */ void refresh() { double alpha; double beta; if (alphaInput.get() == null) { alpha = 2; } else { alpha = alphaInput.get().getValue(); } if (betaInput.get() == null) { beta = 2; } else { beta = betaInput.get().getValue(); } dist.setAlphaBeta(alpha, beta); } @Override public Distribution getDistribution() { refresh(); return dist; } class InverseGammaImpl implements ContinuousDistribution { double m_fAlpha; double m_fBeta; // log of the constant beta^alpha/Gamma(alpha) double C; InverseGammaImpl(double alpha, double beta) { setAlphaBeta(alpha, beta); } void setAlphaBeta(double alpha, double beta) { m_fAlpha = alpha; m_fBeta = beta; C = m_fAlpha * Math.log(m_fBeta) - org.apache.commons.math.special.Gamma.logGamma(m_fAlpha); } @Override public double cumulativeProbability(double x) throws MathException { throw new MathException("Not implemented yet"); } @Override public double cumulativeProbability(double x0, double x1) throws MathException { throw new MathException("Not implemented yet"); } @Override public double inverseCumulativeProbability(double p) throws MathException { throw new MathException("Not implemented yet"); } @Override public double density(double x) { double logP = logDensity(x); return Math.exp(logP); } @Override public double logDensity(double x) { double logP = -(m_fAlpha + 1.0) * Math.log(x) - (m_fBeta / x) + C; return logP; } } // class OneOnXImpl @Override public double getMean() { return betaInput.get().getValue() / (alphaInput.get().getValue() - 1.0); } } // class InverseGamma