Browse Source

Distributions: static PDF/CDF functions for StudentT, Stable, Weibull #188

pull/194/head
Christoph Ruegg 13 years ago
parent
commit
b4592acd02
  1. 188
      src/Numerics/Distributions/Stable.cs
  2. 145
      src/Numerics/Distributions/StudentT.cs
  3. 107
      src/Numerics/Distributions/Weibull.cs
  4. 19
      src/UnitTests/DistributionTests/Continuous/StudentTTests.cs

188
src/Numerics/Distributions/Stable.cs

@ -37,10 +37,10 @@ namespace MathNet.Numerics.Distributions
{
/// <summary>
/// Continuous Univariate Stable distribution.
/// A random variable is said to be stable (or to have a stable distribution) if it has
/// the property that a linear combination of two independent copies of the variable has
/// A random variable is said to be stable (or to have a stable distribution) if it has
/// the property that a linear combination of two independent copies of the variable has
/// the same distribution, up to location and scale parameters.
/// For details about this distribution, see
/// For details about this distribution, see
/// <a href="http://en.wikipedia.org/wiki/Stable_distribution">Wikipedia - Stable distribution</a>.
/// </summary>
/// <remarks><para>The distribution will use the <see cref="System.Random"/> by default.`
@ -58,7 +58,7 @@ namespace MathNet.Numerics.Distributions
double _location;
/// <summary>
/// Initializes a new instance of the <see cref="Stable"/> class.
/// Initializes a new instance of the <see cref="Stable"/> class.
/// </summary>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
@ -71,7 +71,7 @@ namespace MathNet.Numerics.Distributions
}
/// <summary>
/// Initializes a new instance of the <see cref="Stable"/> class.
/// Initializes a new instance of the <see cref="Stable"/> class.
/// </summary>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
@ -93,19 +93,6 @@ namespace MathNet.Numerics.Distributions
return "Stable(α = " + _alpha + ", β = " + _beta + ", c = " + _scale + ", μ = " + _location + ")";
}
/// <summary>
/// Checks whether the parameters of the distribution are valid.
/// </summary>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
/// <param name="scale">The scale (c) of the distribution. Range: c > 0.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
static bool IsValidParameterSet(double alpha, double beta, double scale, double location)
{
return alpha > 0.0 && alpha <= 2.0 && beta >= -1.0 && beta <= 1.0 && scale > 0.0 && !Double.IsNaN(location);
}
/// <summary>
/// Sets the parameters of the distribution after checking their validity.
/// </summary>
@ -116,7 +103,8 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">When the parameters are out of range.</exception>
void SetParameters(double alpha, double beta, double scale, double location)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha, beta, scale, location))
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0
|| Double.IsNaN(alpha) || Double.IsNaN(beta) || Double.IsNaN(scale) || Double.IsNaN(location))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
@ -179,7 +167,7 @@ namespace MathNet.Numerics.Distributions
{
get
{
if (_alpha <= 1)
if (_alpha <= 1d)
{
throw new NotSupportedException();
}
@ -195,7 +183,7 @@ namespace MathNet.Numerics.Distributions
{
get
{
if (_alpha == 2)
if (_alpha == 2d)
{
return 2.0*_scale*_scale;
}
@ -211,7 +199,7 @@ namespace MathNet.Numerics.Distributions
{
get
{
if (_alpha == 2)
if (_alpha == 2d)
{
return Constants.Sqrt2*_scale;
}
@ -237,7 +225,7 @@ namespace MathNet.Numerics.Distributions
{
get
{
if (_alpha != 2)
if (_alpha != 2d)
{
throw new NotSupportedException();
}
@ -254,7 +242,7 @@ namespace MathNet.Numerics.Distributions
{
get
{
if (_beta != 0)
if (_beta != 0d)
{
throw new NotSupportedException();
}
@ -311,40 +299,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
if (_alpha == 2)
{
return (new Normal(_location, StdDev)).Density(x);
}
if (_alpha == 1 && _beta == 0)
{
return (new Cauchy(_location, _scale)).Density(x);
}
if (_alpha == 0.5 && _beta == 1)
{
return LevyDensity(_scale, _location, x);
}
throw new NotSupportedException();
}
/// <summary>
/// Computes the density of the Levy distribution.
/// </summary>
/// <param name="scale">The scale (c) of the distribution.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns>
static double LevyDensity(double scale, double location, double x)
{
// The parameters scale and location must be correct
if (x < location)
{
throw new NotSupportedException();
}
return (Math.Sqrt(scale/Constants.Pi2)*Math.Exp(-scale/(2*(x - location))))/Math.Pow(x - location, 1.5);
return PDF(_alpha, _beta, _scale, _location, x);
}
/// <summary>
@ -354,7 +309,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return Math.Log(Density(x));
return PDFLn(_alpha, _beta, _scale, _location, x);
}
/// <summary>
@ -365,35 +320,7 @@ namespace MathNet.Numerics.Distributions
/// <remarks>Throws a not supported exception if <c>Alpha != 2</c>, <c>(Alpha != 1 and Beta !=0)</c>, or <c>(Alpha != 0.5 and Beta != 1)</c></remarks>
public double CumulativeDistribution(double x)
{
if (_alpha == 2)
{
return (new Normal(_location, StdDev)).CumulativeDistribution(x);
}
if (_alpha == 1 && _beta == 0)
{
return (new Cauchy(_location, _scale)).CumulativeDistribution(x);
}
if (_alpha == 0.5 && _beta == 1)
{
return LevyCumulativeDistribution(_scale, _location, x);
}
throw new NotSupportedException();
}
/// <summary>
/// Computes the cumulative distribution function of the Levy distribution.
/// </summary>
/// <param name="scale">The scale (c) of the distribution.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="x">The location at which to compute the cumulative density.</param>
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
static double LevyCumulativeDistribution(double scale, double location, double x)
{
// The parameters scale and location must be correct
return SpecialFunctions.Erfc(Math.Sqrt(scale/(2*(x - location))));
return CDF(_alpha, _beta, _scale, _location, x);
}
/// <summary>
@ -453,6 +380,83 @@ namespace MathNet.Numerics.Distributions
}
}
/// <summary>
/// Computes the probability density of the distribution (PDF) at x, i.e. ∂P(X ≤ x)/∂x.
/// </summary>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
/// <param name="scale">The scale (c) of the distribution. Range: c > 0.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns>
/// <seealso cref="Density"/>
public static double PDF(double alpha, double beta, double scale, double location, double x)
{
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0)
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (alpha == 2d) return Normal.PDF(location, Constants.Sqrt2*scale, x);
if (alpha == 1d && beta == 0d) return Cauchy.PDF(location, scale, x);
if (alpha == 0.5d && beta == 1d && x >= location)
{
return (Math.Sqrt(scale/Constants.Pi2)*Math.Exp(-scale/(2*(x - location))))/Math.Pow(x - location, 1.5);
}
throw new NotSupportedException();
}
/// <summary>
/// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x).
/// </summary>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
/// <param name="scale">The scale (c) of the distribution. Range: c > 0.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the log density at <paramref name="x"/>.</returns>
/// <seealso cref="DensityLn"/>
public static double PDFLn(double alpha, double beta, double scale, double location, double x)
{
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0)
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (alpha == 2d) return Normal.PDFLn(location, Constants.Sqrt2*scale, x);
if (alpha == 1d && beta == 0d) return Cauchy.PDFLn(location, scale, x);
if (alpha == 0.5d && beta == 1d && x >= location)
{
return (Math.Log(scale/Constants.Pi2))/2 - scale/(2*(x - location)) - 1.5*Math.Log(x - location);
}
throw new NotSupportedException();
}
/// <summary>
/// Computes the cumulative distribution (CDF) of the distribution at x, i.e. P(X ≤ x).
/// </summary>
/// <param name="x">The location at which to compute the cumulative distribution function.</param>
/// <param name="alpha">The stability (α) of the distribution. Range: 2 ≥ α > 0.</param>
/// <param name="beta">The skewness (β) of the distribution. Range: 1 ≥ β ≥ -1.</param>
/// <param name="scale">The scale (c) of the distribution. Range: c > 0.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
/// <seealso cref="CumulativeDistribution"/>
public static double CDF(double alpha, double beta, double scale, double location, double x)
{
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0)
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (alpha == 2d) return Normal.CDF(location, Constants.Sqrt2*scale, x);
if (alpha == 1d && beta == 0d) return Cauchy.CDF(location, scale, x);
if (alpha == 0.5d && beta == 1d)
{
return SpecialFunctions.Erfc(Math.Sqrt(scale/(2*(x - location))));
}
throw new NotSupportedException();
}
/// <summary>
/// Generates a sample from the distribution.
@ -465,10 +469,8 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public static double Sample(System.Random rnd, double alpha, double beta, double scale, double location)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha, beta, scale, location))
{
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0)
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
return SampleUnchecked(rnd, alpha, beta, scale, location);
}
@ -484,10 +486,8 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sequence of samples from the distribution.</returns>
public static IEnumerable<double> Samples(System.Random rnd, double alpha, double beta, double scale, double location)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(location, scale, scale, location))
{
if (alpha <= 0.0 || alpha > 2.0 || beta < -1.0 || beta > 1.0 || scale <= 0.0)
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
while (true)
{

145
src/Numerics/Distributions/StudentT.cs

@ -38,7 +38,7 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Continuous Univariate Student's T-distribution.
/// Implements the univariate Student t-distribution. For details about this
/// distribution, see
/// distribution, see
/// <a href="http://en.wikipedia.org/wiki/Student%27s_t-distribution">
/// Wikipedia - Student's t-distribution</a>.
/// </summary>
@ -50,7 +50,7 @@ namespace MathNet.Numerics.Distributions
/// Gamma((dof+1)/2) (1 + (x - mu)^2 / (scale * scale * dof))^(-(dof+1)/2) /
/// (Gamma(dof/2)*Sqrt(dof*pi*scale)).</para>
/// <para>The distribution will use the <see cref="System.Random"/> by
/// default. Users can get/set the random number generator by using the
/// default. Users can get/set the random number generator by using the
/// <see cref="RandomSource"/> property.</para>
/// <para>The statistics classes will check all the incoming parameters
/// whether they are in the allowed range. This might involve heavy
@ -66,18 +66,17 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the StudentT class. This is a Student t-distribution with location 0.0
/// scale 1.0 and degrees of freedom 1. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// scale 1.0 and degrees of freedom 1.
/// </summary>
public StudentT()
: this(0.0, 1.0, 1.0)
{
_random = MersenneTwister.Default;
SetParameters(0.0, 1.0, 1.0);
}
/// <summary>
/// Initializes a new instance of the StudentT class with a particular location, scale and degrees of
/// freedom. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// freedom.
/// </summary>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
@ -90,8 +89,7 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the StudentT class with a particular location, scale and degrees of
/// freedom. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// freedom.
/// </summary>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
@ -112,18 +110,6 @@ namespace MathNet.Numerics.Distributions
return "StudentT(μ = " + _location + ", σ = " + _scale + ", ν = " + _freedom + ")";
}
/// <summary>
/// Checks whether the parameters of the distribution are valid.
/// </summary>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
/// <param name="freedom">The degrees of freedom (ν) for the distribution. Range: ν > 0.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
static bool IsValidParameterSet(double location, double scale, double freedom)
{
return scale > 0.0 && freedom > 0.0 && !Double.IsNaN(location);
}
/// <summary>
/// Sets the parameters of the distribution after checking their validity.
/// </summary>
@ -133,7 +119,7 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">When the parameters are out of range.</exception>
void SetParameters(double location, double scale, double freedom)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(location, scale, freedom))
if (scale <= 0.0 || freedom <= 0.0 || Double.IsNaN(scale) || Double.IsNaN(location) || Double.IsNaN(freedom))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
@ -295,17 +281,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
// TODO JVG we can probably do a better job for Cauchy special case
if (_freedom >= 1e+8d)
{
return Normal.PDF(_location, _scale, x);
}
var d = (x - _location)/_scale;
return Math.Exp(SpecialFunctions.GammaLn((_freedom + 1.0)/2.0) - SpecialFunctions.GammaLn(_freedom/2.0))
*Math.Pow(1.0 + (d*d/_freedom), -0.5*(_freedom + 1.0))
/Math.Sqrt(_freedom*Math.PI)
/_scale;
return PDF(_location, _scale, _freedom, x);
}
/// <summary>
@ -315,17 +291,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
// TODO JVG we can probably do a better job for Cauchy special case
if (_freedom >= 1e+8d)
{
return Normal.PDFLn(_location, _scale, x);
}
var d = (x - _location)/_scale;
return SpecialFunctions.GammaLn((_freedom + 1.0)/2.0)
- (0.5*((_freedom + 1.0)*Math.Log(1.0 + (d*d/_freedom))))
- SpecialFunctions.GammaLn(_freedom/2.0)
- (0.5*Math.Log(_freedom*Math.PI)) - Math.Log(_scale);
return PDFLn(_location, _scale, _freedom, x);
}
/// <summary>
@ -335,22 +301,13 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
// TODO JVG we can probably do a better job for Cauchy special case
if (Double.IsPositiveInfinity(_freedom))
{
return Normal.CDF(_location, _scale, x);
}
var k = (x - _location)/_scale;
var h = _freedom/(_freedom + (k*k));
var ib = 0.5*SpecialFunctions.BetaRegularized(_freedom/2.0, 0.5, h);
return x <= _location ? ib : 1.0 - ib;
return CDF(_location, _scale, _freedom, x);
}
/// <summary>
/// Samples student-t distributed random variables.
/// </summary>
/// <remarks>The algorithm is method 2 in section 5, chapter 9
/// <remarks>The algorithm is method 2 in section 5, chapter 9
/// in L. Devroye's "Non-Uniform Random Variate Generation"</remarks>
/// <param name="rnd">The random number generator to use.</param>
/// <param name="location">The location (μ) of the distribution.</param>
@ -384,6 +341,74 @@ namespace MathNet.Numerics.Distributions
}
}
/// <summary>
/// Computes the probability density of the distribution (PDF) at x, i.e. ∂P(X ≤ x)/∂x.
/// </summary>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
/// <param name="freedom">The degrees of freedom (ν) for the distribution. Range: ν > 0.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns>
/// <seealso cref="Density"/>
public static double PDF(double location, double scale, double freedom, double x)
{
if (scale <= 0.0 || freedom <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
// TODO JVG we can probably do a better job for Cauchy special case
if (freedom >= 1e+8d) return Normal.PDF(location, scale, x);
var d = (x - location)/scale;
return Math.Exp(SpecialFunctions.GammaLn((freedom + 1.0)/2.0) - SpecialFunctions.GammaLn(freedom/2.0))
*Math.Pow(1.0 + (d*d/freedom), -0.5*(freedom + 1.0))
/Math.Sqrt(freedom*Math.PI)
/scale;
}
/// <summary>
/// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x).
/// </summary>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
/// <param name="freedom">The degrees of freedom (ν) for the distribution. Range: ν > 0.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the log density at <paramref name="x"/>.</returns>
/// <seealso cref="DensityLn"/>
public static double PDFLn(double location, double scale, double freedom, double x)
{
if (scale <= 0.0 || freedom <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
// TODO JVG we can probably do a better job for Cauchy special case
if (freedom >= 1e+8d) return Normal.PDFLn(location, scale, x);
var d = (x - location)/scale;
return SpecialFunctions.GammaLn((freedom + 1.0)/2.0)
- (0.5*((freedom + 1.0)*Math.Log(1.0 + (d*d/freedom))))
- SpecialFunctions.GammaLn(freedom/2.0)
- (0.5*Math.Log(freedom*Math.PI)) - Math.Log(scale);
}
/// <summary>
/// Computes the cumulative distribution (CDF) of the distribution at x, i.e. P(X ≤ x).
/// </summary>
/// <param name="x">The location at which to compute the cumulative distribution function.</param>
/// <param name="location">The location (μ) of the distribution.</param>
/// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
/// <param name="freedom">The degrees of freedom (ν) for the distribution. Range: ν > 0.</param>
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
/// <seealso cref="CumulativeDistribution"/>
public static double CDF(double location, double scale, double freedom, double x)
{
if (scale <= 0.0 || freedom <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
// TODO JVG we can probably do a better job for Cauchy special case
if (Double.IsPositiveInfinity(freedom)) return Normal.CDF(location, scale, x);
var k = (x - location)/scale;
var h = freedom/(freedom + (k*k));
var ib = 0.5*SpecialFunctions.BetaRegularized(freedom/2.0, 0.5, h);
return x <= location ? ib : 1.0 - ib;
}
/// <summary>
/// Generates a sample from the Student t-distribution.
/// </summary>
@ -394,10 +419,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public static double Sample(System.Random rnd, double location, double scale, double freedom)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(location, scale, freedom))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
if (scale <= 0.0 || freedom <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
return SampleUnchecked(rnd, location, scale, freedom);
}
@ -412,10 +434,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sequence of samples from the distribution.</returns>
public static IEnumerable<double> Samples(System.Random rnd, double location, double scale, double freedom)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(location, scale, freedom))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
if (scale <= 0.0 || freedom <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
while (true)
{

107
src/Numerics/Distributions/Weibull.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -37,12 +37,12 @@ namespace MathNet.Numerics.Distributions
{
/// <summary>
/// Continuous Univariate Weibull distribution.
/// For details about this distribution, see
/// For details about this distribution, see
/// <a href="http://en.wikipedia.org/wiki/Weibull_distribution">Wikipedia - Weibull distribution</a>.
/// </summary>
/// <remarks>
/// <para>The Weibull distribution is parametrized by a shape and scale parameter.</para>
/// <para>The distribution will use the <see cref="System.Random"/> by default.
/// <para>The distribution will use the <see cref="System.Random"/> by default.
/// Users can get/set the random number generator by using the <see cref="RandomSource"/> property.</para>
/// <para>The statistics classes will check all the incoming parameters whether they are in the allowed
/// range. This might involve heavy computation. Optionally, by setting Control.CheckDistributionParameters
@ -95,17 +95,6 @@ namespace MathNet.Numerics.Distributions
return "Weibull(k = " + _shape + ", λ = " + _scale + ")";
}
/// <summary>
/// Checks whether the parameters of the distribution are valid.
/// </summary>
/// <param name="shape">The shape (k) of the Weibull distribution. Range: k > 0.</param>
/// <param name="scale">The scale (λ) of the Weibull distribution. Range: λ > 0.</param>
/// <returns><c>true</c> when the parameters positive valid floating point numbers, <c>false</c> otherwise.</returns>
static bool IsValidParameterSet(double shape, double scale)
{
return shape > 0.0 && scale > 0.0;
}
/// <summary>
/// Sets the parameters of the distribution after checking their validity.
/// </summary>
@ -114,7 +103,7 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">When the parameters are out of range.</exception>
void SetParameters(double shape, double scale)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(shape, scale))
if (shape <= 0.0 || scale <= 0.0 || Double.IsNaN(shape) || Double.IsNaN(scale))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
@ -285,10 +274,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
if (x < 0.0)
{
return 0.0;
}
if (x < 0.0) return 0.0;
return -SpecialFunctions.ExponentialMinusOne(-Math.Pow(x, _shape)*_scalePowShapeInv);
}
@ -328,6 +314,79 @@ namespace MathNet.Numerics.Distributions
}
}
/// <summary>
/// Computes the probability density of the distribution (PDF) at x, i.e. ∂P(X ≤ x)/∂x.
/// </summary>
/// <param name="shape">The shape (k) of the Weibull distribution. Range: k > 0.</param>
/// <param name="scale">The scale (λ) of the Weibull distribution. Range: λ > 0.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns>
/// <seealso cref="Density"/>
public static double PDF(double shape, double scale, double x)
{
if (shape <= 0.0 || scale <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (x >= 0.0)
{
if (x == 0.0 && shape == 1.0)
{
return shape/scale;
}
return shape
*Math.Pow(x/scale, shape - 1.0)
*Math.Exp(-Math.Pow(x, shape)*Math.Pow(scale, -shape))
/scale;
}
return 0.0;
}
/// <summary>
/// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x).
/// </summary>
/// <param name="shape">The shape (k) of the Weibull distribution. Range: k > 0.</param>
/// <param name="scale">The scale (λ) of the Weibull distribution. Range: λ > 0.</param>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the log density at <paramref name="x"/>.</returns>
/// <seealso cref="DensityLn"/>
public static double PDFLn(double shape, double scale, double x)
{
if (shape <= 0.0 || scale <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (x >= 0.0)
{
if (x == 0.0 && shape == 1.0)
{
return Math.Log(shape) - Math.Log(scale);
}
return Math.Log(shape)
+ ((shape - 1.0)*Math.Log(x/scale))
- (Math.Pow(x, shape)*Math.Pow(scale, -shape))
- Math.Log(scale);
}
return double.NegativeInfinity;
}
/// <summary>
/// Computes the cumulative distribution (CDF) of the distribution at x, i.e. P(X ≤ x).
/// </summary>
/// <param name="x">The location at which to compute the cumulative distribution function.</param>
/// <param name="shape">The shape (k) of the Weibull distribution. Range: k > 0.</param>
/// <param name="scale">The scale (λ) of the Weibull distribution. Range: λ > 0.</param>
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
/// <seealso cref="CumulativeDistribution"/>
public static double CDF(double shape, double scale, double x)
{
if (shape <= 0.0 || scale <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
if (x < 0.0) return 0.0;
return -SpecialFunctions.ExponentialMinusOne(-Math.Pow(x, shape)*Math.Pow(scale, -shape));
}
/// <summary>
/// Generates a sample from the Weibull distribution.
/// </summary>
@ -337,10 +396,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public static double Sample(System.Random rnd, double shape, double scale)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(shape, scale))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
if (shape <= 0.0 || scale <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
return SampleUnchecked(rnd, shape, scale);
}
@ -354,10 +410,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sequence of samples from the distribution.</returns>
public static IEnumerable<double> Samples(System.Random rnd, double shape, double scale)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(shape, scale))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
if (shape <= 0.0 || scale <= 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
while (true)
{

19
src/UnitTests/DistributionTests/Continuous/StudentTTests.cs

@ -390,25 +390,6 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
ied.Take(5).ToArray();
}
/// <summary>
/// Fail sample static with bad parameters.
/// </summary>
[Test]
public void FailSampleStatic()
{
Assert.Throws<ArgumentOutOfRangeException>(() => StudentT.Sample(new Random(0), Double.NaN, 1.0, Double.NaN));
}
/// <summary>
/// Fail sample sequence static with bad parameters.
/// </summary>
[Test]
public void FailSampleSequenceStatic()
{
var ied = StudentT.Samples(new Random(0), 0.0, 1.0, Double.NaN);
Assert.Throws<ArgumentOutOfRangeException>(() => ied.Take(5).ToArray());
}
/// <summary>
/// Can sample.
/// </summary>

Loading…
Cancel
Save