/// <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> public static int Sample(IRandomSource rng, DiscreteDistribution dist) { double[] pArr = dist.Probabilities; // Obtain a random threshold value by sampling uniformly from interval [0,1). double thresh = rng.NextDouble(); // Loop through the discrete probabilities, accumulating as we go and stopping once // the accumulator is greater than the random sample. double acc = 0.0; 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 (0.0 != pArr[i]) { 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> /// 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> /// Take a sample from the distribution. /// </summary> public int Sample() { return(DiscreteDistribution.Sample(_rng, _dist)); }
/// <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); }