|
|
@ -1,4 +1,4 @@ |
|
|
// <copyright file="Combinatorics.cs" company="Math.NET">
|
|
|
// <copyright file="Normal.cs" company="Math.NET">
|
|
|
// Math.NET Numerics, part of the Math.NET Project
|
|
|
// Math.NET Numerics, part of the Math.NET Project
|
|
|
// http://mathnet.opensourcedotnet.info
|
|
|
// http://mathnet.opensourcedotnet.info
|
|
|
//
|
|
|
//
|
|
|
@ -37,13 +37,18 @@ namespace MathNet.Numerics.Distributions |
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public class Normal : IContinuousDistribution |
|
|
public class Normal : IContinuousDistribution |
|
|
{ |
|
|
{ |
|
|
// Keeps track of the mean of the normal distribution.
|
|
|
/// <summary>
|
|
|
|
|
|
/// Keeps track of the mean of the normal distribution.
|
|
|
|
|
|
/// </summary>
|
|
|
private double mMean; |
|
|
private double mMean; |
|
|
// Keeps track of the standard deviation of the normal distribution.
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Keeps track of the standard deviation of the normal distribution.
|
|
|
|
|
|
/// </summary>
|
|
|
private double mStdDev; |
|
|
private double mStdDev; |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Constructs a standard normal distribution. This is a normal distribution with mean 0.0
|
|
|
/// Initializes a new instance of the Normal class. This is a normal distribution with mean 0.0
|
|
|
/// and standard deviation 1.0. The distribution will
|
|
|
/// and standard deviation 1.0. The distribution will
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
@ -52,7 +57,7 @@ namespace MathNet.Numerics.Distributions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Construct a normal distribution with a particular mean and standard deviation. The distribution will
|
|
|
/// Initializes a new instance of the Normal class with a particular mean and standard deviation. The distribution will
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
@ -69,6 +74,7 @@ namespace MathNet.Numerics.Distributions |
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution.</param>
|
|
|
|
|
|
/// <returns>a normal distribution.</returns>
|
|
|
public static Normal WithMeanStdDev(double mean, double stddev) |
|
|
public static Normal WithMeanStdDev(double mean, double stddev) |
|
|
{ |
|
|
{ |
|
|
return new Normal(mean, stddev); |
|
|
return new Normal(mean, stddev); |
|
|
@ -79,7 +85,8 @@ namespace MathNet.Numerics.Distributions |
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="stddev">The variance of the normal distribution.</param>
|
|
|
/// <param name="var">The variance of the normal distribution.</param>
|
|
|
|
|
|
/// <returns>a normal distribution.</returns>
|
|
|
public static Normal WithMeanVariance(double mean, double var) |
|
|
public static Normal WithMeanVariance(double mean, double var) |
|
|
{ |
|
|
{ |
|
|
return new Normal(mean, System.Math.Sqrt(var)); |
|
|
return new Normal(mean, System.Math.Sqrt(var)); |
|
|
@ -90,16 +97,17 @@ namespace MathNet.Numerics.Distributions |
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution.</param>
|
|
|
/// <param name="stddev">The precision of the normal distribution.</param>
|
|
|
/// <param name="prec">The precision of the normal distribution.</param>
|
|
|
|
|
|
/// <returns>a normal distribution.</returns>
|
|
|
public static Normal WithMeanAndPrecision(double mean, double prec) |
|
|
public static Normal WithMeanAndPrecision(double mean, double prec) |
|
|
{ |
|
|
{ |
|
|
return new Normal(mean, 1.0 / System.Math.Sqrt(prec)); |
|
|
return new Normal(mean, 1.0 / System.Math.Sqrt(prec)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// A string representation of the distribution.
|
|
|
/// A string representation of the distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>a string representation of the distribution.</returns>
|
|
|
public override string ToString() |
|
|
public override string ToString() |
|
|
{ |
|
|
{ |
|
|
return "Normal(Mean = " + mMean + ", StdDev = " + mStdDev + ")"; |
|
|
return "Normal(Mean = " + mMean + ", StdDev = " + mStdDev + ")"; |
|
|
@ -149,23 +157,38 @@ namespace MathNet.Numerics.Distributions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The precision of the normal distribution.
|
|
|
/// Gets or sets the precision of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Precision |
|
|
public double Precision |
|
|
{ |
|
|
{ |
|
|
get { return 1.0 / (mStdDev * mStdDev); } |
|
|
get |
|
|
set { SetParameters(mMean, 1.0/Math.Sqrt(value)); } |
|
|
{ |
|
|
|
|
|
return 1.0 / (mStdDev * mStdDev); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set |
|
|
|
|
|
{ |
|
|
|
|
|
double sdev = 1.0/Math.Sqrt(value); |
|
|
|
|
|
|
|
|
|
|
|
// Handle the case when the precision is -0.
|
|
|
|
|
|
if(Double.IsInfinity(sdev)) |
|
|
|
|
|
{ |
|
|
|
|
|
sdev = Double.PositiveInfinity; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SetParameters(mMean, sdev); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#region IDistribution implementation
|
|
|
#region IDistribution implementation
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The random number generator which is used to draw random samples.
|
|
|
/// Gets or sets the random number generator which is used to draw random samples.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public Random RandomSource { get; set; } |
|
|
public Random RandomSource { get; set; } |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The mean of the normal distribution.
|
|
|
/// Gets or sets the mean of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Mean |
|
|
public double Mean |
|
|
{ |
|
|
{ |
|
|
@ -174,7 +197,7 @@ namespace MathNet.Numerics.Distributions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The variance of the normal distribution.
|
|
|
/// Gets or sets the variance of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Variance |
|
|
public double Variance |
|
|
{ |
|
|
{ |
|
|
@ -183,7 +206,7 @@ namespace MathNet.Numerics.Distributions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The standard deviation of the normal distribution.
|
|
|
/// Gets or sets the standard deviation of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double StdDev |
|
|
public double StdDev |
|
|
{ |
|
|
{ |
|
|
@ -192,42 +215,61 @@ namespace MathNet.Numerics.Distributions |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The entropy of the normal distribution.
|
|
|
/// Gets the entropy of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Entropy { get { return Math.Log(mStdDev) + Constants.LogSqrt2PiE; } } |
|
|
public double Entropy |
|
|
|
|
|
{ |
|
|
|
|
|
get { return Math.Log(mStdDev) + Constants.LogSqrt2PiE; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The skewness of the normal distribution.
|
|
|
/// Gets the skewness of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Skewness { get { return 0.0; } } |
|
|
public double Skewness |
|
|
|
|
|
{ |
|
|
|
|
|
get { return 0.0; } |
|
|
|
|
|
} |
|
|
#endregion
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
#region IContinuousDistribution implementation
|
|
|
#region IContinuousDistribution implementation
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The mode of the normal distribution.
|
|
|
/// Gets the mode of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Mode { get { return mMean; } } |
|
|
public double Mode |
|
|
|
|
|
{ |
|
|
|
|
|
get { return mMean; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The median of the normal distribution.
|
|
|
/// Gets the median of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Median { get { return mMean; } } |
|
|
public double Median |
|
|
|
|
|
{ |
|
|
|
|
|
get { return mMean; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The minimum of the normal distribution.
|
|
|
/// Gets the minimum of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Minimum { get { return System.Double.NegativeInfinity; } } |
|
|
public double Minimum |
|
|
|
|
|
{ |
|
|
|
|
|
get { return System.Double.NegativeInfinity; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// The maximum of the normal distribution.
|
|
|
/// Gets the maximum of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public double Maximum { get { return System.Double.PositiveInfinity; } } |
|
|
public double Maximum |
|
|
|
|
|
{ |
|
|
|
|
|
get { return System.Double.PositiveInfinity; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Computes the density of the normal distribution.
|
|
|
/// Computes the density of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="x">The location at which to compute the density.</param>
|
|
|
/// <param name="x">The location at which to compute the density.</param>
|
|
|
|
|
|
/// <returns>the density at <paramref name="x"/>.</returns>
|
|
|
public double Density(double x) |
|
|
public double Density(double x) |
|
|
{ |
|
|
{ |
|
|
double d = (x - mMean) / mStdDev; |
|
|
double d = (x - mMean) / mStdDev; |
|
|
@ -238,26 +280,37 @@ namespace MathNet.Numerics.Distributions |
|
|
/// Computes the log density of the normal distribution.
|
|
|
/// Computes the log density of the normal distribution.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="x">The location at which to compute the log density.</param>
|
|
|
/// <param name="x">The location at which to compute the log density.</param>
|
|
|
|
|
|
/// <returns>the log density at <paramref name="x"/>.</returns>
|
|
|
public double DensityLn(double x) |
|
|
public double DensityLn(double x) |
|
|
{ |
|
|
{ |
|
|
double d = (x - mMean) / mStdDev; |
|
|
double d = (x - mMean) / mStdDev; |
|
|
return -0.5 * d * d - Math.Log(mStdDev) - Constants.LogSqrt2Pi; |
|
|
return (-0.5 * d * d) - Math.Log(mStdDev) - Constants.LogSqrt2Pi; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public double CumulativeDistribution(double x) { throw new NotImplementedException(); } |
|
|
/// <summary>
|
|
|
|
|
|
/// Computes the cumulative distribution function of the normal distribution.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="x">The location at which to compute the cumulative density.</param>
|
|
|
|
|
|
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
|
|
|
|
|
|
public double CumulativeDistribution(double x) |
|
|
|
|
|
{ |
|
|
|
|
|
return 0.5 * (1.0 + SpecialFunctions.Erf((x - mMean) / (mStdDev * System.Math.Sqrt(2.0)))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Generates a sample from the normal distribution using the <i>Box-Muller</i> algorithm.
|
|
|
/// Generates a sample from the normal distribution using the <i>Box-Muller</i> algorithm.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>a sample from the distribution.</returns>
|
|
|
public double Sample() |
|
|
public double Sample() |
|
|
{ |
|
|
{ |
|
|
double r2; |
|
|
double r2; |
|
|
return mMean + mStdDev * SampleBoxMuller(RandomSource, out r2); |
|
|
return mMean + (mStdDev * SampleBoxMuller(RandomSource, out r2)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Generates a sequence of samples from the normal distribution using the <i>Box-Muller</i> algorithm.
|
|
|
/// Generates a sequence of samples from the normal distribution using the <i>Box-Muller</i> algorithm.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>a sequence of samples from the distribution.</returns>
|
|
|
public IEnumerable<double> Samples() |
|
|
public IEnumerable<double> Samples() |
|
|
{ |
|
|
{ |
|
|
double r2; |
|
|
double r2; |
|
|
@ -265,15 +318,20 @@ namespace MathNet.Numerics.Distributions |
|
|
while (true) |
|
|
while (true) |
|
|
{ |
|
|
{ |
|
|
double r1 = SampleBoxMuller(RandomSource, out r2); |
|
|
double r1 = SampleBoxMuller(RandomSource, out r2); |
|
|
yield return mMean + mStdDev * r1; |
|
|
yield return mMean + (mStdDev * r1); |
|
|
yield return mMean + mStdDev * r2; |
|
|
yield return mMean + (mStdDev * r2); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#endregion
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Computes the inverse cumulative distribution function of the normal distribution.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="p">The location at which to compute the inverse cumulative density.</param>
|
|
|
|
|
|
/// <returns>the inverse cumulative density at <paramref name="x"/>.</returns>
|
|
|
public double InverseCumulativeDistribution(double p) |
|
|
public double InverseCumulativeDistribution(double p) |
|
|
{ |
|
|
{ |
|
|
throw new NotImplementedException(); |
|
|
return mMean - (mStdDev * System.Math.Sqrt(2.0) * SpecialFunctions.ErfcInv(2.0 * p)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
@ -282,10 +340,11 @@ namespace MathNet.Numerics.Distributions |
|
|
/// <param name="rng">The random number generator to use.</param>
|
|
|
/// <param name="rng">The random number generator to use.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution from which to generate samples.</param>
|
|
|
|
|
|
/// <returns>a sample from the distribution.</returns>
|
|
|
public static double Sample(System.Random rng, double mean, double stddev) |
|
|
public static double Sample(System.Random rng, double mean, double stddev) |
|
|
{ |
|
|
{ |
|
|
double r2; |
|
|
double r2; |
|
|
return mean + stddev * SampleBoxMuller(rng, out r2); |
|
|
return mean + (stddev * SampleBoxMuller(rng, out r2)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
@ -294,6 +353,7 @@ namespace MathNet.Numerics.Distributions |
|
|
/// <param name="rng">The random number generator to use.</param>
|
|
|
/// <param name="rng">The random number generator to use.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="mean">The mean of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution from which to generate samples.</param>
|
|
|
/// <param name="stddev">The standard deviation of the normal distribution from which to generate samples.</param>
|
|
|
|
|
|
/// <returns>a sequence of samples from the distribution.</returns>
|
|
|
public static IEnumerable<double> Samples(System.Random rng, double mean, double stddev) |
|
|
public static IEnumerable<double> Samples(System.Random rng, double mean, double stddev) |
|
|
{ |
|
|
{ |
|
|
double r2; |
|
|
double r2; |
|
|
@ -301,8 +361,8 @@ namespace MathNet.Numerics.Distributions |
|
|
while(true) |
|
|
while(true) |
|
|
{ |
|
|
{ |
|
|
double r1 = SampleBoxMuller(rng, out r2); |
|
|
double r1 = SampleBoxMuller(rng, out r2); |
|
|
yield return mean + stddev * r1; |
|
|
yield return mean + (stddev * r1); |
|
|
yield return mean + stddev * r2; |
|
|
yield return mean + (stddev * r2); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -310,18 +370,20 @@ namespace MathNet.Numerics.Distributions |
|
|
/// Samples a pair of standard normal distributed random variables using the <i>Box-Muller</i> algorithm.
|
|
|
/// Samples a pair of standard normal distributed random variables using the <i>Box-Muller</i> algorithm.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="rnd">The random number generator to use.</param>
|
|
|
/// <param name="rnd">The random number generator to use.</param>
|
|
|
/// <param name="r2">The second random number.</param>
|
|
|
/// <param name="r2">A second random number from the standard normal distribution computed as a side product.</param>
|
|
|
|
|
|
/// <returns>a random number from the standard normal distribution.</returns>
|
|
|
internal static double SampleBoxMuller(System.Random rnd, out double r2) |
|
|
internal static double SampleBoxMuller(System.Random rnd, out double r2) |
|
|
{ |
|
|
{ |
|
|
double v1 = 2.0 * rnd.NextDouble() - 1.0; |
|
|
double v1 = (2.0 * rnd.NextDouble()) - 1.0; |
|
|
double v2 = 2.0 * rnd.NextDouble() - 1.0; |
|
|
double v2 = (2.0 * rnd.NextDouble()) - 1.0; |
|
|
double r = v1 * v1 + v2 * v2; |
|
|
double r = (v1 * v1) + (v2 * v2); |
|
|
while (r >= 1.0 || r == 0.0) |
|
|
while (r >= 1.0 || r == 0.0) |
|
|
{ |
|
|
{ |
|
|
v1 = 2.0 * rnd.NextDouble() - 1.0; |
|
|
v1 = (2.0 * rnd.NextDouble()) - 1.0; |
|
|
v2 = 2.0 * rnd.NextDouble() - 1.0; |
|
|
v2 = (2.0 * rnd.NextDouble()) - 1.0; |
|
|
r = v1 * v1 + v2 * v2; |
|
|
r = (v1 * v1) + (v2 * v2); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
double fac = System.Math.Sqrt(-2.0 * System.Math.Log(r) / r); |
|
|
double fac = System.Math.Sqrt(-2.0 * System.Math.Log(r) / r); |
|
|
r2 = v2 * fac; |
|
|
r2 = v2 * fac; |
|
|
return v1 * fac; |
|
|
return v1 * fac; |
|
|
|