using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BotSharp.Algorithm.HiddenMarkovModel.MathUtils.Distribution { public class ChiSquare { private static double logSqrtPi = System.Math.Log(System.Math.Sqrt(System.Math.PI)); private static double rezSqrtPi = 1 / System.Math.Sqrt(System.Math.PI); private static double bigx = 20.0; public const double EPSILON = .0000000001; /// /// Return the probability density function of a F-distribution /// /// reference value for the variable x following the F-distribution /// degrees of freedom /// /// The probability densitiy function public static double GetPDF(double F, int df, double deltaF = 0.0001) { double F1 = F - deltaF / 2; double F2 = F + deltaF / 2; if (F1 <= EPSILON) { F1 = F; deltaF = deltaF / 2; } double p1 = GetPercentile(F1, df); double p2 = GetPercentile(F2, df); double areaP = p2 - p1; return areaP / deltaF; } /// /// Return the critical value F for p = P(x <= F), where p is the percentile /// /// The implementation here is adapted from http://www.cs.umb.edu/~rickb/files/disc_proj/disc/weka/weka-3-2-3/weka/core/Statistics.java /// /// percentile P(x <= F) /// degrees of freedom of numerator /// The critical value F for p = P(x <= F) public static double GetQuantile(double p, int df) { double fval; double maxf = 99999.0; double minf = .000001; if (p <= 0.0 || p >= 1.0) return (0.0); fval = 1.0 / p; // initial value for guess fval, the smaller the p, the larger the F while (System.Math.Abs(maxf - minf) > .000001) { if (GetPercentile(fval, df) > p) // F too large maxf = fval; else // F too small minf = fval; fval = (maxf + minf) * 0.5; } return (fval); } /// /// Return the P(y < x) where y follows the Chi^2 distribution /// /// reference value for y which follows the Chi^2 distribution /// degrees of freedom /// The cumulative probability P(y < x) public static double GetPercentile(double x, int df) { return 1 - ChiSquaredProbability(x, df); } /// /// Return the P(y > x) where y follows the Chi^2 distribution /// /// The implementation here is adapted from http://www.cs.umb.edu/~rickb/files/disc_proj/disc/weka/weka-3-2-3/weka/core/Statistics.java /// /// reference value for y which follows the Chi^2 distribution /// degrees of freedom /// The probability P(y > x) private static double ChiSquaredProbability(double x, int df) { double a, y = 0, s, e, c, z, val; bool even; if (x <= 0 || df < 1) return (1); a = 0.5 * x; even = (((int)(2 * (df / 2))) == df); if (df > 1) y = System.Math.Exp(-a); //((-a < -bigx) ? 0.0 : Math.exp (-a)); s = (even ? y : (2.0 * Gaussian.GetPercentile(-System.Math.Sqrt(x)))); if (df > 2) { x = 0.5 * (df - 1.0); z = (even ? 1.0 : 0.5); if (a > bigx) { e = (even ? 0.0 : logSqrtPi); c = System.Math.Log(a); while (z <= x) { e = System.Math.Log(z) + e; val = c * z - a - e; s += System.Math.Exp(val); //((val < -bigx) ? 0.0 : Math.exp (val)); z += 1.0; } return (s); } else { e = (even ? 1.0 : (rezSqrtPi / System.Math.Sqrt(a))); c = 0.0; while (z <= x) { e = e * (a / z); c = c + e; z += 1.0; } return (c * y + s); } } else { return (s); } } } }