From 0dc05c2139ac475d690c0543729bd02bafad1ded Mon Sep 17 00:00:00 2001 From: Jurgen Van Gael Date: Sun, 15 Nov 2009 00:30:27 +0800 Subject: [PATCH] Added a unit test for the distributions. --- src/Numerics/Statistics/Histogram.cs | 10 + .../CommonDistributionTests.cs | 171 ++++++++++++++---- 2 files changed, 148 insertions(+), 33 deletions(-) diff --git a/src/Numerics/Statistics/Histogram.cs b/src/Numerics/Statistics/Histogram.cs index 2fe05db2..687d730c 100644 --- a/src/Numerics/Statistics/Histogram.cs +++ b/src/Numerics/Statistics/Histogram.cs @@ -345,6 +345,16 @@ namespace MathNet.Numerics.Statistics } } + /// + /// Returns the Bucket with index . + /// + /// The index of the bucket to retrieve. + /// A reference to the bucket at index . + public Bucket GetBucket(int i) + { + return buckets[i]; + } + /// /// Returns the Bucket that contains the value v. /// diff --git a/src/UnitTests/DistributionTests/CommonDistributionTests.cs b/src/UnitTests/DistributionTests/CommonDistributionTests.cs index 33969d4e..2cc8e001 100644 --- a/src/UnitTests/DistributionTests/CommonDistributionTests.cs +++ b/src/UnitTests/DistributionTests/CommonDistributionTests.cs @@ -1,4 +1,4 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // http://mathnet.opensourcedotnet.info // @@ -30,63 +30,168 @@ namespace MathNet.Numerics.UnitTests.DistributionTests { using System; using System.Linq; + using System.Collections.Generic; using MbUnit.Framework; using MathNet.Numerics.Distributions; + using MathNet.Numerics.Statistics; [TestFixture] public class CommonDistributionTests { - private IDistribution[] dists; + // The number of samples we want. + private int numberOfTestSamples = 100000; + // The accuracy of the histograms. + private double sampleAccuracy = 0.01; + // The number of buckets to use to test against the cdf. + private int numberOfBuckets = 100; + // The list of discrete distributions which we test. + private List discreteDistributions; + // The list of continuous distributions which we test. + private List continuousDistributions; [SetUp] public void SetupDistributions() { - dists = new IDistribution[10]; - - dists[0] = new Beta(1.0, 1.0); - dists[1] = new ContinuousUniform(0.0, 1.0); - dists[2] = new Gamma(1.0, 1.0); - dists[3] = new Normal(0.0, 1.0); - dists[4] = new Bernoulli(0.6); - dists[5] = new Weibull(1.0, 1.0); - dists[6] = new DiscreteUniform(1, 10); - dists[7] = new LogNormal(1.0, 1.0); - dists[8] = new Binomial(0.7, 10); - dists[9] = new Categorical(new double[] { 0.7, 0.3 }); + discreteDistributions = new List(); + discreteDistributions.Add(new Bernoulli(0.6)); + discreteDistributions.Add(new Binomial(0.7, 10)); + discreteDistributions.Add(new Categorical(new double[] { 0.7, 0.3 })); + discreteDistributions.Add(new DiscreteUniform(1, 10)); + + continuousDistributions = new List(); + continuousDistributions.Add(new Beta(1.0, 1.0)); + continuousDistributions.Add(new ContinuousUniform(0.0, 1.0)); + continuousDistributions.Add(new Gamma(1.0, 1.0)); + continuousDistributions.Add(new Normal(0.0, 1.0)); + continuousDistributions.Add(new Weibull(1.0, 1.0)); + continuousDistributions.Add(new LogNormal(1.0, 1.0)); } [Test] - [Row(0)] - [Row(1)] - [Row(2)] - [Row(3)] - [Row(4)] + [MultipleAsserts] public void ValidateThatUnivariateDistributionsHaveRandomSource(int i) { - Assert.IsNotNull(dists[i].RandomSource); + foreach(var dd in discreteDistributions) + { + Assert.IsNotNull(dd.RandomSource); + } + + foreach(var cd in continuousDistributions) + { + Assert.IsNotNull(cd.RandomSource); + } } [Test] - [Row(0)] - [Row(1)] - [Row(2)] - [Row(3)] - [Row(4)] + [MultipleAsserts] public void CanSetRandomSource(int i) { - dists[i].RandomSource = new Random(); + foreach(var dd in discreteDistributions) + { + dd.RandomSource = new Random(); + } + + foreach(var cd in continuousDistributions) + { + cd.RandomSource = new Random(); + } } [Test] - [Row(0)] - [Row(1)] - [Row(2)] - [Row(3)] - [Row(4)] - [ExpectedException(typeof(ArgumentNullException))] + [MultipleAsserts] public void FailSetRandomSourceWithNullReference(int i) { - dists[i].RandomSource = null; + foreach(var dd in discreteDistributions) + { + Assert.Throws(() => dd.RandomSource = null); + } + + foreach(var cd in continuousDistributions) + { + Assert.Throws(() => cd.RandomSource = null); + } + } + + [Test] + [MultipleAsserts] + public void SampleFollowsCorrectDistribution() + { + // The test samples from the distributions, builds a histogram and checks + // whether the histogram follows the CDF. + foreach (var dd in discreteDistributions) + { + int[] samples = new int[numberOfTestSamples]; + for (int i = 0; i < numberOfTestSamples; i++) + { + samples[i] = dd.Sample(); + } + + var histogram = new Histogram(samples.Select(x => (double)x), numberOfBuckets); + for (int i = 0; i < numberOfBuckets; i++) + { + var bucket = histogram.GetBucket(i); + double empiricalProbability = bucket.Count / (double)numberOfTestSamples; + double realProbability = dd.CumulativeDistribution(bucket.UpperBound) + - dd.CumulativeDistribution(bucket.LowerBound); + Assert.LessThan(Math.Abs(empiricalProbability - realProbability), sampleAccuracy); + } + } + + foreach (var cd in continuousDistributions) + { + double[] samples = new double[numberOfTestSamples]; + for (int i = 0; i < numberOfTestSamples; i++) + { + samples[i] = cd.Sample(); + } + + var histogram = new Histogram(samples, numberOfBuckets); + for (int i = 0; i < numberOfBuckets; i++) + { + var bucket = histogram.GetBucket(i); + double empiricalProbability = bucket.Count / (double)numberOfTestSamples; + double realProbability = cd.CumulativeDistribution(bucket.UpperBound) + - cd.CumulativeDistribution(bucket.LowerBound); + Assert.LessThan(Math.Abs(empiricalProbability - realProbability), sampleAccuracy); + } + } + } + + [Test] + [MultipleAsserts] + public void SamplesFollowsCorrectDistribution() + { + // The test samples from the distributions, builds a histogram and checks + // whether the histogram follows the CDF. + foreach (var dd in discreteDistributions) + { + var samples = dd.Samples().Take(numberOfTestSamples).Select(x => (double)x); + + var histogram = new Histogram(samples, numberOfBuckets); + for (int i = 0; i < numberOfBuckets; i++) + { + var bucket = histogram.GetBucket(i); + double empiricalProbability = bucket.Count / (double)numberOfTestSamples; + double realProbability = dd.CumulativeDistribution(bucket.UpperBound) + - dd.CumulativeDistribution(bucket.LowerBound); + Assert.LessThan(Math.Abs(empiricalProbability - realProbability), sampleAccuracy); + } + } + + foreach (var cd in continuousDistributions) + { + var samples = cd.Samples().Take(numberOfTestSamples); + + var histogram = new Histogram(samples, numberOfBuckets); + for (int i = 0; i < numberOfBuckets; i++) + { + var bucket = histogram.GetBucket(i); + double empiricalProbability = bucket.Count / (double)numberOfTestSamples; + double realProbability = cd.CumulativeDistribution(bucket.UpperBound) + - cd.CumulativeDistribution(bucket.LowerBound); + Assert.LessThan(Math.Abs(empiricalProbability - realProbability), sampleAccuracy); + } + } } } }