From 806f26e0af4984f72e33d057196dc683a601e686 Mon Sep 17 00:00:00 2001 From: Jurgen Van Gael Date: Fri, 14 Aug 2009 16:29:24 +0800 Subject: [PATCH] Added Dirichlet distribution. Signed-off-by: jvangael --- .../Distributions/Multivariate/Dirichlet.cs | 252 ++++++++++++++++++ src/Numerics/Numerics.csproj | 2 +- .../Multivariate/DirichletTests.cs | 62 +++++ src/UnitTests/UnitTests.csproj | 2 +- 4 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 src/Numerics/Distributions/Multivariate/Dirichlet.cs create mode 100644 src/UnitTests/DistributionTests/Multivariate/DirichletTests.cs diff --git a/src/Numerics/Distributions/Multivariate/Dirichlet.cs b/src/Numerics/Distributions/Multivariate/Dirichlet.cs new file mode 100644 index 00000000..dc059e93 --- /dev/null +++ b/src/Numerics/Distributions/Multivariate/Dirichlet.cs @@ -0,0 +1,252 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +namespace dnAnalytics.Statistics.Distributions +{ + using System; + using Properties; + + /// + /// Implements the multivariate Dirichlet distribution. For details about this distribution, see + /// Wikipedia - Dirichlet distribution. + /// + /// The distribution will use the by default. + /// Users can get/set the random number generator by using the property. + /// 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 + /// to false, all parameter checks can be turned off. + public class Dirichlet + { + // The Dirichlet distribution parameters. + private readonly double[] _alpha; + + /// + /// The distribution's random number generator. + /// + private Random _random; + + /// + /// Initializes a new instance of the Dirichlet class. The distribution will + /// be initialized with the default random number generator. + /// + /// An array with the Dirichlet parameters. + public Dirichlet(double[] alpha) + { + SetParameters(alpha); + RandomSource = new Random(); + } + + /// + /// Constructs a new symmetric Dirichlet distribution. The distribution will + /// be initialized with the default random number generator. + /// + /// The value of each parameter of the Dirichlet distribution. + /// The dimension of the Dirichlet distribution. + public Dirichlet(double alpha, int k) + { + // Create a parameter structure. + double[] parm = new double[k]; + for (int i = 0; i < k; i++) + { + parm[i] = alpha; + } + + SetParameters(parm); + RandomSource = new Random(); + } + + /// + /// Checks whether the parameters of the distribution are valid: no parameter can be less than zero and + /// at least one parameter should be larger than zero. + /// + /// The parameters of the Dirichlet distribution. + /// True when the parameters are valid, false otherwise. + public static bool IsValidParameterSet(double[] alpha) + { + bool allzero = true; + + for (int i = 0; i < alpha.Length; i++) + { + if (alpha[i] < 0.0) + { + return false; + } + else if (alpha[i] > 0.0) + { + allzero = false; + } + } + + if (allzero) + { + return false; + } + } + + /// + /// Sets the parameters of the distribution after checking their validity. + /// + /// The parameters of the Dirichlet distribution. + /// When the parameters don't pass the function. + private void SetParameters(double[] alpha) + { + if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha) && ! alpha.Length == _alpha.Length) + { + throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters); + } + + for (int i = 0; i < alpha.Length; i++) + { + _alpha[i] = alpha[i]; + } + } + + /// + /// A string representation of the distribution. + /// + public override string ToString() + { + return "Dirichlet(Dimension = " + this.Dimension + ")"; + } + + /// + /// Gets the dimension of the Dirichlet distribution. + /// + public int Dimension + { + get { return _alpha.Length; } + } + + /// + /// The parameters of the Dirichlet distribution. + /// + public double[] Alpha + { + get { return _alpha; } + } + + /// + /// The sum of the Dirichlet parameters. + /// + private double AlphaSum + { + get + { + double s = 0.0; + for (int i = 0; i < _alpha.Length; i++) + { + s += _alpha[i]; + } + return s; + } + } + + /// + /// Gets the mean of the Dirichlet distribution. + /// + public double[] Mean + { + get { return _alpha / AlphaSum; } + } + + /// + /// Gets the variance of the Dirichlet distribution. + /// + public double[] Variance + { + get + { + double s = this.AlphaSum; + double[] v = new double[_alpha.Length]; + for (int i = 0; i < _alpha.Length; i++) + { + v[i] = _alpha[i]*(s - _alpha[i])/(s*s*(s + 1.0)); + } + return v; + } + } + + /// + /// Gets or sets the random number generator which is used to draw random samples. + /// + public Random RandomSource + { + get + { + return _random; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + + _random = value; + } + } + + /// + /// Samples a Dirichlet distributed random vector. + /// + public double[] Sample() + { + return Sample(RandomSource, _alpha); + } + + /// + /// Samples a Dirichlet distributed random vector. + /// + /// The random number generator to use. + /// The Dirichlet distribution parameter. + public static double[] Sample(System.Random rnd, double[] alpha) + { + if (Control.CheckDistributionParameters && ! IsValidParameterSet(alpha)) + { + throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters); + } + + int n = alpha.Length; + double[] gv = new double[n]; + double sum = 0.0; + for (int i = 0; i < n; i++) + { + gv[i] = Gamma.Sample(rnd, alpha[i], 1.0); + sum += gv[i]; + } + + for (int i = 0; i < n; i++) + { + gv[i] /= sum; + } + + return gv; + } + } +} \ No newline at end of file diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 8e8c3add..d976fe73 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -56,6 +56,7 @@ + @@ -121,7 +122,6 @@ -