package uk.ac.imperial.simelec; import cern.jet.random.Uniform; import cern.jet.random.engine.MersenneTwister; import cern.jet.random.engine.RandomEngine; /** * Describes a discrete probability density function. * * @author James Keirstead * */ public class DiscretePDF { // Member fields private double[] values; /** * Creates a new DiscretePDF with a given set of values. If negative values * are contained in <code>values</code> array, these will be replaced with * zeros. * * @param values an array of non-negative values */ public DiscretePDF(double[] values) { this.values = new double[values.length]; for (int i=0; i<values.length; i++) { this.values[i] = values[i]<0 ? 0 : values[i]; } this.normalize(); } /** * Normalizes the values in this DiscretePDF so that their sum * equals one. * */ protected void normalize() { double sum = this.sum(); // Do the normalization for (int i = 0; i<values.length; i++) { values[i] = values[i]/sum; } } /** * Gets the cumulative distribution of this DiscretePDF. * * @return a vector of float values giving the cumulative distribution */ public double[] getCDF() { // Create a placeholder double[] cumdist = new double[values.length]; // Calculate the sum double prev = 0; for (int i = 0; i < cumdist.length; i++) { cumdist[i] = prev + values[i]; prev = cumdist[i]; } return (cumdist); } /** * Draw from this DiscretePDF. * * @return an integer giving the index of the selected interval */ public int getRandomIndex() { if (this.sum()!=1f) { this.normalize(); } // Draw a random value value float rand = (float) Uniform.staticNextDouble(); // Initialize the loop int interval = 0; double[] cumdist = this.getCDF(); do { if (rand <= cumdist[interval]) break; interval++; } while (interval < values.length); return interval; } /** * Calculate the sum of this DiscretePDF * * @return a float */ private double sum() { double sum = 0; for (double v : values) { sum = sum + v; } return sum; } /** * Get the values describing this DiscretePDF * * @return an array of double */ public double[] getValues() { return values; } /** * Sets the seed for the random number generator. * * @param seed * an int giving the seed */ public static void setSeed(int seed) { RandomEngine engine = new MersenneTwister(seed); Uniform.staticSetRandomEngine(engine); } }