Make It Random User's Manual

Distribution Sampling |

Distribution sampling allows you to specify a potentially uneven probability distribution of values and select random samples from the available range of values according to the indicated probability of each value occurring. Make It Random provides a number of continuous probability distributions, offering your choice of the float or double numeric types.

Important |
---|

Most distributions need to pre-compute some data before the first sample can be generated; for some distributions, this pre-computation step can be substantial, relative to the actual sampling process itself. It is advisable to create and use a generator which can pre-compute and save this data, if you are selecting multiple samples from a single distribution. |

This topic contains the following sections:

Basic Distributions

A uniform distribution is specified simply by a range with a lower and an upper boundary. All values within this range will have an equal chance of being generated.

Sampling a uniform distribution.

// Take a sample uniformly chosen from within the range [3, 7]. float sample = random.UniformSample(3f, 7f); // Or create a uniform distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeUniformSampleGenerator(3f, 7f); // Get the first sample from the generator. sample = sampler.Next();

A triangular distribution is specified by a lower and an upper bound, plus a mode within that range which is the value that will be sampled more often than any other. The probability of values decreases linearly as they diverge from the mode and approach the lower or upper bound, reaching zero probability at the bounds themselves.

Sampling a triangular distribution.

// Take a sample chosen from within the range [3, 7], // in which 4 is the most probable number to be chosen, // with probability dropping off to zero as numbers // approach 3 and 7. float sample = random.TriangularSample(3f, 4f, 7f); // Or create a triangular distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeTriangularSampleGenerator(3f, 4f, 7f); // Get the first sample from the generator. sample = sampler.Next();

A trapezoidal distribution is specified by a lower and an upper bound, plus a mode range within that outer range. The values within the mode range all have an equal probability of being sampled, and this probability is the highest of any values in the distribution. The probability of values decreases linearly as they diverge from the lower or upper bound of this inner mode range and approach the lower or upper bound of the whole distribution, reaching zero probability at the outer bounds themselves.

Sampling a trapezoidal distribution.

// Take a sample chosen from within the range [3, 7], // in which values in the range [3.5, 4.25] are the most // probable numbers to be chosen, with probability dropping // off to zero as numbers approach 3 and 7. float sample = random.TrapezoidalSample(3f, 3.5f, 4.25f, 7f); // Or create a triangular distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeTrapezoidalSampleGenerator(3f, 3.5f, 4.25f, 7f); // Get the first sample from the generator. sample = sampler.Next();

A linear distribution is specified by a lower and an upper bound, plus the weight or relative probability of each bound. The probabilities of the rest of the values within the range are then determined by a linear interpolation of the lower and upper weights.

Sampling a linear distribution.

// Take a sample chosen from within the range [3, 7], // with 3 having a low probability, 7 having a high // probability which is four times as great as the // lower bound's probability, and values between // them having intermediate probabilities. float sample = random.LinearSample(3f, 1f, 7f, 4f); // Or create a linear distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeLinearSampleGenerator(3f, 1f, 7f, 4f); // Get the first sample from the generator. sample = sampler.Next();

A Hermite spline distribution is specified by a lower and an upper bound, plus the weight or relative probability and slope of each bound. The probabilities of the rest of the values within the range are then determined by the value of the Hermite spline produced by these two end points and the initial and final slopes of the spline.

Note |
---|

This spline type is exactly the same as that used by individual segments within an instance of UnityEngineAnimationCurve. |

Caution |
---|

Care should be taken to ensure that the value of the does not ever drop below zero. Otherwise, the results of sampling the distribution will be undefined. |

Sampling a Hermite spline distribution.

// Take a sample chosen from within the range [3, 7], // with 3 having a low probability, 7 having a high // probability which is four times as great as the // lower bound's probability. A peak of local higher // probability will occur around 3.7 and a trough of // lowest probability will occur around 5.4. float sample = random.HermiteSplineSample(3f, 1f, 0.5f, 7f, 4f, 1.5f); // Or create a Hermite spline distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeHermiteSplineSampleGenerator(3f, 1f, 0.5f, 7f, 4f, 1.5f); // Get the first sample from the generator. sample = sampler.Next();

A normal distribution is specified by a mean or average value, plus a standard deviation, producing a classic bell curve shaped distribution. The mean will be the most probably value at the center of the distribution, and the standard deviation will determine how quickly the probability of values drop off as they diverge from the mean.

