/** Computes the probability <SPAN CLASS="MATH"><I>p</I>(<I>x</I>)</SPAN>. */ public static double prob(double n, double p, int x) { final int SLIM = 15; // To avoid overflow final double MAXEXP = (Num.DBL_MAX_EXP - 1) * Num.LN2; // To avoid overflow final double MINEXP = (Num.DBL_MIN_EXP - 1) * Num.LN2; // To avoid underflow double y; if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("p not in [0, 1]"); if (n <= 0.0) throw new IllegalArgumentException("n <= 0.0"); if (x < 0) return 0.0; if (p >= 1.0) { // In fact, p == 1 if (x == 0) return 1.0; else return 0.0; } if (p <= 0.0) // In fact, p == 0 return 0.0; y = Num.lnGamma(n + x) - (Num.lnFactorial(x) + Num.lnGamma(n)) + n * Math.log(p) + x * Math.log1p(-p); if (y >= MAXEXP) throw new IllegalArgumentException("term overflow"); return Math.exp(y); }
/** Computes the density function @f$f(x)@f$. */ public static double density(double alpha, double lambda, double x) { if (lambda <= 0) throw new IllegalArgumentException("lambda <= 0"); double z = lambda * (x - alpha); if (z >= -100.0) { double v = Math.exp(-z); return lambda * v / ((1.0 + v) * (1.0 + v)); } return lambda * Math.exp(z); }
/** * Estimates the parameters @f$(\alpha, \lambda)@f$ of the logistic distribution using the maximum * likelihood method, from the @f$n@f$ observations @f$x[i]@f$, @f$i = 0, 1,…, n-1@f$. The * estimates are returned in a two-element array, in regular order: [@f$\alpha@f$, * * @f$\lambda@f$]. The maximum likelihood estimators are the values * @f$(\hat{\alpha}, \hat{\lambda})@f$ that satisfy the equations: * @f{align*}{ \sum_{i=1}^n \frac{1}{1 + e^{\hat{\lambda} (x_i - \hat{\alpha})}} & = \frac{n}{2} * \\ \sum_{i=1}^n \hat{\lambda} (x_i - \hat{\alpha}) \frac{1 - e^{\hat{\lambda} (x_i - * \hat{\alpha})}}{1 + e^{\hat{\lambda} (x_i - \hat{\alpha})}} & = n. * @f} See @cite mEVA00a  (page 128). * @param x the list of observations used to evaluate parameters * @param n the number of observations used to evaluate parameters * @return returns the parameter [@f$\hat{\alpha}@f$, * @f$\hat{\lambda}@f$] */ public static double[] getMLE(double[] x, int n) { if (n <= 0) throw new IllegalArgumentException("n <= 0"); double sum = 0.0; for (int i = 0; i < n; i++) sum += x[i]; double[] param = new double[3]; param[1] = sum / (double) n; sum = 0.0; for (int i = 0; i < n; i++) sum += ((x[i] - param[1]) * (x[i] - param[1])); param[2] = Math.sqrt(Math.PI * Math.PI * n / (3.0 * sum)); double[] fvec = new double[3]; double[][] fjac = new double[3][3]; int[] iflag = new int[2]; int[] info = new int[2]; int[] ipvt = new int[3]; Optim system = new Optim(x, n); Minpack_f77.lmder1_f77(system, 2, 2, param, fvec, fjac, 1e-5, info, ipvt); double parameters[] = new double[2]; parameters[0] = param[1]; parameters[1] = param[2]; return parameters; }
public double evaluate(double gam) { if (gam <= 0) return 1.0e100; double sum = 0.0; for (int j = 0; j < m; j++) sum += Num.digamma(gam + x[j]); return sum / m + Math.log(p) - Num.digamma(gam); }
/** Computes the inverse distribution function @f$F^{-1}(u)@f$. */ public static double inverseF(double alpha, double lambda, double u) { if (lambda <= 0) throw new IllegalArgumentException("lambda <= 0"); if (u < 0.0 || u > 1.0) throw new IllegalArgumentException("u not in [0, 1]"); if (u >= 1.0) return Double.POSITIVE_INFINITY; if (u <= 0.0) return Double.NEGATIVE_INFINITY; return Math.log(u / (1.0 - u)) / lambda + alpha; }
public double evaluate(double s) { if (s <= 0) return 1.0e100; double sum = 0.0; double p = s / (s + mean); for (int j = 0; j < max; j++) sum += Fj[j] / (s + (double) j); return sum + m * Math.log(p); }
/** Computes the distribution function. */ public static double cdf(double n, double p, int x) { final double EPSILON = DiscreteDistributionInt.EPSILON; final int LIM1 = 100000; double sum, term, termmode; int i, mode; final double q = 1.0 - p; if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("p not in [0, 1]"); if (n <= 0.0) throw new IllegalArgumentException("n <= 0.0"); if (x < 0) return 0.0; if (p >= 1.0) // In fact, p == 1 return 1.0; if (p <= 0.0) // In fact, p == 0 return 0.0; // Compute the maximum term mode = 1 + (int) Math.floor((n * q - 1.0) / p); if (mode < 0) mode = 0; else if (mode > x) mode = x; if (mode <= LIM1) { sum = term = termmode = prob(n, p, mode); for (i = mode; i > 0; i--) { term *= i / (q * (n + i - 1.0)); if (term < EPSILON) break; sum += term; } term = termmode; for (i = mode; i < x; i++) { term *= q * (n + i) / (i + 1); if (term < EPSILON) break; sum += term; } if (sum <= 1.0) return sum; else return 1.0; } else // return 1.0 - BinomialDist.cdf (x + n, p, n - 1); return BetaDist.cdf(n, x + 1.0, 15, p); }
public void fcn(int m, int n, double[] x, double[] fvec, double[][] fjac, int iflag[]) { if (x[2] <= 0.0) { final double BIG = 1.0e100; fvec[1] = BIG; fvec[2] = BIG; fjac[1][1] = BIG; fjac[1][2] = 0.0; fjac[2][1] = 0.0; fjac[2][2] = BIG; return; } double sum; double prod; if (iflag[1] == 1) { sum = 0.0; for (int i = 0; i < n; i++) sum += (1.0 / (1.0 + Math.exp(x[2] * (xi[i] - x[1])))); fvec[1] = sum - n / 2.0; sum = 0.0; for (int i = 0; i < n; i++) { prod = x[2] * (xi[i] - x[1]); sum -= prod * Math.tanh(prod / 2.0); } fvec[2] = sum - n; } else if (iflag[1] == 2) { sum = 0.0; for (int i = 0; i < n; i++) { prod = Math.exp(x[2] * (xi[i] - x[1])); sum -= x[2] * prod / ((1 + prod) * (1 + prod)); } fjac[1][1] = sum; sum = 0.0; for (int i = 0; i < n; i++) { prod = Math.exp(x[2] * (xi[i] - x[1])); sum -= (xi[i] - x[1]) * prod / ((1 + prod) * (1 + prod)); } fjac[1][2] = sum; sum = 0.0; for (int i = 0; i < n; i++) { prod = Math.exp(x[2] * (xi[i] - x[1])); sum -= (x[2] * ((-1.0 + prod) * (1.0 + prod) - (2.0 * (x[2] * (xi[i] - x[1])) * prod))) / ((1.0 + prod) * (1.0 + prod)); } fjac[2][1] = sum; sum = 0.0; for (int i = 0; i < n; i++) { prod = Math.exp(x[2] * (xi[i] - x[1])); sum -= ((x[1] - xi[1]) * ((-1.0 + prod) * (1.0 + prod) - (2.0 * (x[2] * (xi[i] - x[1])) * prod))) / ((1.0 + prod) * (1.0 + prod)); } fjac[2][2] = sum; } }
/** * Computes and returns the standard deviation of the logistic distribution with * parameters @f$\alpha@f$ and @f$\lambda@f$. * * @return the standard deviation of the logistic distribution */ public static double getStandardDeviation(double alpha, double lambda) { if (lambda <= 0.0) throw new IllegalArgumentException("lambda <= 0"); return (Math.sqrt(1.0 / 3.0) * Math.PI / lambda); }
/** Computes the complementary distribution function @f$1-F(x)@f$. */ public static double barF(double alpha, double lambda, double x) { if (lambda <= 0) throw new IllegalArgumentException("lambda <= 0"); double z = lambda * (x - alpha); if (z <= 100.0) return 1.0 / (1.0 + Math.exp(z)); return Math.exp(-z); }
/** * Sets the parameter <SPAN CLASS="MATH"><I>n</I></SPAN> and <SPAN CLASS="MATH"><I>p</I></SPAN> of * this object. */ public void setParams(double n, double p) { /* * * Compute all probability terms of the negative binomial distribution; * start at the mode, and calculate probabilities on each side until they * become smaller than EPSILON. Set all others to 0. */ supportA = 0; int i, mode, Nmax; int imin, imax; double sum; double[] P; // Negative Binomial mass probabilities double[] F; // Negative Binomial cumulative if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("p not in [0, 1]"); if (n <= 0.0) throw new IllegalArgumentException("n <= 0"); this.n = n; this.p = p; // Compute the mode (at the maximum term) mode = 1 + (int) Math.floor((n * (1.0 - p) - 1.0) / p); /* * For mode > MAXN, we shall not use pre-computed arrays. mode < 0 should be impossible, unless overflow of long occur, in which case mode will be = LONG_MIN. */ if (mode < 0.0 || mode > MAXN) { pdf = null; cdf = null; return; } /* * In theory, the negative binomial distribution has an infinite range. But for i > Nmax, probabilities should be extremely small. Nmax = Mean + 16 * Standard deviation. */ Nmax = (int) (n * (1.0 - p) / p + 16 * Math.sqrt(n * (1.0 - p) / (p * p))); if (Nmax < 32) Nmax = 32; P = new double[1 + Nmax]; double epsilon = EPSILON / prob(n, p, mode); // We shall normalize by explicitly summing all terms >= epsilon sum = P[mode] = 1.0; // Start from the maximum and compute terms > epsilon on each side. i = mode; while (i > 0 && P[i] >= epsilon) { P[i - 1] = P[i] * i / ((1.0 - p) * (n + i - 1)); i--; sum += P[i]; } imin = i; i = mode; while (P[i] >= epsilon) { P[i + 1] = P[i] * (1.0 - p) * (n + i) / (i + 1); i++; sum += P[i]; if (i == Nmax - 1) { Nmax *= 2; double[] nT = new double[1 + Nmax]; System.arraycopy(P, 0, nT, 0, P.length); P = nT; } } imax = i; // Renormalize the sum of probabilities to 1 for (i = imin; i <= imax; i++) P[i] /= sum; // Compute the cumulative probabilities for F and keep them in the // lower part of CDF. F = new double[1 + Nmax]; F[imin] = P[imin]; i = imin; while (i < imax && F[i] < 0.5) { i++; F[i] = F[i - 1] + P[i]; } // This is the boundary between F (i <= xmed) and 1 - F (i > xmed) in // the array CDF xmed = i; // Compute the cumulative probabilities of the complementary // distribution 1 - F and keep them in the upper part of the array F[imax] = P[imax]; i = imax - 1; do { F[i] = P[i] + F[i + 1]; i--; } while (i > xmed); xmin = imin; xmax = imax; pdf = new double[imax + 1 - imin]; cdf = new double[imax + 1 - imin]; System.arraycopy(P, imin, pdf, 0, imax + 1 - imin); System.arraycopy(F, imin, cdf, 0, imax + 1 - imin); }
/** * Computes and returns the standard deviation of the negative binomial distribution with * parameters <SPAN CLASS="MATH"><I>n</I></SPAN> and <SPAN CLASS="MATH"><I>p</I></SPAN>. * * @return the standard deviation of the negative binomial distribution */ public static double getStandardDeviation(double n, double p) { return Math.sqrt(NegativeBinomialDist.getVariance(n, p)); }
/** Computes the inverse function without precomputing tables. */ public static int inverseF(double n, double p, double u) { if (u < 0.0 || u > 1.0) throw new IllegalArgumentException("u is not in [0,1]"); if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("p not in [0, 1]"); if (n <= 0.0) throw new IllegalArgumentException("n <= 0"); if (p >= 1.0) // In fact, p == 1 return 0; if (p <= 0.0) // In fact, p == 0 return 0; if (u <= prob(n, p, 0)) return 0; if (u >= 1.0) return Integer.MAX_VALUE; double sum, term, termmode; final double q = 1.0 - p; // Compute the maximum term int mode = 1 + (int) Math.floor((n * q - 1.0) / p); if (mode < 0) mode = 0; int i = mode; term = prob(n, p, i); while ((term >= u) && (term > Double.MIN_NORMAL)) { i /= 2; term = prob(n, p, i); } if (term <= Double.MIN_NORMAL) { i *= 2; term = prob(n, p, i); while (term >= u && (term > Double.MIN_NORMAL)) { term *= i / (q * (n + i - 1.0)); i--; } } mode = i; sum = termmode = prob(n, p, i); for (i = mode; i > 0; i--) { term *= i / (q * (n + i - 1.0)); if (term < EPSILON) break; sum += term; } term = termmode; i = mode; double prev = -1; if (sum < u) { // The CDF at the mode is less than u, so we add term to get >= u. while ((sum < u) && (sum > prev)) { term *= q * (n + i) / (i + 1); prev = sum; sum += term; i++; } } else { // The computed CDF is too big so we substract from it. sum -= term; while (sum >= u) { term *= i / (q * (n + i - 1.0)); i--; sum -= term; } } return i; }