diff --git a/src/Numerics/Distributions/Discrete/Categorical.cs b/src/Numerics/Distributions/Discrete/Categorical.cs
index 9cde7e6d..75a4e7af 100644
--- a/src/Numerics/Distributions/Discrete/Categorical.cs
+++ b/src/Numerics/Distributions/Discrete/Categorical.cs
@@ -50,7 +50,7 @@ namespace MathNet.Numerics.Distributions
public class Categorical : IDiscreteDistribution
{
///
- /// Stores the normalized categorical probabilities.
+ /// Stores the unnormalized categorical probabilities.
///
private double[] _p;
@@ -71,24 +71,31 @@ namespace MathNet.Numerics.Distributions
RandomSource = new System.Random();
}
- /* TODO
///
- /// Generate a categorical distribution from histogram . The distribution will
- /// not be automatically updated when the histogram changes.
+ /// Initializes a new instance of the Categorical class from a histogram . The distribution
+ /// will not be automatically updated when the histogram changes. The categorical distribution will have
+ /// one value for each bucket and a probability for that value proportional to the bucket count.
///
- public Categorical(Histogram h)
+ /// The histogram from which to create the categorical variable.
+ public Categorical(Histogram histogram)
{
+ if (histogram == null)
+ {
+ throw new ArgumentNullException("Cannot create a categorical variable from a null histogram.");
+ }
+
// The probability distribution vector.
- _p = new double[h.BinCount];
+ double[] p = new double[histogram.BucketCount];
// Fill in the distribution vector.
- for (int i = 0; i < h.BinCount; i++)
+ for (int i = 0; i < histogram.BucketCount; i++)
{
- _p[i] = h[i];
+ p[i] = histogram[i].Count;
}
- RandomNumberGenerator = new System.Random();
- }*/
+ SetParameters(p);
+ RandomSource = new System.Random();
+ }
///
/// A string representation of the distribution.
@@ -144,13 +151,28 @@ namespace MathNet.Numerics.Distributions
}
///
- /// Gets or sets the probability of generating a one.
+ /// Gets or sets the normalized probability vector of the multinomial.
///
+ /// Note that sometimes the normalized probability vector cannot be represented
+ /// exactly in a floating point representation.
public double[] P
{
get
{
- return (double[]) _p.Clone();
+ double[] p = (double[]) _p.Clone();
+
+ double sum = 0.0;
+ for (int i = 0; i < p.Length; i++)
+ {
+ sum += p[i];
+ }
+
+ for (int i = 0; i < p.Length; i++)
+ {
+ p[i] /= sum;
+ }
+
+ return p;
}
set
diff --git a/src/UnitTests/DistributionTests/Discrete/CategoricalTests.cs b/src/UnitTests/DistributionTests/Discrete/CategoricalTests.cs
index 34e21bf2..e1b9e915 100644
--- a/src/UnitTests/DistributionTests/Discrete/CategoricalTests.cs
+++ b/src/UnitTests/DistributionTests/Discrete/CategoricalTests.cs
@@ -32,6 +32,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests
using System.Linq;
using MbUnit.Framework;
using MathNet.Numerics.Distributions;
+ using MathNet.Numerics.Statistics;
[TestFixture]
public class CategoricalTests
@@ -55,7 +56,28 @@ namespace MathNet.Numerics.UnitTests.DistributionTests
public void CanCreateCategorical()
{
var m = new Categorical(largeP);
- AssertEx.AreEqual(largeP, m.P);
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanCreateCategoricalFromHistogram()
+ {
+ double[] smallDataset = { 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5 };
+ Histogram hist = new Histogram(smallDataset, 10, 0.0, 10.0);
+ var m = new Categorical(hist);
+
+ for (int i = 0; i <= m.Maximum; i++)
+ {
+ AssertEx.AreEqual(1.0/10.0, m.P[i]);
+ }
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void CategoricalCreateFailsWithNullHistogram()
+ {
+ Histogram h = null;
+ var m = new Categorical(h);
}
[Test]