From 9aa90f54a7fbe289b75a9ec57a5e715424c482d3 Mon Sep 17 00:00:00 2001 From: logophobia Date: Tue, 21 Apr 2015 11:59:16 +0200 Subject: [PATCH] chisquared inverse distribution --- src/Numerics/Distributions/ChiSquared.cs | 29 +++++++++++++++++++ .../Continuous/ChiSquareTests.cs | 26 +++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/Numerics/Distributions/ChiSquared.cs b/src/Numerics/Distributions/ChiSquared.cs index 90249767..5d7d64a7 100644 --- a/src/Numerics/Distributions/ChiSquared.cs +++ b/src/Numerics/Distributions/ChiSquared.cs @@ -325,6 +325,18 @@ namespace MathNet.Numerics.Distributions return (Math.Pow(x, (freedom/2.0) - 1.0)*Math.Exp(-x/2.0))/(Math.Pow(2.0, freedom/2.0)*SpecialFunctions.Gamma(freedom/2.0)); } + /// + /// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution + /// at the given probability. This is also known as the quantile or percent point function. + /// + /// The location at which to compute the inverse cumulative density. + /// the inverse cumulative density at . + /// + public double InverseCumulativeDistribution(double p) + { + return InvCDF(_freedom, p); + } + /// /// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x). /// @@ -359,6 +371,23 @@ namespace MathNet.Numerics.Distributions return SpecialFunctions.GammaLowerRegularized(freedom/2.0, x/2.0); } + /// + /// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution + /// at the given probability. This is also known as the quantile or percent point function. + /// + /// The degrees of freedom (k) of the distribution. Range: k > 0. + /// The location at which to compute the inverse cumulative density. + /// the inverse cumulative density at . + public static double InvCDF(double freedom, double p) + { + if(!IsValidParameterSet(freedom)) + { + throw new ArgumentException(Resources.InvalidDistributionParameters); + } + + return SpecialFunctions.GammaLowerRegularizedInv(freedom / 2.0, p) / 0.5; + } + /// /// Generates a sample from the ChiSquare distribution. /// diff --git a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs index 6bedc208..ccc2c614 100644 --- a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs @@ -318,5 +318,31 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous Assert.That(n.CumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); Assert.That(ChiSquared.CDF(dof, x), Is.EqualTo(expected).Within(1e-14)); } + + [TestCase(1.0, 0.0, 0.0)] + [TestCase(1.0, 0.24817036595415071751, 0.1)] + [TestCase(1.0, 0.68268949213708589717, 1.0)] + [TestCase(1.0, 0.98098352632769945624, 5.5)] + [TestCase(1.0, 1.0, Double.PositiveInfinity)] + [TestCase(2.0, 0.0, 0.0)] + [TestCase(2.0, 0.048770575499285990909, 0.1)] + [TestCase(2.0, 0.39346934028736657640, 1.0)] + [TestCase(2.0, 0.93607213879329242730, 5.5)] + [TestCase(2.0, 1.0, Double.PositiveInfinity)] + [TestCase(2.5, 0.0, 0.0)] + [TestCase(2.5, 0.020298266579604156571, 0.1)] + [TestCase(2.5, 0.28378995266531297417, 1.0)] + [TestCase(2.5, 0.90239512593899828629, 5.5)] + [TestCase(2.5, 1.0, Double.PositiveInfinity)] + [TestCase(10000.0, 0.0, 0.0)] + [TestCase(10000.0, 0.5, 9999.3333412343982)] + [TestCase(20000.0, 0.0, 0.0)] + [TestCase(100000, 0.1, 99427.302671875732)] + public void ValidateInverseCumulativeDistribution(double dof, double x, double expected) + { + var n = new ChiSquared(dof); + Assert.That(n.InverseCumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); + Assert.That(ChiSquared.InvCDF(dof, x), Is.EqualTo(expected).Within(1e-14)); + } } }