Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.random.ndvariable

Multidimensional Random Variables

Generator name Description
SphereVariable Uniform distribution on a unit-sphere
SimplexVariable Uniform distribution on a standard-simplex
DirichletVariable Dirichlet random variable
MultinomialVariable Multinomial random variable
MultivariateNormalVariable Multivariate_normal random variable
Authors:
Simon Bürger, Ilya Yaroshenko
template isNdRandomVariable(T)
Test if T is an n-dimensional random variable.
Examples:
static assert(isNdRandomVariable!(SphereVariable!double));
struct SphereVariable(T) if (isFloatingPoint!T);

SphereVariable!T sphereVar(T = double)()
if (isFloatingPoint!T);

alias sphereVariable = sphereVar(T = double)() if (isFloatingPoint!T);
Uniform distribution on a sphere.
Returns:
X ~ 1 with X[0]^^2 + .. + X[$-1]^^2 = 1
Examples:
Generate random points on a circle
import mir.random.engine;
import mir.math.common: fabs;

double[2] x;
sphereVar()(rne, x);
assert(fabs(x[0] * x[0] + x[1] * x[1] - 1) < 1e-10);
enum auto isNdRandomVariable;
alias Element = T;
void opCall(G)(ref scope G gen, scope T[] result)
if (isSaturatedRandomEngine!G);

void opCall(G)(scope G* gen, scope T[] result)
if (isSaturatedRandomEngine!G);
struct SimplexVariable(T) if (isFloatingPoint!T);

SimplexVariable!T simplexVar(T = double)()
if (isFloatingPoint!T);

alias simplexVariable = simplexVar(T = double)() if (isFloatingPoint!T);
Uniform distribution on a simplex.
Returns:
X ~ 1 with X[i] >= 0 and X[0] + .. + X[$-1] = 1
Examples:
// mir.ndslice package is required for 'SimplexVariable', it can be found in 'mir-algorithm'
static if (is(typeof({ import mir.ndslice.slice; })))
{
    import mir.random.engine;
    auto rv = simplexVar;
    double[3] x;
    rv(rne, x);
    assert(x[0] >= 0 && x[1] >= 0 && x[2] >= 0);
    assert(fabs(x[0] + x[1] + x[2] - 1) < 1e-10);
}
Examples:
import mir.math.common: fabs;

// mir.ndslice package is required for 'SimplexVariable', it can be found in 'mir-algorithm'
static if (is(typeof({ import mir.ndslice.slice; })))
{
    import mir.ndslice.slice;

    Random* gen = threadLocalPtr!Random;
    SimplexVariable!double rv;
    double[3] x;
    rv(gen, x);
    assert(x[0] >= 0 && x[1] >= 0 && x[2] >= 0);
    assert(fabs(x[0] + x[1] + x[2] - 1) < 1e-10);
}
enum auto isNdRandomVariable;
alias Element = T;
void opCall(G)(ref scope G gen, scope T[] result)
if (isSaturatedRandomEngine!G);

void opCall(G)(scope G* gen, scope T[] result)
if (isSaturatedRandomEngine!G);
struct DirichletVariable(T) if (isFloatingPoint!T);

DirichletVariable!T dirichletVar(T)(in T[] alpha)
if (isFloatingPoint!T);

alias dirichletVariable = dirichletVar(T)(in T[] alpha) if (isFloatingPoint!T);
Dirichlet distribution.
Examples:
import mir.random.engine;
import mir.math.common: fabs;

auto rv = dirichletVar([1.0, 5.7, 0.3]);
double[3] x;
rv(rne, x);
assert(x[0] >= 0 && x[1] >= 0 && x[2] >= 0);
assert(fabs(x[0] + x[1] + x[2] - 1) < 1e-10);
Examples:
import mir.random.engine;
import mir.math.common: fabs;

Random* gen = threadLocalPtr!Random;
auto rv = DirichletVariable!double([1.0, 5.7, 0.3]);
double[3] x;
rv(gen, x);
assert(x[0] >= 0 && x[1] >= 0 && x[2] >= 0);
assert(fabs(x[0] + x[1] + x[2] - 1) < 1e-10);
enum auto isNdRandomVariable;
alias Element = T;
const(T)[] alpha;
this()(const(T)[] alpha);
Parameters:
const(T)[] alpha concentration parameters

