/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.probdist; import umontreal.iro.lecuyer.util.RootFinder; import umontreal.iro.lecuyer.functions.MathFunction; /** * The Pascal distribution is a special case of the * negative binomial distribution with * parameters n and p, where n is a positive * integer and * 0 <= p <= 1. * Its mass function is *

*

*
* p(x) = nCr(n + x - 1, x)pn(1 - p)x,        for x = 0, 1, 2,… *

* where nCr is defined in {@link BinomialDist}. * This p(x) can be interpreted as the probability of having x failures * before the nth success in a sequence of independent Bernoulli trials * with probability of success p. * For n = 1, this gives the geometric distribution. * */ public class PascalDist extends NegativeBinomialDist { private int n; private static final double EPSI = 1.0E-10; private static class Function implements MathFunction { protected int m; protected int max; protected double mean; protected int[] Fj; public Function (int m, int max, double mean, int[] Fj) { this.m = m; this.max = max; this.mean = mean; this.Fj = new int[Fj.length]; System.arraycopy(Fj, 0, this.Fj, 0, Fj.length); } public double evaluate (double p) { double sum = 0.0; double s = (p * mean) / (1.0 - p); for (int j = 0; j < max; j++) sum += Fj[j] / (s + (double) j); return sum + m * Math.log (p); } public double evaluateN (int n, double p) { double sum = 0.0; for (int j = 0; j < max; j++) sum += Fj[j] / (n + j); return sum + m * Math.log (p); } } /** * Creates an object that contains the probability * terms and the distribution function for * the Pascal distribution with parameter n and p. * */ public PascalDist (int n, double p) { setParams (n, p); } /** * Estimates the parameter (n, p) of the Pascal distribution * using the maximum likelihood method, from the m observations * x[i], * i = 0, 1,…, m - 1. The estimates are returned in a two-element * array, in regular order: [n, p]. * * @param x the list of observations used to evaluate parameters * * @param m the number of observations used to evaluate parameters * * @return returns the parameters [hat(n), hat(p)] * */ public static double[] getMLE (int[] x, int m) { if (m <= 0) throw new IllegalArgumentException ("m <= 0"); double sum = 0.0; int max = Integer.MIN_VALUE; for (int i = 0; i < m; i++) { sum += x[i]; if (x[i] > max) max = x[i]; } double mean = (double) sum / (double) m; double var = 0.0; for (int i = 0; i < m; i++) var += (x[i] - mean) * (x[i] - mean); var /= (double) m; if (mean >= var) throw new UnsupportedOperationException("mean >= variance"); int[] Fj = new int[max]; for (int j = 0; j < max; j++) { int prop = 0; for (int i = 0; i < m; i++) if (x[i] > j) prop++; Fj[j] = prop; } double[] parameters = new double[2]; Function f = new Function (m, max, mean, Fj); parameters[1] = RootFinder.brentDekker (EPSI, 1 - EPSI, f, 1e-5); if (parameters[1] >= 1.0) parameters[1] = 1.0 - 1e-15; parameters[0] = Math.round ((parameters[1] * mean) / (1.0 - parameters[1])); if(parameters[0] == 0) parameters[0] = 1; return parameters; } /** * Creates a new instance of a Pascal distribution with parameters n and * p estimated using the maximum likelihood method based on the m * observations x[i], * i = 0, 1,…, m - 1. * * @param x the list of observations to use to evaluate parameters * * @param m the number of observations to use to evaluate parameters * * */ public static PascalDist getInstanceFromMLE (int[] x, int m) { double parameters[] = getMLE (x, m); return new PascalDist ((int) parameters[0], parameters[1]); } /** * Returns the parameter n of this object. * */ public int getN() { return n; } /** * Sets the parameter n and p of this object. * */ public void setParams (int n, double p) { setParams ((double) n, p); this.n = n; } /** * Return a table containing the parameters of the current distribution. * This table is put in regular order: [n, p]. * * */ public double[] getParams () { double[] retour = {n, p}; return retour; } public String toString () { return super.toString(); } }

Ads help maintain this website.