diff --git a/src/Numerics/Distributions/TruncatedNormal.cs b/src/Numerics/Distributions/TruncatedNormal.cs
index 72b33b58..1a1a57c3 100644
--- a/src/Numerics/Distributions/TruncatedNormal.cs
+++ b/src/Numerics/Distributions/TruncatedNormal.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -42,24 +42,27 @@ namespace MathNet.Numerics.Distributions {
///
public class TruncatedNormal : IContinuousDistribution
{
-
System.Random _random;
///
/// Mean of the untruncated normal distribution.
///
- readonly double _mu;
+ readonly double _mu;
+
///
/// Standard deviation of the uncorrected normal distribution.
///
readonly double _sigma;
+
readonly double _lowerBound;
readonly double _upperBound;
readonly Normal _standardNormal = new Normal(0.0, 1.0);
+
///
/// Position in the standard normal distribution of the lower bound.
///
readonly double _alpha;
+
///
/// Position in the standard normal distribution of the upper bound.
///
@@ -73,7 +76,7 @@ namespace MathNet.Numerics.Distributions {
///
/// Initializes a new instance of the TruncatedNormal class. The distribution will
- /// be initialized with the default random number generator. The mean
+ /// be initialized with the default random number generator. The mean
/// and standard deviation are that of the untruncated normal distribution.
///
/// The mean (μ) of the untruncated distribution.
@@ -81,10 +84,9 @@ namespace MathNet.Numerics.Distributions {
/// The inclusive lower bound of the truncated distribution. Default is double.NegativeInfinity.
/// The inclusive upper bound of the truncated distribution. Must be larger than .
/// Default is double.PositiveInfinity.
- public TruncatedNormal(double mean, double stddev, double lowerBound = double.NegativeInfinity, double upperBound = double.PositiveInfinity)
- :this(mean, stddev, SystemRandomSource.Default, lowerBound, upperBound)
+ public TruncatedNormal(double mean, double stddev, double lowerBound = double.NegativeInfinity, double upperBound = double.PositiveInfinity)
+ : this(mean, stddev, SystemRandomSource.Default, lowerBound, upperBound)
{
-
}
///
@@ -98,9 +100,9 @@ namespace MathNet.Numerics.Distributions {
/// The inclusive upper bound of the truncated distribution. Must be larger than .
/// Default is double.PositiveInfinity.
- public TruncatedNormal(double untruncatedMean, double untruncatedStdDev, System.Random randomSource, double lowerBound = double.NegativeInfinity, double upperBound = double.PositiveInfinity)
+ public TruncatedNormal(double untruncatedMean, double untruncatedStdDev, System.Random randomSource, double lowerBound = double.NegativeInfinity, double upperBound = double.PositiveInfinity)
{
- if (!IsValidParameterSet(untruncatedMean, untruncatedStdDev, lowerBound, upperBound))
+ if (!IsValidParameterSet(untruncatedMean, untruncatedStdDev, lowerBound, upperBound))
{
throw new ArgumentException(Resources.InvalidDistributionParameters);
}
@@ -121,23 +123,24 @@ namespace MathNet.Numerics.Distributions {
///
/// The mean (μ) of the normal distribution.
/// The standard deviation (σ) of the normal distribution. Range: σ > 0.
- public static bool IsValidParameterSet(double mean, double stddev, double lowerBound, double upperBound)
+ public static bool IsValidParameterSet(double mean, double stddev, double lowerBound, double upperBound)
{
bool normalRequirements = Normal.IsValidParameterSet(mean, stddev) && stddev > 0;
bool boundsAreOrdered = lowerBound < upperBound;
return normalRequirements && boundsAreOrdered;
}
- public override string ToString() {
+ public override string ToString()
+ {
return "TruncatedNormal(μ = " + _mu + ", σ = " + _sigma +", LowerBound = " + _lowerBound + ", UpperBound = " + _upperBound + ")";
}
- ///
- /// Gets the mode of the normal distribution.
- ///
- public double Mode
+ ///
+ /// Gets the mode of the truncated normal distribution.
+ ///
+ public double Mode
{
- get
+ get
{
if (_mu < _lowerBound)
return _lowerBound;
@@ -150,7 +153,7 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the minimum of the truncated normal distribution.
///
- public double Minimum
+ public double Minimum
{
get { return _lowerBound; }
}
@@ -158,7 +161,7 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the maximum of the truncated normal distribution.
///
- public double Maximum
+ public double Maximum
{
get { return _upperBound; }
}
@@ -166,9 +169,9 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the mean (μ) of the truncated normal distribution.
///
- public double Mean
+ public double Mean
{
- get
+ get
{
var pdfDifference = _standardNormal.Density(_alpha) - _standardNormal.Density(_beta);
var diffFromUncorrected = pdfDifference * _sigma / _cumulativeDensityWithinBounds;
@@ -177,11 +180,11 @@ namespace MathNet.Numerics.Distributions {
}
///
- /// Gets the variance of the truncated normal distribution.
+ /// Gets the variance of the truncated normal distribution.
///
- public double Variance
+ public double Variance
{
- get
+ get
{
//Apparently "Barr and Sherrill (1999)" has a simpler expression for one sided truncations, if anyone has access...
@@ -209,7 +212,7 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the standard deviation (σ) of the truncated normal distribution. Range: σ > 0.
///
- public double StdDev
+ public double StdDev
{
get { return Math.Sqrt(Variance); }
}
@@ -217,9 +220,9 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the entropy of the truncated normal distribution.
///
- public double Entropy
+ public double Entropy
{
- get
+ get
{
var firstTerm = Constants.LogSqrt2PiE + Math.Log(_sigma + _cumulativeDensityWithinBounds);
@@ -232,7 +235,7 @@ namespace MathNet.Numerics.Distributions {
public double Skewness
{
- get
+ get
{
throw new NotImplementedException();
}
@@ -241,9 +244,9 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets the median of the truncated distribution.
///
- public double Median
+ public double Median
{
- get
+ get
{
return InverseCumulativeDistribution(0.5);
}
@@ -252,7 +255,7 @@ namespace MathNet.Numerics.Distributions {
///
/// Gets or sets the random number generator which is used to draw random samples.
///
- public System.Random RandomSource
+ public System.Random RandomSource
{
get { return _random; }
set { _random = value ?? SystemRandomSource.Default; }
@@ -264,7 +267,7 @@ namespace MathNet.Numerics.Distributions {
/// The location at which to compute the density.
/// the density at .
///
- public double Density(double x)
+ public double Density(double x)
{
if (x < _lowerBound || _upperBound < x)
return 0d;
@@ -278,29 +281,30 @@ namespace MathNet.Numerics.Distributions {
/// The location at which to compute the log density.
/// the log density at .
///
- public double DensityLn(double x)
+ public double DensityLn(double x)
{
return _standardNormal.DensityLn((x - _mu) / _sigma) - Math.Log(_sigma) - Math.Log(_cumulativeDensityWithinBounds);
- }
+ }
-
- public double Sample()
+ public double Sample()
{
//TODO: implement sampling more efficiently/accurately, use method described by Mazet here: http://miv.u-strasbg.fr/mazet/rtnorm/
// see implementations listed on that page for examples.
return InverseCumulativeDistribution(RandomSource.NextDouble());
}
- public void Samples(double[] values)
+ public void Samples(double[] values)
{
- for(int i = 0; i < values.Length; i++) {
+ for(int i = 0; i < values.Length; i++)
+ {
values[i] = Sample();
}
}
- public IEnumerable Samples()
+ public IEnumerable Samples()
{
- while (true) {
+ while (true)
+ {
yield return Sample();
}
}
@@ -311,7 +315,7 @@ namespace MathNet.Numerics.Distributions {
/// The location at which to compute the cumulative distribution function.
/// the cumulative distribution at location .
///
- public double CumulativeDistribution(double x)
+ public double CumulativeDistribution(double x)
{
if (x < _lowerBound)
return 0d;
@@ -329,13 +333,12 @@ namespace MathNet.Numerics.Distributions {
/// The location at which to compute the inverse cumulative density.
/// the inverse cumulative density at .
///
- public double InverseCumulativeDistribution(double p)
+ public double InverseCumulativeDistribution(double p)
{
//TODO check that this is correct with someone.
var pUntruncated = p * _cumulativeDensityWithinBounds + _standardNormal.CumulativeDistribution(_alpha);
return _standardNormal.InverseCumulativeDistribution(pUntruncated) * _sigma + _mu;
}
-
}
}
diff --git a/src/UnitTests/DistributionTests/CommonDistributionTests.cs b/src/UnitTests/DistributionTests/CommonDistributionTests.cs
index 82fcb5f4..2bd0d656 100644
--- a/src/UnitTests/DistributionTests/CommonDistributionTests.cs
+++ b/src/UnitTests/DistributionTests/CommonDistributionTests.cs
@@ -89,8 +89,8 @@ namespace MathNet.Numerics.UnitTests.DistributionTests
new StudentT(0.0, 1.0, 5.0),
new Triangular(0, 1, 0.7),
new Weibull(1.0, 1.0),
- new TruncatedNormal(0, 1.0, -1.0, 1.5), //Finite
- new TruncatedNormal(0, 1.0, -0.5), //Semi-finite
+ new TruncatedNormal(0, 1.0, -1.0, 1.5), //Finite
+ new TruncatedNormal(0, 1.0, -0.5), //Semi-finite
};
[Test]
diff --git a/src/UnitTests/DistributionTests/Continuous/TruncatedNormalTests.cs b/src/UnitTests/DistributionTests/Continuous/TruncatedNormalTests.cs
index 98a4b3fd..3c357e46 100644
--- a/src/UnitTests/DistributionTests/Continuous/TruncatedNormalTests.cs
+++ b/src/UnitTests/DistributionTests/Continuous/TruncatedNormalTests.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2014 Math.NET
+// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -31,16 +31,13 @@
using MathNet.Numerics.Distributions;
using NUnit.Framework;
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Threading.Tasks;
-namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
+namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
{
[TestFixture, Category("Distributions")]
- public class TruncatedNormalTests
+ public class TruncatedNormalTests
{
-
///
/// Can create a truncated normal without bounds.
///
@@ -50,7 +47,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(0.0, 10.0)]
[TestCase(10.0, 100.0)]
[TestCase(-5.0, Double.PositiveInfinity)]
- public void CanCreateWithoutBounds(double mean, double stdDev)
+ public void CanCreateWithoutBounds(double mean, double stdDev)
{
var truncatedNormal = new TruncatedNormal(mean, stdDev);
Assert.IsTrue(double.IsNegativeInfinity(truncatedNormal.Minimum));
@@ -68,7 +65,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
///
[TestCase(0.0, -1.0,-10d, 10d)]
[TestCase(0.0, 1.0, 10d, 9d)]
- public void TruncatedNormalCreateFailsWithBadParameters(double mean, double stdDev, double lower, double upper)
+ public void TruncatedNormalCreateFailsWithBadParameters(double mean, double stdDev, double lower, double upper)
{
Assert.That(() => new TruncatedNormal(mean, stdDev, lower, upper), Throws.ArgumentException);
}
@@ -78,7 +75,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(-6.0, 1.0, -5.0, 5.0)]
[TestCase(8.0, 1.0, -5.0, 5.0)]
[TestCase(15, 20.0, -20.0, 0.0)]
- public void ValidateMode(double mean, double stdDev, double lower, double upper)
+ public void ValidateMode(double mean, double stdDev, double lower, double upper)
{
double mode;
if(mean < lower) {
@@ -108,10 +105,10 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(6.0, .69146246127401310363770461060833773988360217555457859)]
[TestCase(10.0, 0.9937903346742238648330218954258077788721022530769078)]
[TestCase(Double.PositiveInfinity, 1.0)]
- public void ValidateCumulativeNoBounds(double x, double p)
+ public void ValidateCumulativeNoBounds(double x, double p)
{
var truncatedNormal = new TruncatedNormal(5.0, 2.0);
- AssertHelpers.AlmostEqualRelative(p, truncatedNormal.CumulativeDistribution(x), 14);
+ AssertHelpers.AlmostEqualRelative(p, truncatedNormal.CumulativeDistribution(x), 14);
}
///
@@ -130,7 +127,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(6.0, .69146246127401310363770461060833773988360217555457859)]
[TestCase(10.0, 0.9937903346742238648330218954258077788721022530769078)]
[TestCase(Double.PositiveInfinity, 1.0)]
- public void ValidateInverseCumulativeNoBounds(double x, double p)
+ public void ValidateInverseCumulativeNoBounds(double x, double p)
{
var truncatedNormal = new TruncatedNormal(5.0, 2.0);
AssertHelpers.AlmostEqualRelative(x, truncatedNormal.InverseCumulativeDistribution(p), 14);
@@ -147,7 +144,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(0.0, 10.0)]
[TestCase(10.0, 100.0)]
[TestCase(-5.0, Double.PositiveInfinity)]
- public void ValidateDensityNoBounds(double mean, double sdev)
+ public void ValidateDensityNoBounds(double mean, double sdev)
{
var n = new TruncatedNormal(mean, sdev);
for (var i = 0; i < 11; i++) {
@@ -159,7 +156,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
}
///
- /// Validate density when only one bound is are specified.
+ /// Validate density when only one bound is are specified.
///
/// Mean value.
/// Standard deviation value.
@@ -168,11 +165,11 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(0.0, 10.0, -10.0)]
[TestCase(10.0, 100.0, 15.0)]
[TestCase(-5.0, Double.PositiveInfinity, -5.0)]
- public void ValidateDensitySemiFinite(double mean, double sdev, double lowerBound)
+ public void ValidateDensitySemiFinite(double mean, double sdev, double lowerBound)
{
var truncatedNormal = new TruncatedNormal(mean, sdev, lowerBound);
var normal = new Normal(mean, sdev);
- for (var i = 0; i < 11; i++)
+ for (var i = 0; i < 11; i++)
{
var x = i - 5.0;
double density;
@@ -180,7 +177,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
{
density = 0d;
}
- else
+ else
{
var d = (mean - x) / sdev;
var pdf = Math.Exp(-0.5 * d * d) / (sdev * Constants.Sqrt2Pi);
@@ -200,19 +197,19 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(0.0, 10.0, -10.0, 15.0)]
[TestCase(10.0, 100.0, 15.0, 100.0)]
[TestCase(-5.0, Double.PositiveInfinity, -5.0, 0.0)]
- public void ValidateDensityFinite(double mean, double sdev, double lowerBound, double upperBound)
+ public void ValidateDensityFinite(double mean, double sdev, double lowerBound, double upperBound)
{
var truncatedNormal = new TruncatedNormal(mean, sdev, lowerBound, upperBound);
var normal = new Normal(mean, sdev);
- for (var i = 0; i < 11; i++)
+ for (var i = 0; i < 11; i++)
{
var x = i - 5.0;
double density;
- if (x < lowerBound || upperBound < x)
+ if (x < lowerBound || upperBound < x)
{
density = 0d;
- }
- else
+ }
+ else
{
var d = (mean - x) / sdev;
var pdf = Math.Exp(-0.5 * d * d) / (sdev * Constants.Sqrt2Pi);
@@ -224,7 +221,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
///
- /// Validate density log when no bounds are specified. Uses same
+ /// Validate density log when no bounds are specified. Uses same
/// test cases as the Normal distribution as should be equivalent in this case.
///
/// Mean value.
@@ -234,10 +231,10 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
[TestCase(0.0, 10.0)]
[TestCase(10.0, 100.0)]
[TestCase(-5.0, Double.PositiveInfinity)]
- public void ValidateDensityLnNoBounds(double mean, double sdev)
+ public void ValidateDensityLnNoBounds(double mean, double sdev)
{
var n = new TruncatedNormal(mean, sdev);
- for (var i = 0; i < 11; i++)
+ for (var i = 0; i < 11; i++)
{
var x = i - 5.0;
var d = (mean - x) / sdev;
@@ -247,7 +244,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
}
[Test]
- public void CanSample()
+ public void CanSample()
{
var truncatedNormal = new TruncatedNormal(5.0, 2.0, -10, 10.0);
truncatedNormal.Sample();
@@ -258,7 +255,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous
/// Can sample sequence.
///
[Test]
- public void CanSampleSequence()
+ public void CanSampleSequence()
{
var truncatedNormal = new TruncatedNormal(5.0, 2.0, -10, 10.0);
var ied = truncatedNormal.Samples();