/// \file DistributionModel.cs
///
/// Contains the class that serves as the base class for various random number generator, it also serves as the utility class for random number generation using uniform random distribution
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/*! \mainpage HiddenMarkovModels.MathUtils Source Code Documentation
*
* HiddenMarkovModels.MathUtils provides the math functions to be used in various simulation, machine learning, mining, and optimization package in the SimuKit framework
*
* The library currently contains a set of random number generator with various distribution models which includes:
*
* - Uniform Distribution
* - Erlang Distribution
* - Gaussian Distribution
* - Poisson Distribution
* - LogNormal Distribution
* - Exponential Distribution
*
*/
namespace BotSharp.Algorithm.HiddenMarkovModel.MathUtils.Distribution
{
///
/// Class that serves as the base class for various random number generator, it also serves as the utility class for random number generation using uniform random distribution
///
public abstract class DistributionModel
{
///
/// Variable representing the the seed of the generator (the default value is the one used by Marsaglia)
///
private static uint m_w = 521288629;
///
/// Variable representing another seed that forms the pair of unsigned integers with m_w (the default value is the one used by Marsaglia)
///
private static uint m_z = 362436069;
///
/// Method that returns a randomly generated double value
///
///
public abstract double Next();
///
/// Member variable representing the mean of the underlying distribution
///
protected double mMean = 0;
///
/// Member variable representing the standard deviation of the underlying distribution
///
protected double mStdDev = 1;
///
/// Method that sets the seed for the random number generator
///
///
public static void SetSeed(uint u)
{
m_w = u;
}
public abstract DistributionModel Clone();
///
/// Method that returns a randomly generated double value in the range (0, 1)
///
/// A randomly generated double value in the range (0, 1)
public static double GetUniform()
{
// 0 <= u < 2^32
uint u = GetUint();
// The magic number below is 1/(2^32 + 2).
// The result is strictly between 0 and 1.
return (u + 1.0) * 2.328306435454494e-10;
}
///
/// Method that return a randomly generated unsigned integer.
/// The method uses George Marsaglia's MWC algorithm to produce an unsigned integer.
/// Please refers to http://www.bobwheeler.com/statistics/Password/MarsagliaPost.txt
///
/// A randomly generated unsigned integer
private static uint GetUint()
{
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
///
/// Method that set the seed using the system time
///
public static void SetSeedFromSystemTime()
{
System.DateTime dt = System.DateTime.Now;
long x = dt.ToFileTime();
SetSeed((uint)(x >> 16), (uint)(x % 4294967296));
}
///
/// Method that sets the two seeds of the random number generator
///
/// The first seed
/// The second seed
public static void SetSeed(uint u, uint v)
{
if (u != 0) m_w = u;
if (v != 0) m_z = v;
}
///
/// Constructor
///
/// The seed for the random number generator
public DistributionModel(uint seed)
{
SetSeed(seed);
}
///
/// Constructor
///
public DistributionModel()
{
SetSeedFromSystemTime();
}
///
/// Property representing the mean of the underlying distribution model
///
public double Mean
{
get { return mMean; }
set { mMean = value; }
}
public double Variance
{
get { return mStdDev * mStdDev; }
set { mStdDev = System.Math.Sqrt(value); }
}
///
/// Property representing the standard deviation of the underlying distribution model
///
public double StdDev
{
get { return mStdDev; }
set { mStdDev = value; }
}
///
/// Method that returns a randomly generated integer in the range [0, upper_bound)
///
/// The upper bound for the randomly generated integer (exclusive)
/// A randomly generated integer in the range [0, upper_bound)
public static int NextInt(int upper_bound)
{
if (upper_bound == 0) return 0;
return (int)(GetUint() % (uint)upper_bound);
}
///
/// Return the log of either PDF(x) or PMF(x) (if PDF is not defined for the distribution)
///
/// value for the variable
/// The log of either PDF(x) or PMF(x) (if PDF is not defined for the distribution)
public abstract double LogProbabilityFunction(double x);
public abstract void Process(double[] values);
public abstract void Process(double[] values, double[] weights);
public abstract double GetPDF(double x); //return the probability density function for x
public abstract double GetCDF(double x); //return the cumulative density function for x: P(X <= x)
///
/// Return the value for probability mass function at value x
///
///
/// P(X = x)
public virtual double GetPMF(int x)
{
throw new NotImplementedException();
}
public static void Shuffle(T[] data)
{
int indexer = 0;
int len = data.Length;
int upper = len - 1;
T temp;
int indexer2 = 0;
while (indexer < upper)
{
indexer2 = NextInt(len - indexer) + indexer;
temp = data[indexer2];
data[indexer2] = data[indexer];
data[indexer] = temp;
}
}
public static void Shuffle(List data)
{
int indexer = 0;
int len = data.Count;
int upper = len - 1;
T temp;
int indexer2 = 0;
while (indexer < upper)
{
indexer2 = NextInt(len - indexer) + indexer;
temp = data[indexer2];
data[indexer2] = data[indexer];
data[indexer] = temp;
}
}
}
}