/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.probdist; import umontreal.iro.lecuyer.util.Num; import umontreal.iro.lecuyer.functions.MathFunction; /** * Extends the class {@link ContinuousDistribution} for the chi * distribution with shape parameter * v > 0, where the number of degrees of freedom * v is a positive integer. * The density function is given by *

*

*
* f (x) = e-x2/2xv-1/(2(v/2)-1Γ(v/2)) for x > 0, *

* where * Γ(x) is the gamma function defined in * {@link GammaDist}. * The distribution function is *

*

*
* F(x) = 1/Γ(v/2)∫0x2/2tv/2-1e-t dt. *

* It is equivalent to the gamma distribution function with parameters * * α = v/2 and λ = 1, evaluated at x2/2. * */ public class ChiDist extends ContinuousDistribution { private int nu; private double C1; private static class Function implements MathFunction { protected int n; protected double sum; public Function (double s, int n) { this.n = n; this.sum = s; } public double evaluate (double k) { if (k < 1.0) return 1.0e200; return (sum + n * (Num.lnGamma (k / 2.0) - 0.5*(Num.LN2) - Num.lnGamma ((k + 1.0) / 2.0))); } } /** * Constructs a ChiDist object. * */ public ChiDist (int nu) { setNu (nu); } public double density (double x) { if (x <= 0.0) return 0.0; return Math.exp ((nu - 1)*Math.log (x) - x*x/2.0 - C1); } public double cdf (double x) { return cdf (nu, x); } public double barF (double x) { return barF (nu, x); } public double inverseF (double u) { return inverseF (nu, u); } public double getMean() { return ChiDist.getMean (nu); } public double getVariance() { return ChiDist.getVariance (nu); } public double getStandardDeviation() { return ChiDist.getStandardDeviation (nu); } /** * Computes the density function. * */ public static double density (int nu, double x) { if (nu <= 0) throw new IllegalArgumentException ("nu <= 0"); if (x <= 0.0) return 0.0; return Math.exp ((nu - 1)*Math.log (x) - x*x/2.0 - (nu/2.0 - 1.0)*Num.LN2 - Num.lnGamma (nu/2.0)); } /** * Computes the distribution function by using the * gamma distribution function. * */ public static double cdf (int nu, double x) { if (x <= 0.0) return 0.0; return GammaDist.cdf (nu/2.0, 15, x*x/2.0); } /** * Computes the complementary distribution. * */ public static double barF (int nu, double x) { if (x <= 0.0) return 1.0; return GammaDist.barF (nu/2.0, 15, x*x/2.0); } /** * Returns the inverse distribution function computed * using the gamma inversion. * */ public static double inverseF (int nu, double u) { double res = GammaDist.inverseF (nu/2.0, 15, u); return Math.sqrt (2*res); } /** * Estimates the parameter ν of the chi distribution * using the maximum likelihood method, from the n observations * x[i], * i = 0, 1,…, n - 1. The estimate is returned in element 0 * of the returned array. * * @param x the list of observations to use to evaluate parameters * * @param n the number of observations to use to evaluate parameters * * @return returns the parameter [hat(ν)] * */ public static double[] getMLE (double[] x, int n) { double[] parameters = new double[1]; double mean = 0.0; for (int i = 0; i < n; i++) mean += x[i]; mean /= (double) n; double var = 0.0; for (int i = 0; i < n; i++) var += ((x[i] - mean) * (x[i] - mean)); var /= (double) n; double k = Math.round (var + mean * mean) - 5.0; if (k < 1.0) k = 1.0; double sum = 0.0; for (int i = 0; i < n; i++) { if (x[i] > 0.0) sum += Math.log (x[i]); else sum -= 709.0; } Function f = new Function (sum, n); while (f.evaluate(k) > 0.0) k++; parameters[0] = k; return parameters; } /** * Creates a new instance of a chi distribution with parameter ν estimated using * the maximum likelihood method based on the n observations x[i], * * i = 0, 1,…, n - 1. * * @param x the list of observations to use to evaluate parameters * * @param n the number of observations to use to evaluate parameters * * */ public static ChiDist getInstanceFromMLE (double[] x, int n) { double parameters[] = getMLE (x, n); return new ChiDist ((int) parameters[0]); } /** * Computes and returns the mean * of the chi distribution with parameter ν. * * @return the mean of the chi distribution * * E[X] = (2)1/2Γ((ν +1)/2)/Γ(ν/2) * */ public static double getMean (int nu) { if (nu <= 0) throw new IllegalArgumentException ("nu <= 0"); return Num.RAC2 * Num.gammaRatioHalf(nu / 2.0); } /** * Computes and returns the variance * of the chi distribution with parameter ν. * * @return the variance of the chi distribution * * Var[X] = 2[Γ(ν/2)Γ(1 + ν/2) - Γ2(1/2(ν +1))]/Γ(ν/2) * */ public static double getVariance (int nu) { if (nu <= 0) throw new IllegalArgumentException ("nu <= 0"); double mean = ChiDist.getMean(nu); return (nu - (mean * mean)); } /** * Computes and returns the standard deviation of the chi distribution * with parameter ν. * * @return the standard deviation of the chi distribution * */ public static double getStandardDeviation (int nu) { return Math.sqrt (ChiDist.getVariance (nu)); } /** * Returns the value of ν for this object. * */ public int getNu() { return nu; } /** * Sets the value of ν for this object. * */ public void setNu (int nu) { if (nu <= 0) throw new IllegalArgumentException ("nu <= 0"); this.nu = nu; supportA = 0.0; C1 = (nu/2.0 - 1.0)*Num.LN2 + Num.lnGamma (nu/2.0); } /** * Return a table containing parameters of the current distribution. * * */ public double[] getParams () { double[] retour = {nu}; return retour; } public String toString () { return getClass().getSimpleName() + " : nu = " + nu; } }

Ads help maintain this website.