Constraints alpha[i] > 0

ditto

void opCall(G)(ref scope G gen, scope T[] result)
if (isSaturatedRandomEngine!G);

void opCall(G)(scope G* gen, scope T[] result)
if (isSaturatedRandomEngine!G);
struct MultinomialVariable(T) if (isFloatingPoint!T);

MultinomialVariable!T multinomialVar(T)(size_t N, return const T[] probs)
if (isFloatingPoint!T);

alias multinomialVariable = multinomialVar(T)(size_t N, return const T[] probs) if (isFloatingPoint!T);
Multinomial distribution.
Examples:
Tests if sample returned is of correct size.
import mir.random.engine;
size_t s = 10000;
double[6] p =[1/6., 1/6., 1/6., 1/6., 1/6., 1/6.]; // probs must add up to one
auto rv = multinomialVar(s, p);
uint[6] x;
rv(rne, x[]);
assert(x[0]+x[1]+x[2]+x[3]+x[4]+x[5] == s);
enum auto isNdRandomVariable;
alias Element = uint;
const(T)[] probs;
this()(size_t N, const(T)[] probs);
Parameters:
const(T)[] probs probabilities of the multinomial distribution
size_t N Number of rolls

Constraints sum(probs[i]) <= 1

void opCall(G)(ref scope G gen, scope uint[] result)
if (isSaturatedRandomEngine!G);

void opCall(G)(scope G* gen, scope uint[] result)
if (isSaturatedRandomEngine!G);
struct MultivariateNormalVariable(T) if (isFloatingPoint!T);

MultivariateNormalVariable!T multivariateNormalVar(T)(Slice!(const(T)*) mu, Slice!(T*, 2) sigma, bool chol = false);

MultivariateNormalVariable!T multivariateNormalVar(T)(Slice!(T*, 2) sigma, bool chol = false);

alias multivariateNormalVariable = multivariateNormalVar(T)(Slice!(const(T)*) mu, Slice!(T*, 2) sigma, bool chol = false);
Multivariate normal distribution. Beta version (has not properly tested).
Examples:
// mir.ndslice package is required for 'multivariateNormalVar', it can be found in 'mir-algorithm'
static if (is(typeof({ import mir.ndslice.slice; })))
{
    import mir.random.engine;
    import mir.ndslice.slice: sliced;
    auto mu = [10.0, 0.0].sliced;
    auto sigma = [2.0, -1.5, -1.5, 2.0].sliced(2,2);
    auto rv = multivariateNormalVar(mu, sigma);
    double[2] x;
    rv(rne, x[]);
}
Examples:
// mir.ndslice package is required for 'multivariateNormalVar', it can be found in 'mir-algorithm'
static if (is(typeof({ import mir.ndslice.slice; })))
{
    import mir.ndslice.slice: sliced;
    import mir.random.engine;

    Random* gen = threadLocalPtr!Random;
    auto mu = [10.0, 0.0].sliced;
    auto sigma = [2.0, -1.5, -1.5, 2.0].sliced(2,2);
    auto rv = multivariateNormalVar(mu, sigma);
    double[2] x;
    rv(gen, x[]);
}
bool cholesky()(Slice!(T*, 2) m);
Compute Cholesky decomposition in place. Only accesses lower/left half of the matrix. Returns false if the matrix is not positive definite.
enum auto isNdRandomVariable;
alias Element = T;
this()(Slice!(const(T)*) mu, Slice!(T*, 2) sigma, bool chol = false);

this()(Slice!(T*, 2) sigma, bool chol = false);
Constructor computes the Cholesky decomposition of sigma in place without memory allocation. Furthermore it is assumed to be a symmetric matrix, but only the lower/left half is actually accessed.
Parameters:
Slice!(const(T)*) mu mean vector (assumed zero if not supplied)
Slice!(T*, 2) sigma covariance matrix
bool chol optional flag indicating that sigma is already Cholesky decomposed

Constraints sigma has to be positive-definite

void opCall(G)(ref scope G gen, scope T[] result)
if (isSaturatedRandomEngine!G);

void opCall(G)(scope G* gen, scope T[] result)
if (isSaturatedRandomEngine!G);