Browse Source

Fixes dirichlet distribution (multivariate beta) density function (pdf). Closes gh-9.

la-knuth
Christoph Ruegg 15 years ago
parent
commit
4455e9f6e1
  1. 35
      src/Numerics/Distributions/Multivariate/Dirichlet.cs
  2. 2
      src/Numerics/NumberTheory/IntegerTheory.cs
  3. 22
      src/UnitTests/DistributionTests/Multivariate/DirichletTests.cs

35
src/Numerics/Distributions/Multivariate/Dirichlet.cs

@ -3,7 +3,9 @@
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET //
// Copyright (c) 2009-2011 Math.NET
//
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -12,8 +14,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
//
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -251,42 +255,45 @@ namespace MathNet.Numerics.Distributions
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
var flag = x.Length == (_alpha.Length - 1); var shortVersion = x.Length == (_alpha.Length - 1);
if ((x.Length != _alpha.Length) && !flag) if ((x.Length != _alpha.Length) && !shortVersion)
{ {
throw new ArgumentException("x"); throw new ArgumentException("x");
} }
var num = 0.0; var term = 0.0;
var num2 = 0.0; var sumxi = 0.0;
var sumalpha = 0.0;
for (var i = 0; i < x.Length; i++) for (var i = 0; i < x.Length; i++)
{ {
var d = x[i]; var xi = x[i];
if ((d <= 0.0) || (d >= 1.0)) if ((xi <= 0.0) || (xi >= 1.0))
{ {
return 0.0; return 0.0;
} }
num += (_alpha[i] - 1.0) * Math.Log(d); term += (_alpha[i] - 1.0) * Math.Log(xi) - SpecialFunctions.GammaLn(_alpha[i]);
num2 += d; sumxi += xi;
sumalpha += _alpha[i];
} }
// Calculate x[Length - 1] element, if needed // Calculate x[Length - 1] element, if needed
if (flag) if (shortVersion)
{ {
if (num2 >= 1.0) if (sumxi >= 1.0)
{ {
return 0.0; return 0.0;
} }
num += (_alpha[_alpha.Length - 1] - 1.0) * Math.Log(1.0 - num2); term += (_alpha[_alpha.Length - 1] - 1.0) * Math.Log(1.0 - sumxi) - SpecialFunctions.GammaLn(_alpha[_alpha.Length - 1]);
sumalpha += _alpha[_alpha.Length - 1];
} }
else if (!num2.AlmostEqualInDecimalPlaces(1.0, 8)) else if (!sumxi.AlmostEqualInDecimalPlaces(1.0, 8))
{ {
return 0.0; return 0.0;
} }
return -SpecialFunctions.GammaLn(AlphaSum) + num; return term + SpecialFunctions.GammaLn(sumalpha);
} }
/// <summary> /// <summary>

2
src/Numerics/NumberTheory/IntegerTheory.cs

@ -32,7 +32,7 @@ namespace MathNet.Numerics.NumberTheory
{ {
using System; using System;
/// <summary> /// <summary>
/// Number theory utility functions for integers. /// Number theory utility functions for integers.
/// </summary> /// </summary>
public static partial class IntegerTheory public static partial class IntegerTheory

22
src/UnitTests/DistributionTests/Multivariate/DirichletTests.cs

@ -202,8 +202,11 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Multivariate
/// </summary> /// </summary>
/// <param name="x">Alphas array.</param> /// <param name="x">Alphas array.</param>
/// <param name="res">Expected value.</param> /// <param name="res">Expected value.</param>
[TestCase(new[] { 0.01, 0.03, 0.5 }, 1335.32600710379)] /// <remarks>
[TestCase(new[] { 0.1, 0.2, 0.3, 0.4 }, 59.1446044600076)] /// Mathematica: InputForm[PDF[DirichletDistribution[{0.1, 0.3, 0.5, 0.8}], {0.01, 0.03, 0.5}]]
/// </remarks>
[TestCase(new[] { 0.01, 0.03, 0.5 }, 18.77225681167061)]
[TestCase(new[] { 0.1, 0.2, 0.3, 0.4 }, 0.8314656481199253)]
public void ValidateDensity(double[] x, double res) public void ValidateDensity(double[] x, double res)
{ {
var d = new Dirichlet(new[] { 0.1, 0.3, 0.5, 0.8 }); var d = new Dirichlet(new[] { 0.1, 0.3, 0.5, 0.8 });
@ -222,6 +225,21 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Multivariate
AssertHelpers.AlmostEqual(d.DensityLn(x), Math.Log(d.Density(x)), 12); AssertHelpers.AlmostEqual(d.DensityLn(x), Math.Log(d.Density(x)), 12);
} }
/// <summary>
/// Validate density log matches Beta for 2-dimension cases
/// </summary>
/// <param name="x">Alpha array.</param>
[TestCase(0.01)]
[TestCase(0.1)]
[TestCase(0.4)]
[TestCase(0.71)]
public void ValidateBetaSpecialCaseDensityLn(double x)
{
var d = new Dirichlet(new[] { 0.1, 0.3 });
var beta = new Beta(0.1, 0.3);
AssertHelpers.AlmostEqual(d.DensityLn(new[] { x }), beta.DensityLn(x), 10);
}
/// <summary> /// <summary>
/// Validate entropy. /// Validate entropy.
/// </summary> /// </summary>

Loading…
Cancel
Save