package edu.stanford.nlp.stats; import java.util.Random; /** * Represents a Gamma distribution. The way that samples are drawn is * stolen from Yee Whye Teh's code. It won't give the probability of a variable because * gamma is a continuous distribution. should it give the mass at that point? * * @author Jenny Finkel */ public class Gamma implements ProbabilityDistribution<Double> { /** * */ private static final long serialVersionUID = -2992079318379176178L; public final double alpha; public Gamma(double alpha) { this.alpha = alpha; } public Double drawSample(Random random) { return drawSample(random, alpha); } public static Double drawSample(Random random, double alpha) { if (alpha <= 0.0) { /* Not well defined, set to zero and skip. */ return 0.0; } else if ( alpha == 1.0 ) { /* Exponential */ return -Math.log(Math.random()); } else if (alpha < 1.0) { /* Use Johnks generator */ double cc = 1.0 / alpha; double dd = 1.0 / (1.0-alpha); while (true) { double xx = Math.pow(Math.random(), cc); double yy = xx + Math.pow(Math.random(), dd); if (yy <= 1.0) { return -Math.log(Math.random()) * xx / yy; } } } else { /* Use bests algorithm */ double bb = alpha - 1.0; double cc = 3.0 * alpha - 0.75; while (true) { double uu = Math.random(); double vv = Math.random(); double ww = uu * (1.0 - uu); double yy = Math.sqrt(cc / ww) * (uu - 0.5); double xx = bb + yy; if (xx >= 0) { double zz = 64.0 * ww * ww * ww * vv * vv; if ( ( zz <= (1.0 - 2.0 * yy * yy / xx) ) || ( Math.log(zz) <= 2.0 * (bb * Math.log(xx / bb) - yy) ) ) { return xx; } } } } } // Generalized Random sampling. public static double drawSample(Random r, double a, double b) { return drawSample(r,a)*b; } public double probabilityOf(Double x) { return 0.0; // cos its not discrete } public double logProbabilityOf(Double x) { return 0.0; // cos its not discrete } @Override public int hashCode() { return (new Double(alpha)).hashCode(); } @Override public boolean equals(Object o) { if (!(o instanceof Gamma)) { return false; } return ((Gamma)o).alpha == alpha; } }