9.2 Vectorized Random Number Generators (.NET, C#, CSharp, VB, Visual Basic, F#)
Unlike scalar-type generators, whose output is a successive random number (Section 9.1), vectorized generators produce a vector of n successive random numbers from a given distribution. Vectorized generators typically outperform scalar generators because the overhead expense of a function call is comparable to the total time required for computation.
NMath provides vectorized distribution classes for many continuous (Table 8) and discrete (Table 9) distributions.
Class |
Description |
Beta distribution. |
|
Cauchy distribution. |
|
Exponential distribution |
|
Gamma distribution. |
|
Gaussian distribution. |
|
Gumbel distribution. |
|
Laplace distribution. |
|
Log-normal distribution. |
|
Rayleigh distribution. |
|
Uniform distribution. |
|
Weibull distribution. |
Class |
Description |
Bernoulli distribution. |
|
Binomial distribution. |
|
Geometric Distribution |
|
Hypergeometric distribution. |
|
Negative Binomial distribution. |
|
Poisson distribution. |
|
Possion distribution with varying mean. |
|
Uniform distribution. |
|
Integer values with uniform bit distribution. |
Distribution objects are constructed from the relevant distribution parameters. For example:
Code Example – C# random number generators
double mean = 1.0;
double sigma = 1.0;
DoubleRandomGaussianDistribution dist =
new DoubleRandomGaussianDistribution(mean, sigma);
Code Example – VB random number generators
Dim Mean = 1.0
Dim Sigma = 1.0
Dim Dist As New DoubleRandomGaussianDistribution(Mean, Sigma)
Class RandomNumberStream encapsulates a vectorized random number generator which yields a stream of random numbers.
A stream is constructed from an optional seed, and an optional enumerated value specifying which algorithm to use for generating random numbers uniformly distributed in the interval [0, 1].
Code Example – C# random number generators
int seed = 0x345;
var stream = new RandomNumberStream(seed,
RandomNumberStream.BasicRandGenType.MersenneTwister);
Code Example – VB random number generators
Dim Seed As Integer = &H345
Dim Stream As New RandomNumberStream(Seed,
RandomNumberStream.BasicRandGenType.MersenneTwister
You can use a stream and distribution to fill an array:
Code Example – C# random number generators
int n = 100;
int start = 0;
var a = new double[n];
dist.Fill(stream, a, start, n);
Code Example – VB random number generators
Dim N As Integer = 100
Dim Start As Integer = 0
Dim A(N) As Double
Dist.Fill(Stream, A, Start, N)
Or to fill a new vector or matrix:
Code Example – C# random number generators
var v = new DoubleVector(n, stream, dist);
Code Example – VB random number generators
Dim V As New DoubleVector(N, Stream, Dist)
If you want the performance of a vectorized random number generator, but still need to access the random deviates sequentially, NMath provides class RandomNumbers, which uses a stream to buffer the random numbers internally.
For instance:
Code Example – C# random number generators
int bufferSize = 100;
RandomNumbers<double, DoubleRandomGaussianDistribution> rnd =
new RandomNumbers<double, DoubleRandomGaussianDistribution>(seed,
dist, bufferSize);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Next() = {0}", rnd.Next());
}
Code Example – VB random number generators
Dim BufferSize As Integer = 100
Dim RND As New RandomNumbers(Of Double,
DoubleRandomGaussianDistribution)(Seed, Dist, BufferSize)
For I As Integer = 0 To 9
Console.WriteLine("Next() = {0}", RND.Next())
Next
NMath provides classes for generating several independent streams of random numbers using two methods:
● In the leapfrog method, the independent sequences are created by splitting the original sequence into k disjoint subsets, where k is the number of independent streams, is such a way that the first stream generates the random numbers x1, xk+1, x2k+1, x3k+1,..., the second stream generates the numbers x2, xk+2, x2k+2, x3k+2,..., and, finally, the kth stream would generate xk, x2k, x3k... Class LeapfrogRandomStreams uses the leapfrog method.
● In the skip-ahead, or block-splitting, method, the independent sequences are created by splitting the original sequence into k non-overlapping blocks, where k is the number of independent streams. Each stream generates numbers only from its corresponding block. Class SkipAheadRandomStreams uses the skip-ahead method.
For example, this code creates 10 streams of length 100 using the skip-ahead method:
Code Example – C# random number generators
int seed = 0x124;
RandomNumberStream.BasicRandGenType genType =
RandomNumberStream.BasicRandGenType.MultiplicativeCongruent31;
int nstreams = 10;
int streamLen = 100;
SkipAheadRandomStreams gen =
new SkipAheadRandomStreams(seed, genType, nstreams, streamLen);
Code Example – VB random number generators
Dim Seed = &H124
Dim GenType =
RandomNumberStream.BasicRandGenType.MultiplicativeCongruent31
Dim NStreams = 10
Dim StreamLen = 100
Dim Gen As New SkipAheadRandomStreams(Seed, GenType, NStreams,
StreamLen)
You can use a single distribution to fill an array or matrix:
Code Example – C# random number generators
var dist = new DoubleRandomUniformDistribution();
var A = new DoubleMatrix(streamLen, nstreams);
gen.Fill(dist, A);
Code Example – VB random number generators
Dim Dist As New DoubleRandomUniformDistribution()
Dim A As New DoubleMatrix(StreamLen, NStreams)
Gen.Fill(Dist, A)
Or to create a new matrix:
Code Example – C# random number generators
var dist = new DoubleRandomLogNormalDistribution();
DoubleMatrix B = gen.Next(dist);
Code Example – VB random number generators
Dim Dist As New DoubleRandomLogNormalDistribution()
Dim B As DoubleMatrix = Gen.Next(Dist)
You can also use an array of distributions, one per stream:
Code Example – C# random number generators
nstreams = 3;
var intDists = new IRandomNumberDistribution<double>[nstreams];
intDists[0] = new DoubleRandomUniformDistribution();
intDists[1] = new DoubleRandomBetaDistribution();
intDists[2] = new DoubleRandomCauchyDistribution();
var gen = new SkipAheadRandomStreams(seed, genType, nstreams,
streamLen);
DoubleMatrix C = gen.Next(intDists);
Code Example – VB random number generators
nstreams = 3
Dim IntDists(NStreams) As IRandomNumberDistribution(Of Double)
IntDists(0) = New DoubleRandomUniformDistribution()
IntDists(1) = New DoubleRandomBetaDistribution()
IntDists(2) = New DoubleRandomCauchyDistribution()
Dim Gen = New SkipAheadRandomStreams(Seed, GenType, NStreams,
StreamLen)
Dim C As DoubleMatrix = Gen.Next(IntDists)
NMath provides classes for generating sequences of quasirandom points. A quasirandom sequence is a sequence of n-tuples that fills n-space more uniformly than uncorrelated random points. NiederreiterQuasiRandomGenerator generates quasirandom numbers using the Niederreiter method; SobolQuasiRandomGenerator uses the Sobol method.
For example:
Code Example – C# quasirandom numbers
int dim = 3;
var nqrg = new NiederreiterQuasiRandomGenerator(dim);
Code Example – VB quasirandom numbers
Dim Dimensions As Integer = 3
Dim NQRG As New NiederreiterQuasiRandomGenerator(Dimensions)
You can fill an existing matrix or array. (The points are the columns of the matrix, so the number of rows in the given matrix must be equal to the Dimension of the quasirandom number generator.)
Code Example – C# quasirandom numbers
int numPts = 5000;
var A = new DoubleMatrix(nqrg.Dimension, numPts);
nqrg.Fill(A);
Code Example – VB quasirandom numbers
Dim NumPts As Integer = 5000
Dim A As New DoubleMatrix(NQRG.Dimension, NumPts)
NQRG.Fill(A)
Or create a new matrix:
Code Example – C# quasirandom numbers
DoubleMatrix B = nqrg.Next(
new DoubleRandomUniformDistribution(), numPts);
Code Example – VB quasirandom numbers
Dim B As DoubleMatrix = NQRG.Next(
New DoubleRandomUniformDistribution(), NumPts)
The quasirandom numbers will follow the given distribution.