/// <summary> /// Sample from the provided discrete probability distribution. /// </summary> /// <param name="dist">The discrete distribution to sample from.</param> /// <param name="rng">Random number generator.</param> public static int Sample(DiscreteDistribution dist, XorShiftRandom rng) { // Throw the ball and return an integer indicating the outcome. double sample = rng.NextDouble(); double acc = 0.0; for(int i=0; i<dist.Probabilities.Length; i++) { acc += dist.Probabilities[i]; if(sample < acc) { 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<dist.Probabilities.Length; i++) { if(0.0 != dist.Probabilities[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."); }
public void NextDouble() { int sampleCount = 10000000; XorShiftRandom rng = new XorShiftRandom(); double[] sampleArr = new double[sampleCount]; for(int i=0; i<sampleCount; i++){ sampleArr[i] = rng.NextDouble(); } UniformDistributionTest(sampleArr, 0.0, 1.0); }
/// <summary> /// For activation functions that accept auxiliary arguments; generates random initial values for aux arguments for newly /// added nodes (from an 'add neuron' mutation). /// </summary> public double[] GetRandomAuxArgs(XorShiftRandom rng, double connectionWeightRange) { double[] auxArgs = new double[2]; auxArgs[0] = (rng.NextDouble()-0.5) * 2.0; auxArgs[1] = rng.NextDouble(); return auxArgs; }
/// <summary> /// Sample from a set of possible outcomes with equal probability, i.e. a uniform discrete distribution. /// </summary> /// <param name="numberOfOutcomes">The number of possible outcomes.</param> /// <param name="rng">Random number generator.</param> /// <returns>An integer between 0..numberOfOutcomes-1.</returns> public static int SampleUniformDistribution(int numberOfOutcomes, XorShiftRandom rng) { return (int)(rng.NextDouble() * numberOfOutcomes); }
/// <summary> /// Sample from a binary distribution with the specified probability split between state false and true. /// </summary> /// <param name="probability">A probability between 0..1 that describes the probbaility of sampling boolean true.</param> /// <param name="rng">Random number generator.</param> public static bool SampleBinaryDistribution(double probability, XorShiftRandom rng) { return rng.NextDouble() < probability; }
/// <summary> /// Rounds up or down to a whole number by using the fractional part of the input value /// as the probability that the value will be rounded up. /// /// This is useful if we wish to round values and then sum them without generating a rounding bias. /// For monetary rounding this problem is solved with rounding to e.g. the nearest even number which /// then causes a bias towards even numbers. /// /// This solution is more appropriate for certain types of scientific values. /// </summary> public static double ProbabilisticRound(double val, XorShiftRandom rng) { double integerPart = Math.Floor(val); double fractionalPart = val - integerPart; return rng.NextDouble() < fractionalPart ? integerPart + 1.0 : integerPart; }