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);
}
}
}
}