/// <summary> /// Get the next sample point from the gaussian distribution. /// </summary> public double NextDouble() { if (null != _spareValue) { double tmp = _spareValue.Value; _spareValue = null; return(tmp); } // Generate two new gaussian values. double x, y, sqr; // We need a non-zero random point inside the unit circle. do { x = 2.0 * _rng.NextDouble() - 1.0; y = 2.0 * _rng.NextDouble() - 1.0; sqr = x * x + y * y; }while(sqr > 1.0 || sqr == 0); // Make the Box-Muller transformation. double fac = Math.Sqrt(-2.0 * Math.Log(sqr) / sqr); _spareValue = x * fac; return(y * fac); }
/// <summary> /// Performs a single throw onto a roulette wheel where the wheel's space is unevenly divided between outcomes. /// The probabilty that a segment will be selected is given by that segment's value in the 'probabilities' /// array within the specified RouletteWheelLayout. The probabilities within a RouletteWheelLayout have already /// been normalised so that their total is always equal to 1.0. /// </summary> /// <param name="layout">The roulette wheel layout.</param> /// <param name="rng">Random number generator.</param> public static int SingleThrow(RouletteWheelLayout layout, FastRandom rng) { // Throw the ball and return an integer indicating the outcome. double throwValue = layout.ProbabilitiesTotal * rng.NextDouble(); double accumulator = 0.0; for(int i=0; i<layout.Probabilities.Length; i++) { accumulator += layout.Probabilities[i]; if(throwValue < accumulator) { return layout.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<layout.Probabilities.Length; i++) { if(layout.Probabilities[i] != 0.0) { return layout.Labels[i]; } } // If we get here then we have an array of zero probabilities. throw new SharpNeatException("Invalid operation. No non-zero probabilities to select."); }
/// <summary> /// Performs a single throw onto a roulette wheel where the wheel's space is unevenly divided between outcomes. /// The probabilty that a segment will be selected is given by that segment's value in the 'probabilities' /// array within the specified RouletteWheelLayout. The probabilities within a RouletteWheelLayout have already /// been normalised so that their total is always equal to 1.0. /// </summary> /// <param name="layout">The roulette wheel layout.</param> /// <param name="rng">Random number generator.</param> public static int SingleThrow(RouletteWheelLayout layout, FastRandom rng) { // Throw the ball and return an integer indicating the outcome. double throwValue = layout.ProbabilitiesTotal * rng.NextDouble(); double accumulator = 0.0; for (int i = 0; i < layout.Probabilities.Length; i++) { accumulator += layout.Probabilities[i]; if (throwValue < accumulator) { return(layout.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 < layout.Probabilities.Length; i++) { if (layout.Probabilities[i] != 0.0) { return(layout.Labels[i]); } } // If we get here then we have an array of zero probabilities. throw new SharpNeatException("Invalid operation. No non-zero probabilities to select."); }
/// <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, FastRandom rng) { double integerPart = Math.Floor(val); double fractionalPart = val - integerPart; return(rng.NextDouble() < fractionalPart ? integerPart + 1.0 : integerPart); }
/// <summary> /// Get the next sample value from the gaussian distribution. /// </summary> public double NextSample() { for (;;) { // Select box at random. byte u = _rng.NextByte(); int i = (int)(u & 0x7F); double sign = ((u & 0x80) == 0) ? -1.0 : 1.0; // Generate uniform random value with range [0,0xffffffff]. uint u2 = _rng.NextUInt(); // Special case for the base segment. if (0 == i) { if (u2 < _xComp[0]) { // Generated x is within R0. return(u2 * __UIntToU * _A_Div_Y0 * sign); } // Generated x is in the tail of the distribution. return(SampleTail() * sign); } // All other segments. if (u2 < _xComp[i]) { // Generated x is within the rectangle. return(u2 * __UIntToU * _x[i] * sign); } // Generated x is outside of the rectangle. // Generate a random y coordinate and test if our (x,y) is within the distribution curve. // This execution path is relatively slow/expensive (makes a call to Math.Exp()) but relatively rarely executed, // although more often than the 'tail' path (above). double x = u2 * __UIntToU * _x[i]; if (_y[i - 1] + ((_y[i] - _y[i - 1]) * _rng.NextDouble()) < GaussianPdfDenorm(x)) { return(x * sign); } } }
/// <summary> /// Performs a single throw for a given number of outcomes with equal probabilities. /// </summary> /// <param name="numberOfOutcomes">The number of possible outcomes.</param> /// <param name="rng">Random number generator.</param> /// <returns>An integer between 0..numberOfOutcomes-1. In effect this routine selects one of the possible outcomes.</returns> public static int SingleThrowEven(int numberOfOutcomes, FastRandom rng) { return (int)(rng.NextDouble() * numberOfOutcomes); }
/// <summary> /// A simple single throw routine. /// </summary> /// <param name="probability">A probability between 0..1 that the throw will result in a true result.</param> /// <param name="rng">Random number generator.</param> public static bool SingleThrow(double probability, FastRandom rng) { return rng.NextDouble() < probability; }
/// <summary> /// Performs a single throw for a given number of outcomes with equal probabilities. /// </summary> /// <param name="numberOfOutcomes">The number of possible outcomes.</param> /// <param name="rng">Random number generator.</param> /// <returns>An integer between 0..numberOfOutcomes-1. In effect this /// routine selects one of the possible outcomes.</returns> public static int SingleThrowEven(int numberOfOutcomes, FastRandom rng) { return((int)(rng.NextDouble() * numberOfOutcomes)); }
/// <summary> /// A simple single throw routine. /// </summary> /// <param name="probability">A probability between 0..1 that the throw will result in a true result.</param> /// <param name="rng">Random number generator.</param> public static bool SingleThrow(double probability, FastRandom rng) { return(rng.NextDouble() < probability); }