package edu.umd.cloud9.example.clustering; import java.util.Random; public class UnivariateGaussianMixtureModel { public int size; public double[] weight; public int[] pos; public PVector[] param; /** * Class constructor. */ public UnivariateGaussianMixtureModel() { this.size = 0; } public void setSize(int n){ this.size = n; this.weight = new double[n]; this.param = new PVector[n]; this.pos = new int[n]; } public UnivariateGaussianMixtureModel(int n) { this.size = n; this.weight = new double[n]; this.param = new PVector[n]; this.pos = new int[n]; } /** * Computes the density value of this mixture value. * * @param x a point * @return density value of this mixture value */ public double density(Point x) { double cumul = 0.0d; for (int i = 0; i < this.size; i++) cumul += this.weight[i] * densityOfGaussian(x, this.param[i]); return cumul; } /** * Normalizes the weights of the mixture models \f$ \alpha_i \f$ such as \f$ \sum_{i=1}^n \alpha_i * = 1 \f$. */ public void normalizeWeights() { double sum = 0; int i; for (i = 0; i < this.size; i++) sum += this.weight[i]; for (i = 0; i < this.size; i++) this.weight[i] /= sum; } /** * Method toString. * * @return string describing the mixture model */ public String toString() { String output = String.format("Mixture containing %d components\n", size); for (int i = 0; i < this.size; i++) { output += String.format(" Component %4d: ", pos[i]); output += String.format("Weight = %8.6f ", weight[i]); output += String.format("Parameters = %s\n", param[i]); } return output; } /** * Creates and returns a copy of the instance. * * @return a clone of the instance */ public UnivariateGaussianMixtureModel clone() { UnivariateGaussianMixtureModel mm = new UnivariateGaussianMixtureModel(this.size); mm.weight = this.weight.clone(); mm.pos = this.pos.clone(); for (int i = 0; i < this.size; i++) mm.param[i] = (PVector) this.param[i].clone(); return mm; } /** * Return the dimension of the parameters of the mixture model. * * @return parameters's dimension */ public int getDimension() { return this.param[0].getDimension(); } /** * Draws points from the considered mixture model. * * @param m number of points to draw * @return a point */ public Point[] drawRandomPoints(int m) { // Array of points Point[] points = new Point[m]; // Cumulative array int n = this.size; double[] t = new double[n]; double sum = 0; for (int i = 0; i < n; i++) { sum += this.weight[i]; t[i] = sum; } // Loop for (int i = 0; i < m; i++) { // Random number between 0 and 1 double r = Math.random(); // Find generative class int idx = 0; while (t[idx] < r && idx < n - 1) idx++; // Draw and return the point from the idx-th model points[i] = drawRandomPointFromGaussian(this.param[idx]); } return points; } /** * Computes the density value \f$ f(x;\mu,\sigma^2) \f$. * * @param x point * @param param parameters (source, natural, or expectation) * @return \f$ f(x;\mu,\sigma^2) = \frac{1}{ \sqrt{2\pi \sigma^2} } \exp \left( - * \frac{(x-\mu)^2}{ 2 \sigma^2} \right) \f$ */ public static double densityOfGaussian(Point x, PVector param) { return Math.exp(-(x.value - param.array[0]) * (x.value - param.array[0]) / (2.0d * param.array[1])) / (Math.sqrt(2.0d * Math.PI * param.array[1])); } /** * Draws a point from the considered distribution. * * @param L source parameters \f$ \mathbf{\Lambda} = ( \mu , \sigma^2 )\f$ * @return a point */ public static Point drawRandomPointFromGaussian(PVector L) { double mean = L.array[0]; double variance = L.array[1]; // Draw the point Random rand = new Random(); return new Point(mean + rand.nextGaussian() * Math.sqrt(variance)); } }