From e21559ac10bc66a62740a8c4faf44a078e34ebed Mon Sep 17 00:00:00 2001 From: Abratiychuk Date: Mon, 4 Oct 2010 03:06:28 +0800 Subject: [PATCH] Verified Distributions, added several properties, fixed several properties. --- src/Numerics/Distributions/Continuous/Beta.cs | 2 +- .../Distributions/Continuous/ChiSquare.cs | 2 +- .../Distributions/Continuous/Exponential.cs | 34 +++++++++++++ .../Continuous/FisherSnedecor.cs | 2 +- .../Distributions/Continuous/InverseGamma.cs | 6 +-- .../Distributions/Continuous/Pareto.cs | 7 ++- .../Distributions/Continuous/Stable.cs | 40 ++++++++++++++- .../Distributions/Continuous/Weibull.cs | 3 +- .../Distributions/Discrete/Bernoulli.cs | 2 +- .../Distributions/Discrete/Binomial.cs | 2 +- .../Discrete/ConwayMaxwellPoisson.cs | 12 ++--- .../Distributions/Discrete/Geometric.cs | 7 +-- .../Discrete/NegativeBinomial.cs | 28 +++++------ .../Distributions/Multivariate/Multinomial.cs | 26 ++++++---- .../Distributions/Multivariate/NormalGamma.cs | 49 ++++++++++++------- .../DistributionTests/Continuous/BetaTests.cs | 2 +- .../Continuous/ChiSquareTests.cs | 2 +- .../Continuous/FisherSnedecorTests.cs | 2 +- .../Continuous/InverseGammaTests.cs | 6 +-- .../Continuous/ParetoTests.cs | 9 +++- .../Continuous/StableTests.cs | 4 +- .../Discrete/BernoulliTests.cs | 2 +- .../Discrete/BinomialTests.cs | 2 +- .../Discrete/GeometricTests.cs | 15 +++--- .../Discrete/NegativeBinomialTests.cs | 31 +++++++----- .../Multivariate/MultinomialTests.cs | 25 +++++++++- .../Multivariate/NormalGammaTests.cs | 9 ++++ 27 files changed, 233 insertions(+), 98 deletions(-) diff --git a/src/Numerics/Distributions/Continuous/Beta.cs b/src/Numerics/Distributions/Continuous/Beta.cs index b4374570..374450a1 100644 --- a/src/Numerics/Distributions/Continuous/Beta.cs +++ b/src/Numerics/Distributions/Continuous/Beta.cs @@ -363,7 +363,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } diff --git a/src/Numerics/Distributions/Continuous/ChiSquare.cs b/src/Numerics/Distributions/Continuous/ChiSquare.cs index bdba56bf..9987f903 100644 --- a/src/Numerics/Distributions/Continuous/ChiSquare.cs +++ b/src/Numerics/Distributions/Continuous/ChiSquare.cs @@ -184,7 +184,7 @@ namespace MathNet.Numerics.Distributions /// the cumulative density at . public double CumulativeDistribution(double x) { - return SpecialFunctions.GammaUpperIncomplete(Mean / 2.0, x / 2.0) / SpecialFunctions.Gamma(Mean / 2.0); + return SpecialFunctions.GammaLowerIncomplete(Mean / 2.0, x / 2.0) / SpecialFunctions.Gamma(Mean / 2.0); } #endregion diff --git a/src/Numerics/Distributions/Continuous/Exponential.cs b/src/Numerics/Distributions/Continuous/Exponential.cs index 19267e2c..5855854c 100644 --- a/src/Numerics/Distributions/Continuous/Exponential.cs +++ b/src/Numerics/Distributions/Continuous/Exponential.cs @@ -310,6 +310,40 @@ namespace MathNet.Numerics.Distributions } } + /// + /// Draws a random sample from the distribution. + /// + /// The random number generator to use. + /// The lambda parameter of the Exponential distribution. + /// A random number from this distribution. + public static double Sample(Random rnd, double lambda) + { + if (Control.CheckDistributionParameters && !IsValidParameterSet(lambda)) + { + throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters); + } + + return DoSample(rnd, lambda); + } + + /// + /// Generates a sequence of samples from the Exponential distribution. + /// + /// The random number generator to use. + /// The lambda parameter of the Exponential distribution. + /// a sequence of samples from the distribution. + public static IEnumerable Samples(Random rnd, double lambda) + { + if (Control.CheckDistributionParameters && !IsValidParameterSet(lambda)) + { + throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters); + } + + while (true) + { + yield return DoSample(rnd, lambda); + } + } #endregion /// diff --git a/src/Numerics/Distributions/Continuous/FisherSnedecor.cs b/src/Numerics/Distributions/Continuous/FisherSnedecor.cs index bd7090ea..9e382890 100644 --- a/src/Numerics/Distributions/Continuous/FisherSnedecor.cs +++ b/src/Numerics/Distributions/Continuous/FisherSnedecor.cs @@ -249,7 +249,7 @@ namespace MathNet.Numerics.Distributions /// the cumulative density at . public double CumulativeDistribution(double x) { - return SpecialFunctions.BetaRegularized(_d1 / 2.0, _d2 / 2.0, _d1 * _d2 / (_d1 + (_d1 * _d2))); + return SpecialFunctions.BetaRegularized(_d1 / 2.0, _d2 / 2.0, _d1 * x / ((_d1 * x) + _d2)); } #endregion diff --git a/src/Numerics/Distributions/Continuous/InverseGamma.cs b/src/Numerics/Distributions/Continuous/InverseGamma.cs index c4963772..67a56f26 100644 --- a/src/Numerics/Distributions/Continuous/InverseGamma.cs +++ b/src/Numerics/Distributions/Continuous/InverseGamma.cs @@ -259,7 +259,7 @@ namespace MathNet.Numerics.Distributions /// the cumulative density at . public double CumulativeDistribution(double x) { - return SpecialFunctions.GammaLowerIncomplete(_shape, _scale / x); + return SpecialFunctions.GammaUpperRegularized(_shape, _scale / x); } #endregion @@ -280,12 +280,12 @@ namespace MathNet.Numerics.Distributions /// /// Gets the median of the distribution. /// - /// Throws . + /// Throws . public double Median { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } diff --git a/src/Numerics/Distributions/Continuous/Pareto.cs b/src/Numerics/Distributions/Continuous/Pareto.cs index 4d8a69b6..97c3bc34 100644 --- a/src/Numerics/Distributions/Continuous/Pareto.cs +++ b/src/Numerics/Distributions/Continuous/Pareto.cs @@ -201,7 +201,12 @@ namespace MathNet.Numerics.Distributions { get { - return _scale * _scale * _shape / ((_shape - 1.0) * (_shape - 1.0) * (_scale - 2.0)); + if (_shape <= 2.0) + { + return double.PositiveInfinity; + } + + return _scale * _scale * _shape / ((_shape - 1.0) * (_shape - 1.0) * (_shape - 2.0)); } } diff --git a/src/Numerics/Distributions/Continuous/Stable.cs b/src/Numerics/Distributions/Continuous/Stable.cs index 7721b11e..7d8cfeb2 100644 --- a/src/Numerics/Distributions/Continuous/Stable.cs +++ b/src/Numerics/Distributions/Continuous/Stable.cs @@ -481,7 +481,7 @@ namespace MathNet.Numerics.Distributions /// A random number from this distribution. public double Sample() { - throw new NotImplementedException(); + return DoSample(RandomSource, _alpha, _beta); } /// @@ -490,9 +490,45 @@ namespace MathNet.Numerics.Distributions /// a sequence of samples from the distribution. public IEnumerable Samples() { - throw new NotImplementedException(); + while (true) + { + yield return DoSample(RandomSource, _alpha, _beta); + } } + /// + /// Samples the distribution. + /// + /// The random number generator to use. + /// The stability parameter of the distribution. + /// The skewness parameter of the distribution. + /// a random number from the distribution. + private static double DoSample(Random rnd, double alpha, double beta) + { + var randTheta = ContinuousUniform.Sample(rnd, -Constants.PiOver2, Constants.PiOver2); + var randW = Exponential.Sample(rnd, 1.0); + + if (!1.0.AlmostEqual(alpha)) + { + var theta = (1.0 / alpha) * Math.Atan(beta * Math.Tan(Constants.PiOver2 * alpha)); + var angle = alpha * (randTheta + theta); + var part1 = beta * Math.Tan(Constants.PiOver2 * alpha); + + var factor = Math.Pow(1.0 + (part1 * part1), 1.0 / (2.0 * alpha)); + var factor1 = Math.Sin(angle) / Math.Pow(Math.Cos(randTheta), (1.0 / alpha)); + var factor2 = Math.Pow(Math.Cos(randTheta - angle) / randW, (1 - alpha) / alpha); + + return factor * factor1 * factor2; + } + else + { + var part1 = Constants.PiOver2 + (beta * randTheta); + var summand = part1 * Math.Tan(randTheta); + var subtrahend = beta * Math.Log(Constants.PiOver2 * randW * Math.Cos(randTheta) / part1); + + return (2.0 / Math.PI) * (summand - subtrahend); + } + } #endregion } } diff --git a/src/Numerics/Distributions/Continuous/Weibull.cs b/src/Numerics/Distributions/Continuous/Weibull.cs index 695be956..c970f98b 100644 --- a/src/Numerics/Distributions/Continuous/Weibull.cs +++ b/src/Numerics/Distributions/Continuous/Weibull.cs @@ -216,12 +216,11 @@ namespace MathNet.Numerics.Distributions /// /// Gets the entropy of the Weibull distribution. /// - /// Throws a not supported exception. public double Entropy { get { - throw new NotSupportedException(); + return (Constants.EulerMascheroni * (1.0 - (1.0 / _shape))) + Math.Log(_scale / _shape) + 1.0; } } diff --git a/src/Numerics/Distributions/Discrete/Bernoulli.cs b/src/Numerics/Distributions/Discrete/Bernoulli.cs index 5862049d..ea9fdd47 100644 --- a/src/Numerics/Distributions/Discrete/Bernoulli.cs +++ b/src/Numerics/Distributions/Discrete/Bernoulli.cs @@ -259,7 +259,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new Exception("The median of the Bernoulli distribution is undefined."); + throw new NotSupportedException("The median of the Bernoulli distribution is undefined."); } } diff --git a/src/Numerics/Distributions/Discrete/Binomial.cs b/src/Numerics/Distributions/Discrete/Binomial.cs index 0e5cc658..5f836591 100644 --- a/src/Numerics/Distributions/Discrete/Binomial.cs +++ b/src/Numerics/Distributions/Discrete/Binomial.cs @@ -320,7 +320,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + return (int)Math.Floor(_p * _n); } } diff --git a/src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs b/src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs index 98618b47..b476b5b1 100644 --- a/src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs +++ b/src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs @@ -346,7 +346,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } @@ -357,7 +357,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } @@ -388,7 +388,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } @@ -399,7 +399,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } @@ -421,7 +421,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + throw new NotSupportedException(); } } @@ -488,7 +488,7 @@ namespace MathNet.Numerics.Distributions _z = Normalization(_lambda, _nu); return _z; - } + } } /// diff --git a/src/Numerics/Distributions/Discrete/Geometric.cs b/src/Numerics/Distributions/Discrete/Geometric.cs index b8348349..eced457d 100644 --- a/src/Numerics/Distributions/Discrete/Geometric.cs +++ b/src/Numerics/Distributions/Discrete/Geometric.cs @@ -195,7 +195,8 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotSupportedException(); + return ((2.0 - _p) / Math.Sqrt(1.0 - _p)); + } } @@ -231,7 +232,7 @@ namespace MathNet.Numerics.Distributions { get { - return (int)Math.Ceiling(-Math.Log(2.0) / Math.Log(1 - _p)); + return (int)Math.Ceiling(-Constants.Ln2 / Math.Log(1 - _p)); } } @@ -253,7 +254,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotSupportedException(); + return int.MaxValue; } } diff --git a/src/Numerics/Distributions/Discrete/NegativeBinomial.cs b/src/Numerics/Distributions/Discrete/NegativeBinomial.cs index 2d6633d9..e9bfdf29 100644 --- a/src/Numerics/Distributions/Discrete/NegativeBinomial.cs +++ b/src/Numerics/Distributions/Discrete/NegativeBinomial.cs @@ -59,7 +59,7 @@ namespace MathNet.Numerics.Distributions private Random _random; /// - /// Gets or sets the r parameter. + /// Gets or sets the number of trials. /// public double R { @@ -75,7 +75,7 @@ namespace MathNet.Numerics.Distributions } /// - /// Gets or sets the p parameter. + /// Gets or sets the probability of success. /// public double P { @@ -93,12 +93,8 @@ namespace MathNet.Numerics.Distributions /// /// Initializes a new instance of the class. /// - /// - /// The r parameter. - /// - /// - /// The p parameter. - /// + /// The number of trials. + /// The probability of a trial resulting in success. public NegativeBinomial(double r, double p) { SetParameters(r, p); @@ -108,8 +104,8 @@ namespace MathNet.Numerics.Distributions /// /// Sets the parameters of the distribution after checking their validity. /// - /// The r parameter. - /// The p parameter. + /// The number of trials. + /// The probability of a trial resulting in success. /// When the parameters don't pass the function. private void SetParameters(double r, double p) { @@ -125,8 +121,8 @@ namespace MathNet.Numerics.Distributions /// /// Checks whether the parameters of the distribution are valid. /// - /// The r parameter. - /// The p parameter. + /// The number of trials. + /// The probability of a trial resulting in success. /// true when the parameters are valid, false otherwise. private static bool IsValidParameterSet(double r, double p) { @@ -217,7 +213,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new Exception("Not implemented yet."); + throw new NotSupportedException(); } } @@ -239,7 +235,7 @@ namespace MathNet.Numerics.Distributions /// the cumulative density at . public double CumulativeDistribution(double x) { - throw new NotImplementedException(); + return 1 - SpecialFunctions.BetaRegularized(x + 1, _r, 1 - _p); } #endregion @@ -264,7 +260,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new Exception("Not implemented yet."); + throw new NotSupportedException(); } } @@ -286,7 +282,7 @@ namespace MathNet.Numerics.Distributions { get { - throw new NotImplementedException(); + return int.MaxValue; } } diff --git a/src/Numerics/Distributions/Multivariate/Multinomial.cs b/src/Numerics/Distributions/Multivariate/Multinomial.cs index 73d3a934..d13acf0a 100644 --- a/src/Numerics/Distributions/Multivariate/Multinomial.cs +++ b/src/Numerics/Distributions/Multivariate/Multinomial.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.Distributions using System; using System.Collections.Generic; using Properties; + using Statistics; /// /// Implements the multinomial distribution. For details about this distribution, see @@ -73,24 +74,31 @@ namespace MathNet.Numerics.Distributions RandomSource = new Random(); } - /* TODO /// - /// Generate a multinomial distribution from histogram . The distribution will + /// Initializes a new instance of the Multinomial class from histogram . The distribution will /// not be automatically updated when the histogram changes. /// - public Multinomial(Histogram h) + /// Histogram instance + /// The number of trials. + public Multinomial(Histogram h, int n) { + if (h == null) + { + throw new ArgumentNullException("h"); + } + // The probability distribution vector. - _p = new double[h.BinCount]; + var p = new double[h.BucketCount]; // Fill in the distribution vector. - for (int i = 0; i < h.BinCount; i++) + for (var i = 0; i < h.BucketCount; i++) { - _p[i] = h[i]; + p[i] = h[i].Count; } - RandomNumberGenerator = new System.Random(); - }*/ + SetParameters(p, n); + RandomSource = new Random(); + } /// /// A string representation of the distribution. @@ -240,7 +248,7 @@ namespace MathNet.Numerics.Distributions // The cumulative density of p. var cp = Categorical.UnnormalizedCdf(p); -// The variable that stores the counts. + // The variable that stores the counts. var ret = new int[p.Length]; for (var i = 0; i < n; i++) diff --git a/src/Numerics/Distributions/Multivariate/NormalGamma.cs b/src/Numerics/Distributions/Multivariate/NormalGamma.cs index 46a9585a..c7152a2f 100644 --- a/src/Numerics/Distributions/Multivariate/NormalGamma.cs +++ b/src/Numerics/Distributions/Multivariate/NormalGamma.cs @@ -329,11 +329,11 @@ namespace MathNet.Numerics.Distributions } } - /* - /// /// Evaluates the probability density function for a NormalGamma distribution. /// + /// The mean/precision pair of the distribution + /// Density value public double Density(MeanPrecisionPair mp) { return Density(mp.Mean, mp.Precision); @@ -342,31 +342,38 @@ namespace MathNet.Numerics.Distributions /// /// Evaluates the probability density function for a NormalGamma distribution. /// + /// The mean of the distribution + /// The precision of the distribution + /// Density value public double Density(double mean, double prec) { if (Double.IsPositiveInfinity(_precisionInvScale) && _meanScale == 0.0) { throw new NotImplementedException(); } - else if (Double.IsPositiveInfinity(_precisionInvScale)) + + if (Double.IsPositiveInfinity(_precisionInvScale)) { throw new NotImplementedException(); } - else if (_meanScale == 0.0) + + if (_meanScale <= 0.0) { throw new NotImplementedException(); } - else - { - double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale; - return System.Math.Pow(prec * _precisionInvScale, _precisionShape) * System.Math.Exp(e) - / (Math.Constants.Sqrt2Pi * System.Math.Sqrt(prec) * Math.SpecialFunctions.Gamma(_precisionShape)); - } + + // double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale; + // return Math.Pow(prec * _precisionInvScale, _precisionShape) * Math.Exp(e) / (Constants.Sqrt2Pi * Math.Sqrt(prec) * SpecialFunctions.Gamma(_precisionShape)); + double e = -(0.5 * prec * _meanScale * (mean - _meanLocation) * (mean - _meanLocation)) - (prec * _precisionInvScale); + return Math.Pow(prec * _precisionInvScale, _precisionShape) * Math.Exp(e) * Math.Sqrt(_meanScale) + / (Constants.Sqrt2Pi * Math.Sqrt(prec) * SpecialFunctions.Gamma(_precisionShape)); } /// /// Evaluates the log probability density function for a NormalGamma distribution. /// + /// The mean/precision pair of the distribution + /// The log of the density value public double DensityLn(MeanPrecisionPair mp) { return DensityLn(mp.Mean, mp.Precision); @@ -375,27 +382,31 @@ namespace MathNet.Numerics.Distributions /// /// Evaluates the log probability density function for a NormalGamma distribution. /// + /// The mean of the distribution + /// The precision of the distribution + /// The log of the density value public double DensityLn(double mean, double prec) { if (Double.IsPositiveInfinity(_precisionInvScale) && _meanScale == 0.0) { throw new NotImplementedException(); } - else if (Double.IsPositiveInfinity(_precisionInvScale)) + + if (Double.IsPositiveInfinity(_precisionInvScale)) { throw new NotImplementedException(); } - else if (_meanScale == 0.0) + + if (_meanScale <= 0.0) { throw new NotImplementedException(); } - else - { - double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale; - return (_precisionShape - 0.5) * System.Math.Log(prec) + _precisionShape * System.Math.Log(_precisionInvScale) + e - - Math.Constants.LogSqrt2Pi - Math.SpecialFunctions.GammaLn(_precisionShape); - } - }*/ + + // double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale; + // return (_precisionShape - 0.5) * Math.Log(prec) + _precisionShape * Math.Log(_precisionInvScale) + e - Constants.LogSqrt2Pi - SpecialFunctions.GammaLn(_precisionShape); + double e = -(0.5 * prec * _meanScale * (mean - _meanLocation) * (mean - _meanLocation)) - (prec * _precisionInvScale); + return ((_precisionShape - 0.5) * Math.Log(prec)) + (_precisionShape * Math.Log(_precisionInvScale)) - (0.5 * Math.Log(_meanScale)) + e - Constants.LogSqrt2Pi - SpecialFunctions.GammaLn(_precisionShape); + } /// /// Generates a sample from the NormalGamma distribution. diff --git a/src/UnitTests/DistributionTests/Continuous/BetaTests.cs b/src/UnitTests/DistributionTests/Continuous/BetaTests.cs index 50b9f800..451cdcc3 100644 --- a/src/UnitTests/DistributionTests/Continuous/BetaTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/BetaTests.cs @@ -193,7 +193,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous } [Test] - [ExpectedException(typeof(NotImplementedException))] + [ExpectedException(typeof(NotSupportedException))] [Row(0.0, 0.0)] [Row(0.0, 0.1)] [Row(1.0, 0.0)] diff --git a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs index 82220efc..827f16d2 100644 --- a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs @@ -289,7 +289,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateCumulativeDistribution(double dof, double x) { var n = new ChiSquare(dof); - Assert.AreEqual(SpecialFunctions.GammaUpperIncomplete(dof / 2.0, x / 2.0) / SpecialFunctions.Gamma(dof / 2.0), n.CumulativeDistribution(x)); + Assert.AreEqual(SpecialFunctions.GammaLowerIncomplete(dof / 2.0, x / 2.0) / SpecialFunctions.Gamma(dof / 2.0), n.CumulativeDistribution(x)); } } } diff --git a/src/UnitTests/DistributionTests/Continuous/FisherSnedecorTests.cs b/src/UnitTests/DistributionTests/Continuous/FisherSnedecorTests.cs index 0c67e276..79cde221 100644 --- a/src/UnitTests/DistributionTests/Continuous/FisherSnedecorTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/FisherSnedecorTests.cs @@ -365,7 +365,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateCumulativeDistribution(double d1, double d2, double x) { var n = new FisherSnedecor(d1, d2); - Assert.AreEqual(SpecialFunctions.BetaRegularized(d1 / 2.0, d2 / 2.0, d1 * d2 / (d1 + d1 * d2)), n.CumulativeDistribution(x)); + Assert.AreEqual(SpecialFunctions.BetaRegularized(d1 / 2.0, d2 / 2.0, d1 * x / (d2 + x * d1)), n.CumulativeDistribution(x)); } } } diff --git a/src/UnitTests/DistributionTests/Continuous/InverseGammaTests.cs b/src/UnitTests/DistributionTests/Continuous/InverseGammaTests.cs index e45d824b..efd55bdd 100644 --- a/src/UnitTests/DistributionTests/Continuous/InverseGammaTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/InverseGammaTests.cs @@ -82,7 +82,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateToString() { var n = new InverseGamma(1.1, 2.1); - Assert.AreEqual("InverseGamma(Shape = 1.1, Inverse Scale = 2.1)", n.ToString()); + Assert.AreEqual(String.Format("InverseGamma(Shape = {0}, Inverse Scale = {1})", n.Shape, n.Scale), n.ToString()); } [Test] @@ -203,7 +203,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous } [Test] - [ExpectedException(typeof(NotImplementedException))] + [ExpectedException(typeof(NotSupportedException))] public void ValidateMedian() { var n = new InverseGamma(1.0, 1.0); @@ -291,7 +291,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateCumulativeDistribution(double a, double b, double x) { var n = new InverseGamma(a, b); - Assert.AreEqual(SpecialFunctions.GammaLowerIncomplete(a, b / x), n.CumulativeDistribution(x)); + Assert.AreEqual(SpecialFunctions.GammaUpperRegularized(a, b / x), n.CumulativeDistribution(x)); } } } diff --git a/src/UnitTests/DistributionTests/Continuous/ParetoTests.cs b/src/UnitTests/DistributionTests/Continuous/ParetoTests.cs index 56b0f7f7..89d5dd68 100644 --- a/src/UnitTests/DistributionTests/Continuous/ParetoTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/ParetoTests.cs @@ -169,7 +169,14 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateVariance(double scale, double shape) { var n = new Pareto(scale, shape); - Assert.AreEqual(scale * scale * shape / ((shape - 1.0) * (shape - 1.0) * (scale - 2.0)), n.Variance); + if (shape <= 2.0) + { + Assert.AreEqual(double.PositiveInfinity, n.Variance); + } + else + { + Assert.AreEqual(scale * scale * shape / ((shape - 1.0) * (shape - 1.0) * (shape - 2.0)), n.Variance); + } } [Test] diff --git a/src/UnitTests/DistributionTests/Continuous/StableTests.cs b/src/UnitTests/DistributionTests/Continuous/StableTests.cs index d35a9396..38ca48bb 100644 --- a/src/UnitTests/DistributionTests/Continuous/StableTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/StableTests.cs @@ -108,7 +108,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous public void ValidateToString() { var n = new Stable(1.2, 0.3, 1.0, 2.0); - Assert.AreEqual("Stable(Stability = 1.2, Skewness = 0.3, Scale = 1, Location = 2)", n.ToString()); + Assert.AreEqual(String.Format("Stable(Stability = {0}, Skewness = {1}, Scale = {2}, Location = {3})",n.Alpha, n.Beta, n.Scale, n.Location) , n.ToString()); } [Test] @@ -319,7 +319,6 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous } [Test] - [ExpectedException(typeof(NotImplementedException))] public void CanSample() { var n = new Stable(1.0, 1.0, 1.0, 1.0); @@ -327,7 +326,6 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous } [Test] - [ExpectedException(typeof(NotImplementedException))] public void CanSampleSequence() { var n = new Stable(1.0, 1.0, 1.0, 1.0); diff --git a/src/UnitTests/DistributionTests/Discrete/BernoulliTests.cs b/src/UnitTests/DistributionTests/Discrete/BernoulliTests.cs index 31e2600c..81d962b9 100644 --- a/src/UnitTests/DistributionTests/Discrete/BernoulliTests.cs +++ b/src/UnitTests/DistributionTests/Discrete/BernoulliTests.cs @@ -68,7 +68,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete public void ValidateToString() { var b = new Bernoulli(0.3); - Assert.AreEqual("Bernoulli(P = 0.3)", b.ToString()); + Assert.AreEqual(String.Format("Bernoulli(P = {0})", b.P), b.ToString()); } [Test] diff --git a/src/UnitTests/DistributionTests/Discrete/BinomialTests.cs b/src/UnitTests/DistributionTests/Discrete/BinomialTests.cs index d92bb70e..64c1e6af 100644 --- a/src/UnitTests/DistributionTests/Discrete/BinomialTests.cs +++ b/src/UnitTests/DistributionTests/Discrete/BinomialTests.cs @@ -69,7 +69,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete public void ValidateToString() { var b = new Binomial(0.3, 2); - Assert.AreEqual("Binomial(Success Probability = 0.3, Number of Trials = 2)", b.ToString()); + Assert.AreEqual(String.Format("Binomial(Success Probability = {0}, Number of Trials = {1})", b.P, b.N), b.ToString()); } [Test] diff --git a/src/UnitTests/DistributionTests/Discrete/GeometricTests.cs b/src/UnitTests/DistributionTests/Discrete/GeometricTests.cs index f9d48792..c9c6c219 100644 --- a/src/UnitTests/DistributionTests/Discrete/GeometricTests.cs +++ b/src/UnitTests/DistributionTests/Discrete/GeometricTests.cs @@ -68,7 +68,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete public void ValidateToString() { var d = new Geometric(0.3); - Assert.AreEqual("Geometric(P = 0.3)", d.ToString()); + Assert.AreEqual(String.Format("Geometric(P = {0})",d.P), d.ToString()); } [Test] @@ -103,11 +103,13 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete } [Test] - [ExpectedException(typeof(NotSupportedException))] - public void ValidateSkewness() + [Row(0.0)] + [Row(0.3)] + [Row(1.0)] + public void ValidateSkewness(double p) { - var d = new Geometric(0.3); - double s = d.Skewness; + var d = new Geometric(p); + Assert.AreEqual((2.0 - p) / Math.Sqrt(1.0 - p), d.Skewness); } [Test] @@ -138,11 +140,10 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete } [Test] - [ExpectedException(typeof(NotSupportedException))] public void ValidateMaximum() { var d = new Geometric(0.3); - int max = d.Maximum; + Assert.AreEqual(int.MaxValue, d.Maximum); } [Test] diff --git a/src/UnitTests/DistributionTests/Discrete/NegativeBinomialTests.cs b/src/UnitTests/DistributionTests/Discrete/NegativeBinomialTests.cs index 949ada36..d1e932b5 100644 --- a/src/UnitTests/DistributionTests/Discrete/NegativeBinomialTests.cs +++ b/src/UnitTests/DistributionTests/Discrete/NegativeBinomialTests.cs @@ -80,7 +80,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete public void ValidateToString() { var d = new NegativeBinomial(1.0, 0.3); - Assert.AreEqual("NegativeBinomial(R = 1, P = 0.3)", d.ToString()); + Assert.AreEqual(String.Format("NegativeBinomial(R = {0}, P = {1})", d.R, d.P), d.ToString()); } [Test] @@ -178,15 +178,14 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete public void ValidateMinimum() { var d = new NegativeBinomial(1.0, 0.5); - Assert.AreEqual(0, d.Minimum); + Assert.AreEqual(0, d.Minimum); } [Test] - [ExpectedException(typeof(Exception))] public void ValidateMaximum() { var d = new NegativeBinomial(1.0, 0.3); - int max = d.Maximum; + Assert.AreEqual(int.MaxValue, d.Maximum); } [Test] @@ -221,6 +220,22 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete Assert.AreEqual(SpecialFunctions.GammaLn(r + x) - SpecialFunctions.GammaLn(r) - SpecialFunctions.GammaLn(x + 1.0) + r * Math.Log(p) + x * Math.Log(1.0 - p), d.ProbabilityLn(x)); } + [Test] + [Row(0.0, 0.0, 5)] + [Row(0.0, 0.3, 3)] + [Row(0.0, 1.0, 0)] + [Row(0.1, 0.0, 2)] + [Row(0.1, 0.3, 1)] + [Row(0.1, 1.0, 2)] + [Row(1.0, 0.0, 2)] + [Row(1.0, 0.3, 10)] + [Row(1.0, 1.0, 5)] + public void ValidateCumulativeDistribution(double r, double p, int x) + { + var d = new NegativeBinomial(r, p); + Assert.AreApproximatelyEqual(SpecialFunctions.BetaRegularized(r, x + 1.0, p), d.CumulativeDistribution(x), 1e-12); + } + [Test] public void CanSample() { @@ -235,13 +250,5 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Discrete var ied = d.Samples(); var e = ied.Take(5).ToArray(); } - - [Test] - [ExpectedException(typeof(NotImplementedException))] - public void ValidateCumulativeDistribution() - { - var d = new NegativeBinomial(1.0, 0.5); - var cdx = d.CumulativeDistribution(1.5); - } } } \ No newline at end of file diff --git a/src/UnitTests/DistributionTests/Multivariate/MultinomialTests.cs b/src/UnitTests/DistributionTests/Multivariate/MultinomialTests.cs index c96b1d36..a3e13ac2 100644 --- a/src/UnitTests/DistributionTests/Multivariate/MultinomialTests.cs +++ b/src/UnitTests/DistributionTests/Multivariate/MultinomialTests.cs @@ -33,8 +33,9 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Multivariate using System; using MbUnit.Framework; using Distributions; + using Statistics; - [TestFixture] + [TestFixture] public class MultinomialTests { double[] badP; @@ -59,6 +60,28 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Multivariate Assert.AreEqual(largeP, m.P); } + [Test] + [MultipleAsserts] + public void CanCreateMultinomialFromHistogram() + { + double[] smallDataset = { 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5 }; + var hist = new Histogram(smallDataset, 10, 0.0, 10.0); + var m = new Multinomial(hist, 7); + + foreach (var t in m.P) + { + Assert.AreEqual(1.0, t); + } + } + + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void MultinomialCreateFailsWithNullHistogram() + { + Histogram h = null; + var m = new Categorical(h); + } + [Test] [ExpectedException(typeof(ArgumentOutOfRangeException))] public void MultinomialCreateFailsWithNegativeRatios() diff --git a/src/UnitTests/DistributionTests/Multivariate/NormalGammaTests.cs b/src/UnitTests/DistributionTests/Multivariate/NormalGammaTests.cs index 603d62aa..5fa03450 100644 --- a/src/UnitTests/DistributionTests/Multivariate/NormalGammaTests.cs +++ b/src/UnitTests/DistributionTests/Multivariate/NormalGammaTests.cs @@ -52,6 +52,15 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Multivariate Assert.AreEqual(precInvScale, ng.PrecisionInverseScale); } + [Test, MultipleAsserts] + [Row(0.0, 1.0, 1.0, 1.0)] + [Row(10.0, 1.0, 2.0, 2.0)] + public void CanGetDensityAndDensityLn(double meanLocation, double meanScale, double precShape, double precInvScale) + { + var ng = new NormalGamma(meanLocation, meanScale, precShape, precInvScale); + Assert.AreEqual(ng.DensityLn(meanLocation, precShape), Math.Log(ng.Density(meanLocation, precShape))); + } + [Test] [Row(1.0, -1.3, 2.0, 2.0)] [Row(1.0, 1.0, -1.0, 1.0)]