diff --git a/src/Numerics/Statistics/MCMC/HybridMC.cs b/src/Numerics/Statistics/MCMC/HybridMC.cs
index fce1b158..6381e050 100644
--- a/src/Numerics/Statistics/MCMC/HybridMC.cs
+++ b/src/Numerics/Statistics/MCMC/HybridMC.cs
@@ -115,7 +115,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// The number of iterations in between returning samples.
/// When the number of burnInterval iteration is negative.
public HybridMC(double[] x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval) :
- this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, new double[x0.Count()], new DiffMethod(HybridMC.Grad))
+ this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, new double[x0.Count()], new System.Random(), new DiffMethod(HybridMC.Grad))
{
for (int i = 0; i < Length; i++)
{ mpSdv[i] = 1; }
@@ -137,16 +137,36 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// the components of the momentum.
/// When the number of burnInterval iteration is negative.
public HybridMC(double[] x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double[] pSdv) :
- this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, new DiffMethod(HybridMC.Grad))
+ this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, new System.Random())
{ }
+ ///
+ /// Constructs a new Hybrid Monte Carlo sampler for a multivariate probability distribution.
+ /// The components of the momentum will be sampled from a normal distribution with standard deviation
+ /// specified by pSdv using the a random number generator provided by the user.
+ /// A three point estimation will be used for differentiation.
+ /// This constructor will set the burn interval.
+ ///
+ /// The initial sample.
+ /// The log density of the distribution we want to sample from.
+ /// Number frogleap simulation steps.
+ /// Size of the frogleap simulation steps.
+ /// The number of iterations in between returning samples.
+ /// The standard deviations of the normal distributions that are used to sample
+ /// the components of the momentum.
+ /// Random number generator used for sampling the momentum.
+ /// When the number of burnInterval iteration is negative.
+ public HybridMC(double[] x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double[] pSdv, System.Random randomSource) :
+ this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, randomSource, new DiffMethod(HybridMC.Grad))
+ { }
+
+
///
/// Constructs a new Hybrid Monte Carlo sampler for a multivariate probability distribution.
/// The components of the momentum will be sampled from a normal distribution with standard deviations
- /// given by pSdv using the default random
- /// number generator. This constructor will set both the burn interval and the method used for
- /// numerical differentiation.
+ /// given by pSdv. This constructor will set the burn interval, the method used for
+ /// numerical differentiation and the random number generator.
///
/// The initial sample.
/// The log density of the distribution we want to sample from.
@@ -155,11 +175,12 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// The number of iterations in between returning samples.
/// The standard deviations of the normal distributions that are used to sample
/// the components of the momentum.
+ /// Random number generator used for sampling the momentum.
/// The method used for numerical differentiation.
/// When the number of burnInterval iteration is negative.
/// When the length of pSdv is not the same as x0.
- public HybridMC(double[] x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double[] pSdv, DiffMethod diff)
- : base(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, diff)
+ public HybridMC(double[] x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double[] pSdv, System.Random randomSource, DiffMethod diff)
+ : base(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, randomSource, diff)
{
Length = x0.Count();
MomentumStdDev = pSdv;
@@ -170,6 +191,8 @@ namespace MathNet.Numerics.Statistics.Mcmc
}
+
+
#endregion
diff --git a/src/Numerics/Statistics/MCMC/HybridMCGeneric.cs b/src/Numerics/Statistics/MCMC/HybridMCGeneric.cs
index 5a73a0d9..ef89f225 100644
--- a/src/Numerics/Statistics/MCMC/HybridMCGeneric.cs
+++ b/src/Numerics/Statistics/MCMC/HybridMCGeneric.cs
@@ -38,7 +38,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
{
using Distributions;
using Properties;
-
+
///
/// The Hybrid (also called Hamiltonian) Monte Carlo produces samples from distribition P using a set
/// of Hamiltonian equations to guide the sampling process. It uses the negative of the log density as
@@ -71,7 +71,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
protected T mCurrent;
- ///
+ ///
/// The number of burn iterations between two samples.
///
protected int mBurnInterval;
@@ -105,8 +105,8 @@ namespace MathNet.Numerics.Statistics.Mcmc
set
{
- mBurnInterval = SetNonNegative(value);
-
+ mBurnInterval = SetNonNegative(value);
+
}
}
@@ -119,7 +119,8 @@ namespace MathNet.Numerics.Statistics.Mcmc
get { return mfrogLeapSteps; }
set
- { mfrogLeapSteps = SetPositive(value);
+ {
+ mfrogLeapSteps = SetPositive(value);
}
}
@@ -128,10 +129,11 @@ namespace MathNet.Numerics.Statistics.Mcmc
///
/// When step size is negative or zero.
public double StepSize
- { get { return mstepSize; }
+ {
+ get { return mstepSize; }
set
{
- mstepSize = SetPositive(value);
+ mstepSize = SetPositive(value);
}
}
@@ -147,18 +149,19 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// Number frogleap simulation steps.
/// Size of the frogleap simulation steps.
/// The number of iterations in between returning samples.
+ /// Random number generator used for sampling the momentum.
/// The method used for differentiation.
/// When the number of burnInterval iteration is negative.
/// When either x0, pdfLnP or diff is null.
- public HybridMCGeneric(T x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, DiffMethod diff)
+ public HybridMCGeneric(T x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, System.Random randomSource, DiffMethod diff)
{
- Energy = new DensityLn(x=>-pdfLnP(x));
+ Energy = new DensityLn(x => -pdfLnP(x));
FrogLeapSteps = frogLeapSteps;
StepSize = stepSize;
BurnInterval = burnInterval;
- mCurrent = x0;
+ mCurrent = x0;
Diff = diff;
-
+ RandomSource = randomSource;
}
#endregion
@@ -256,7 +259,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// Scalar factor multiplying by the second vector/scalar.
/// Second vector/scalar.
abstract protected void DoAdd(ref T first, double factor, T second);
-
+
///
/// Multiplying the second vector/scalar by factor and then subtract it from
/// the first vector/scalar.
@@ -285,7 +288,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
DoAdd(ref mNew, mstepSize, p);
gNew = Diff(Energy, mNew);
DoSubtract(ref p, mstepSize / 2, gNew);
-
+
}
///
@@ -339,7 +342,7 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// Throws when value is negative or zero.
protected int SetPositive(int value)
{
- if (value <=0)
+ if (value <= 0)
{
throw new ArgumentOutOfRangeException(Resources.ArgumentNotNegative);
}
diff --git a/src/Numerics/Statistics/MCMC/UnivariateHybridMC.cs b/src/Numerics/Statistics/MCMC/UnivariateHybridMC.cs
index 242e73a5..f2a45a34 100644
--- a/src/Numerics/Statistics/MCMC/UnivariateHybridMC.cs
+++ b/src/Numerics/Statistics/MCMC/UnivariateHybridMC.cs
@@ -121,14 +121,35 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// the momentum.
/// When the number of burnInterval iteration is negative.
public UnivariateHybridMC(double x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double pSdv) :
- this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, new DiffMethod(UnivariateHybridMC.Grad))
+ this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, new System.Random())
{ }
+ ///
+ /// Constructs a new Hybrid Monte Carlo sampler for a univariate probability distribution.
+ /// The momentum will be sampled from a normal distribution with standard deviation
+ /// specified by pSdv using a random
+ /// number generator provided by the user. A three point estimation will be used for differentiation.
+ /// This constructor will set the burn interval.
+ ///
+ /// The initial sample.
+ /// The log density of the distribution we want to sample from.
+ /// Number frogleap simulation steps.
+ /// Size of the frogleap simulation steps.
+ /// The number of iterations in between returning samples.
+ /// The standard deviation of the normal distribution that is used to sample
+ /// the momentum.
+ /// Random number generator used to sample the momentum.
+ /// When the number of burnInterval iteration is negative.
+ public UnivariateHybridMC(double x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double pSdv, System.Random randomSource) :
+ this(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, pSdv, randomSource, new DiffMethod(UnivariateHybridMC.Grad))
+ { }
+
+
///
/// Constructs a new Hybrid Monte Carlo sampler for a multivariate probability distribution.
/// The momentum will be sampled from a normal distribution with standard deviation
- /// given by pSdv using the default random
- /// number generator. This constructor will set both the burn interval and the method used for
+ /// given by pSdv using a random
+ /// number generator provided by the user. This constructor will set both the burn interval and the method used for
/// numerical differentiation.
///
/// The initial sample.
@@ -139,9 +160,10 @@ namespace MathNet.Numerics.Statistics.Mcmc
/// The standard deviation of the normal distribution that is used to sample
/// the momentum.
/// The method used for numerical differentiation.
+ /// Random number generator used for sampling the momentum.
/// When the number of burnInterval iteration is negative.
- public UnivariateHybridMC(double x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double pSdv, DiffMethod diff)
- : base(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, diff)
+ public UnivariateHybridMC(double x0, DensityLn pdfLnP, int frogLeapSteps, double stepSize, int burnInterval, double pSdv, System.Random randomSource, DiffMethod diff)
+ : base(x0, pdfLnP, frogLeapSteps, stepSize, burnInterval, randomSource, diff)
{
MomentumStdDev = pSdv;
pDistribution = new Normal(0, MomentumStdDev);
diff --git a/src/UnitTests/StatisticsTests/MCMCTests/HybridMCTest.cs b/src/UnitTests/StatisticsTests/MCMCTests/HybridMCTest.cs
index f99cffc8..53f0c6a5 100644
--- a/src/UnitTests/StatisticsTests/MCMCTests/HybridMCTest.cs
+++ b/src/UnitTests/StatisticsTests/MCMCTests/HybridMCTest.cs
@@ -133,29 +133,18 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests.McmcTests
///
/// Test the sampler using a bivariate normal distribution with randomly selected mean and standard deviation.
- /// It is a statistical test and may not pass all the time.
+ /// It is a statistical test and may not pass all the time. Note that Sdv and rho have to be between 0 and 1.
///
- [Test]
- public void SampleTest()
+ [TestCase(new double[2]{0.8,0.2}, new double[2]{3.2,-4.6}, 0.77,1000)]
+ [TestCase(new double[2] { 0.5, 0.1 }, new double[2] { -2.2, -1.3 }, 0.29, 1000)]
+ [TestCase(new double[2] { 0.45, 0.78 }, new double[2] { 1.34, -3.3 }, 0.58, 1000)]
+ public void SampleTest(double[] Sdv, double[] Mean, double rho, int seed)
{
- //Variances and Means
- double[] Sdv = new double[2];
- double[] Mean = new double[2];
- for (int i = 0; i < 2; i++)
- {
- Sdv[i] = RandomVar();
- Mean[i] = 5 * rnd.NextDouble();
-
- }
-
- //Cross Variance
- double rho = 1.0 - RandomVar();
-
DensityLn pdfLn = new DensityLn(x => LogDen(x, Sdv, Mean, rho));
- HybridMC Hybrid = new HybridMC(new double[2] { 0, 0 }, pdfLn, 10, 0.1, 1000);
+ HybridMC Hybrid = new HybridMC(new double[2] { 0, 0 }, pdfLn, 10, 0.1, 1000,new double[2]{1,1},new System.Random(seed));
Hybrid.BurnInterval = 0;
@@ -192,18 +181,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests.McmcTests
}
#region Helper Methods
- ///
- /// Generator for standard deviations and means used in SampleTest.
- ///
- /// A random number between 0.1 and 1.
- private double RandomVar()
- {
- double Var = 0;
- while (Var <= 0.1)
- { Var = rnd.NextDouble(); }
- return Var;
- }
-
+
///
/// The log density of the bivariate normal distribution used in SampleTest.
///
diff --git a/src/UnitTests/StatisticsTests/MCMCTests/UnivariateHybridMCTest.cs b/src/UnitTests/StatisticsTests/MCMCTests/UnivariateHybridMCTest.cs
index a4869854..d71d2931 100644
--- a/src/UnitTests/StatisticsTests/MCMCTests/UnivariateHybridMCTest.cs
+++ b/src/UnitTests/StatisticsTests/MCMCTests/UnivariateHybridMCTest.cs
@@ -55,10 +55,6 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests.McmcTests
///
private Normal normal = new Normal(0.0, 1.0);
- ///
- ///Random number generator to be used in the test.
- ///
- private MersenneTwister rnd = new MersenneTwister();
///
/// Testing the constructor to make sure that RandomSource is
@@ -130,19 +126,18 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests.McmcTests
/// Test the sampler using normal distribution with randomly selected mean and standard deviation.
/// It is a statistical test and may not pass all the time.
///
- [Test]
- public void SampleTest()
+ [TestCase(-4.987, 3.3, 1000)]
+ [TestCase(3.987, 1.2, 1000)]
+ [TestCase(-2.987, 4.3, 1000)]
+ public void SampleTest(double Mean, double Sdv, int seed)
{
- double Mean = 5 * rnd.NextDouble();
- double Sdv = 5 * rnd.NextDouble();
Normal dis = new Normal(Mean, Sdv);
- UnivariateHybridMC Hybrid = new UnivariateHybridMC(0, dis.DensityLn, 10, 0.1, 1000);
+ UnivariateHybridMC Hybrid = new UnivariateHybridMC(0, dis.DensityLn, 10, 0.1, 1000, 1, new System.Random(seed));
Hybrid.BurnInterval = 0;
-
double[] Sample = Hybrid.Sample(10000);
- double Effective = MCMCDiagnostics.EffectiveSize(Sample,x=>x);
+ double Effective = MCMCDiagnostics.EffectiveSize(Sample, x => x);
DescriptiveStatistics Stats = new DescriptiveStatistics(Sample);
@@ -155,7 +150,6 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests.McmcTests
//Approximating chi-square with normal distribution. (Degree of freedom is large)
double DeviationConvergence = 3 * Math.Sqrt(2) / Math.Sqrt(Effective);
-
Assert.AreEqual(DeviationRation, 1, DeviationConvergence, "Standard Deivation");
}
}