/// <summary> /// Sample from the provided discrete probability distribution. /// </summary> /// <param name="rng">Random source.</param> /// <param name="dist">The discrete distribution to sample from.</param> /// <returns>A sample from the discrete distribution.</returns> public static int Sample(IRandomSource rng, DiscreteDistribution dist) { float[] pArr = dist.Probabilities; // Obtain a random threshold value by sampling uniformly from interval [0,1). float thresh = rng.NextFloat(); // ENHANCEMENT: Precalc running sum over pArr, and use binary search over pArr if its length is > 10 (or thereabouts). // Loop through the discrete probabilities, accumulating as we go and stopping once // the accumulator is greater than the random sample. float acc = 0f; for (int i = 0; i < pArr.Length; i++) { acc += pArr[i]; if (acc > thresh) { return(dist.Labels[i]); } } // We might get here through floating point arithmetic rounding issues. // e.g. accumulator == throwValue. // Find a nearby non-zero probability to select. // Wrap around to start of array. for (int i = 0; i < pArr.Length; i++) { if (pArr[i] != 0.0) { return(dist.Labels[i]); } } // If we get here then we have an array of zero probabilities. throw new InvalidOperationException("Invalid operation. No non-zero probabilities to select."); }
/// <summary> /// Fill an array with samples from a distribution. /// </summary> /// <param name="buf">The array to fill with samples.</param> public void Sample(int[] buf) { DiscreteDistribution.Sample(_rng, _dist, buf); }
/// <summary> /// Take a sample from the distribution. /// </summary> public int Sample() { return(DiscreteDistribution.Sample(_rng, _dist)); }
/// <summary> /// Construct with the given distribution and a random source. /// </summary> /// <param name="dist">Discrete distribution.</param> /// <param name="rng">Random source.</param> public DiscreteDistributionSampler(DiscreteDistribution dist, IRandomSource rng) { _dist = dist; _rng = rng; }
/// <summary> /// Construct with the given distribution and a new random source. /// </summary> /// <param name="dist">Discrete distribution.</param> /// <param name="seed">Random source seed.</param> public DiscreteDistributionSampler(DiscreteDistribution dist, ulong seed) { _dist = dist; _rng = RandomDefaults.CreateRandomSource(seed); }
/// <summary> /// Fills the provided span with random samples from the distribution. /// </summary> /// <param name="span">The span to fill with samples.</param> public void Sample(Span <int> span) { DiscreteDistribution.Sample(_rng, _dist, span); }