/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.probdistmulti; import umontreal.iro.lecuyer.util.Num; /** * Implements the abstract class {@link DiscreteDistributionIntMulti} for the * multinomial distribution with parameters n and * (p1, ...,pd). * The probability mass function is * *

*
* P[X = (x1,..., xd)] = n!∏i=1dpixi/(∏i=1dxi!), *

* where * ∑i=1dxi = n and * ∑i=1dpi = 1. * */ public class MultinomialDist extends DiscreteDistributionIntMulti { protected int n; protected double p[]; /** * Creates a MultinomialDist object with parameters n and * (p1,...,pd) such that * ∑i=1dpi = 1. We have * pi = p[i-1]. * */ public MultinomialDist (int n, double p[]) { setParams (n, p); } public double prob (int x[]) { return prob_ (n, p, x); } public double cdf (int x[]) { return cdf_ (n, p, x); } public double[] getMean() { return getMean_ (n, p); } public double[][] getCovariance() { return getCovariance_ (n, p); } public double[][] getCorrelation () { return getCorrelation_ (n, p); } private static void verifParam(int n, double p[]) { double sumPi = 0.0; if (n <= 0) throw new IllegalArgumentException ("n <= 0"); for (int i = 0; i < p.length; i++) { if ((p[i] < 0) || (p[i] > 1)) throw new IllegalArgumentException("p is not a probability vector"); sumPi += p[i]; } if (sumPi != 1.0) throw new IllegalArgumentException ("p is not a probability vector"); } private static double prob_ (int n, double p[], int x[]) { double sumXFact = 0.0; int sumX = 0; double sumPX = 0.0; if (x.length != p.length) throw new IllegalArgumentException ("x and p must have the same dimension"); for (int i = 0; i < p.length; i++) { sumX += x[i]; sumXFact += Num.lnFactorial (x[i]); sumPX += (x[i] * Math.log (p[i])); } if (sumX != n) return 0.0; else { return Math.exp (Num.lnFactorial (n) - sumXFact + sumPX); } } /** * Computes the probability mass function * of the multinomial distribution with parameters n and * (p1,...,pd) evaluated at x. * */ public static double prob (int n, double p[], int x[]) { verifParam (n, p); return prob_ (n, p, x); } private static double cdf_ (int n, double p[], int x[]) { boolean end = false; double sum = 0.0; int j; if (x.length != p.length) throw new IllegalArgumentException ("x and p must have the same dimension"); int is[] = new int[x.length]; for (int i = 0; i < is.length; i++) is[i] = 0; sum = 0.0; while (! end) { sum += prob (n, p, is); is[0]++; if (is[0] > x[0]) { is[0] = 0; j = 1; while (j < x.length && is[j] == x[j]) is[j++] = 0; if (j == x.length) end = true; else is[j]++; } } return sum; } /** * Computes the function F of the multinomial distribution with * parameters n and (p1,...,pd) evaluated at x. * */ public static double cdf (int n, double p[], int x[]) { verifParam (n, p); return cdf_ (n, p, x); } private static double[] getMean_ (int n, double[] p) { double mean[] = new double[p.length]; for (int i = 0; i < p.length; i++) mean[i] = n * p[i]; return mean; } /** * Computes the mean * E[Xi] = npi of the multinomial distribution * with parameters n and (p1,...,pd). * */ public static double[] getMean (int n, double[] p) { verifParam (n, p); return getMean_ (n, p); } private static double[][] getCovariance_ (int n, double[] p) { double cov[][] = new double[p.length][p.length]; for (int i = 0; i < p.length; i++) { for (int j = 0; j < p.length; j++) cov[i][j] = -n * p[i] * p[j]; cov[i][i] = n * p[i] * (1.0 - p[i]); } return cov; } /** * Computes the covariance matrix of the multinomial distribution * with parameters n and (p1,...,pd). * */ public static double[][] getCovariance (int n, double[] p) { verifParam (n, p); return getCovariance_ (n, p); } private static double[][] getCorrelation_ (int n, double[] p) { double corr[][] = new double[p.length][p.length]; for (int i = 0; i < p.length; i++) { for (int j = 0; j < p.length; j++) corr[i][j] = -Math.sqrt(p[i] * p[j] / ((1.0 - p[i]) * (1.0 - p[j]))); corr[i][i] = 1.0; } return corr; } /** * Computes the correlation matrix of the multinomial distribution * with parameters n and (p1,...,pd). * */ public static double[][] getCorrelation (int n, double[] p) { verifParam (n, p); return getCorrelation_ (n, p); } /** * It is now called getMLE. * */ @Deprecated public static double[] getMaximumLikelihoodEstimate (int x[][], int m, int d, int n) { return getMLE(x, m, d, n); } /** * Estimates and returns the parameters [hat(p_i),...,hat(p_d)] of the * multinomial distribution using the maximum likelihood method. It uses the m * observations of d components in table x[i][j], * i = 0, 1,…, m - 1 * and * j = 0, 1,…, d - 1. * * @param x the list of observations used to evaluate parameters * * @param m the number of observations used to evaluate parameters * * @param d the dimension of each observation * * @param n the number of independant trials for each series * * @return returns the parameters [hat(p_i),...,hat(p_d)] * */ public static double[] getMLE (int x[][], int m, int d, int n) { double parameters[] = new double[d]; double xBar[] = new double[d]; double N = 0.0; if (m <= 0) throw new IllegalArgumentException ("m <= 0"); if (d <= 0) throw new IllegalArgumentException ("d <= 0"); for (int i = 0; i < d; i++) xBar[i] = 0; for (int v = 0; v < m; v++) for (int c = 0; c < d; c++) xBar[c] += x[v][c]; for (int i = 0; i < d; i++) { xBar[i] = xBar[i] / (double) n; N += xBar[i]; } if (N != (double) n) throw new IllegalArgumentException("n is not correct"); for (int i = 0; i < d; i++) parameters[i] = xBar[i] / (double) n; return parameters; } /** * Returns the parameter n of this object. * */ public int getN() { return n; } /** * Returns the parameters (p1,...,pd) of this object. * */ public double[] getP() { return p; } /** * Sets the parameters n and (p1,...,pd) of this object. * */ public void setParams (int n, double p[]) { double sumP = 0.0; if (n <= 0) throw new IllegalArgumentException ("n <= 0"); if (p.length < 2) throw new IllegalArgumentException ("p.length < 2"); this.n = n; this.dimension = p.length; this.p = new double[dimension]; for (int i = 0; i < dimension; i++) { if ((p[i] < 0) || (p[i] > 1)) throw new IllegalArgumentException("p is not a probability vector"); this.p[i] = p[i]; sumP += p[i]; } if (sumP != 1.0) throw new IllegalArgumentException ("p is not a probability vector"); } }

Ads help maintain this website.