Although limited to some extent by the numerical precision of float and double numeric types, a normal distribution is capable of generating incredibly huge numbers (positive or negative), albeit with incrediblely low probability. You can optionally specify lower and upper bounds to avoid excessively large values in cases where they would not be appropriate. Note though that this will bias the effect standard deviation to be slightly lower than you specified.

Sampling a normal distribution.

// Take a sample chosen from a bell curve shaped // distribution with a mean of 5 and a standard // deviation of 2. Reject any values below -1 or // above 9. float sample = random.NormalSample(5f, 2f, -1f, 9f); // Or create a normal distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeNormalSampleGenerator(5f, 2f, -1f, 9f); // Get the first sample from the generator. sample = sampler.Next();

An exponential distribution is specified simply by an event rate, and will produce samples from zero to positive infinitiy, with zero being the most probable, and probability asymptotically approaching zero for numbers that approach positive infinity.

Given an event rate, sampling the exponential distribution will give you a value that indicates the duration between one event occurrence and the next. Generating multiple events over time using these durations, the average rate of occurrence should then match the specified event rate.

Although limited to some extent by the numerical precision of float and double numeric types, an exponential distribution is capable of generating incredibly huge numbers (positive only), albeit with incrediblely low probability. You can optionally specify an upper bound to avoid excessively large values in cases where they would not be appropriate. Note though that this will bias the effective event rate to be slightly higher than you specified.

Sampling an exponential distribution.

// Take a sample chosen from a distribution representing // an event rate of 0.25 events per second. Reject any // sampled durations above 10 seconds. float sample = random.ExponentialSample(0.25f, 10f); // Or create an exponential distribution sample generator which can // be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakeExponentialSampleGenerator(0.25f, 10f); // Get the first sample from the generator. sample = sampler.Next();

Piecewise Distributions

A piecewise uniform distribution is specified as a sequence of adjacent simple uniform distributions, each with their own weight or relative probability.

Sampling a piecewise uniform distribution.

// Take a sample chosen from the range [3, 7], // with strongest weighting within [3, 3.5], second // strongest within [5.5, 7], third strongest within // [3.5, 4.5], and weakest within [4.5, 5.5]. float sample = random.PiecewiseUniformSample( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 4f, 2f, 1f, 3f }); // Or create an piecewise uniform distribution sample generator which // can be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakePiecewiseUniformSampleGenerator( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 4f, 2f, 1f, 3f }); // Get the first sample from the generator. sample = sampler.Next();

A piecewise linear distribution is specified as a sequence of adjacent simple linear distributions. Each individual distribution shares its end point weights with the two distributions before and after it.

Sampling a piecewise linear distribution.

// Take a sample chosen from the range [3, 7], // with strongest weighting at 4.5, second strongest // within [5.5, 7], third strongest at 3, and a // zero probability at 3.5. float sample = random.PiecewiseLinearSample( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 1f, 0f, 4f, 2f, 2f }); // Or create an piecewise uniform distribution sample generator which // can be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakePiecewiseLinearSampleGenerator( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 1f, 0f, 4f, 2f, 2f }); // Get the first sample from the generator. sample = sampler.Next();

A piecewise Hermite spline distribution is specified as a sequence of adjacent simple linear distributions. Each individual distribution shares its end point weights with the two distributions before and after it. The slopes are not shared.

This distribution exactly mimics the splines used by UnityEngineAnimationCurve, and therefore can be initialized with a reference to an animation curve. This makes it easy to design the probability distribution within the Unity editor using the standard animation curve editor, and then in code use that curve to initialize a distribution sample generator.

Sampling a piecewise Hermite spline distribution.

// Take a sample chosen from the range [3, 7], with // spline positions at (3, 1), (3.5, 0), (4.5, 4), // (5.5, 2), and (7, 2). Slope at 3 is 1, slopes // at 3.5 are -0.5 and 2, at 4.5 are 2 and 0, at // 5.5 are 0 and -1.5, and slope at 7 is 1. float sample = random.PiecewiseHermiteSplineSample( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 1f, 0f, 4f, 2f, 2f }, new float[] { 1f, -0.5f, 2f, 2f, 0f, 0f, -1.5f, 1f }); // Or create an piecewise Hermite spline distribution sample generator // which can be used to efficiently take multiple samples from that range. ISampleGenerator<float> sampler = random.MakePiecewiseHermiteSplineSampleGenerator( new float[] { 3f, 3.5f, 4.5f, 5.5f, 7f }, new float[] { 1f, 0f, 4f, 2f, 2f }, new float[] { 1f, -0.5f, 2f, 2f, 0f, 0f, -1.5f, 1f }); // Get the first sample from the generator. sample = sampler.Next();

See Also