Represents a distribution over a discrete set of possible states. Total probability over all states must add up to 1.0 This class was previously called RouletteWheelLayout.
        /// <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.");
        }
        /// <summary>
        /// Constructs an activation function library with the provided list of activation functions.
        /// </summary>
        public DefaultActivationFunctionLibrary(IList<ActivationFunctionInfo> fnList)
        {
            // Build a RouletteWheelLayout based on the selection probability on each item.
            int count = fnList.Count;
            double[] probabilities = new double[count];
            for(int i=0; i<count; i++) {
                probabilities[i] = fnList[i].SelectionProbability;
            }
            _rwl = new DiscreteDistribution(probabilities);
            _functionList = fnList;

            // Build a dictionary of functions keyed on integer ID.
            _functionDict = CreateFunctionDictionary(_functionList);
        }
 /// <summary>
 /// Copy constructor.
 /// </summary>
 public DiscreteDistribution(DiscreteDistribution copyFrom)
 {
     _probArr = (double[])copyFrom._probArr.Clone();
     _labelArr = (int[])copyFrom._labelArr.Clone();
 }
        /// <summary>
        /// Construct with default set of parameters.
        /// </summary>
        public NeatGenomeParameters()
        {
            _activationFn                               = SteepenedSigmoid.__DefaultInstance;
            _connectionWeightRange                      = DefaultConnectionWeightRange;
            _initialInterconnectionsProportion          = DefaultInitialInterconnectionsProportion;
            _disjointExcessGenesRecombineProbability    = DefaultDisjointExcessGenesRecombineProbability;
            _connectionWeightMutationProbability        = DefaultConnectionWeightMutationProbability;
            _addNodeMutationProbability                 = DefaultAddNodeMutationProbability;
            _addConnectionMutationProbability           = DefaultAddConnectionMutationProbability;
            _nodeAuxStateMutationProbability            = DefaultNodeAuxStateMutationProbability;
            _deleteConnectionMutationProbability        = DefaultDeleteConnectionMutationProbability;

            _rouletteWheelLayout = CreateRouletteWheelLayout();
            _rouletteWheelLayoutNonDestructive = CreateRouletteWheelLayout_NonDestructive();

            // Create a connection weight mutation scheme.
            _connectionMutationInfoList = CreateConnectionWeightMutationScheme_Default();

            // No fitness history.
            _fitnessHistoryLength = 0;
        }
        /// <summary>
        /// Copy constructor.
        /// </summary>
        public NeatGenomeParameters(NeatGenomeParameters copyFrom)
        {
            _feedforwardOnly                            = copyFrom._feedforwardOnly;
            _activationFn                               = copyFrom._activationFn;
            _connectionWeightRange                      = copyFrom._connectionWeightRange;
            _initialInterconnectionsProportion          = copyFrom._initialInterconnectionsProportion;
            _disjointExcessGenesRecombineProbability    = copyFrom._disjointExcessGenesRecombineProbability;
            _connectionWeightMutationProbability        = copyFrom._connectionWeightMutationProbability;
            _addNodeMutationProbability                 = copyFrom._addNodeMutationProbability;
            _addConnectionMutationProbability           = copyFrom._addConnectionMutationProbability;
            _nodeAuxStateMutationProbability            = copyFrom._nodeAuxStateMutationProbability;
            _deleteConnectionMutationProbability        = copyFrom._deleteConnectionMutationProbability;

            _rouletteWheelLayout = new DiscreteDistribution(copyFrom._rouletteWheelLayout);
            _rouletteWheelLayoutNonDestructive = new DiscreteDistribution(copyFrom._rouletteWheelLayoutNonDestructive);

            _connectionMutationInfoList = new ConnectionMutationInfoList(copyFrom._connectionMutationInfoList);
            _connectionMutationInfoList.Initialize();
            _fitnessHistoryLength = copyFrom._fitnessHistoryLength;
        }
        /// <summary>
        /// Move the prey. The prey moves by a simple set of stochastic rules that make it more likely to move away from
        /// the agent, and more so when it is close.
        /// </summary>
        public void MovePrey()
        {
            // Determine if prey will move in this timestep. (Speed is simulated stochastically)
            if(_rng.NextDouble() > _preySpeed) {
                return;
            }

            // Determine position of agent relative to prey.
            PolarPoint relPolarPos = PolarPoint.FromCartesian(_agentPos - _preyPos);

			// Calculate probabilities of moving in each of the four directions. This stochastic strategy is taken from:
            // Incremental Evolution Of Complex General Behavior, Faustino Gomez and Risto Miikkulainen (1997)
            // (http://nn.cs.utexas.edu/downloads/papers/gomez.adaptive-behavior.pdf)
            // Essentially the prey moves randomly but we bias the movements so the prey moves away from the agent, and thus 
            // generally avoids getting eaten through stupidity.
            double T = MovePrey_T(relPolarPos.Radial);
            double[] probs = new double[4];
            probs[0] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI/2.0) / Math.PI) * T * 0.33);    // North.
            probs[1] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, 0) / Math.PI) * T * 0.33);              // East.
            probs[2] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI * 1.5) / Math.PI) * T * 0.33);  // South.
            probs[3] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI) / Math.PI) * T * 0.33);        // West.
            
            DiscreteDistribution rwl = new DiscreteDistribution(probs);
            int action = DiscreteDistributionUtils.Sample(rwl, _rng);
            switch(action)
            {
                 case 0: // Move north.
                    _preyPos._y = Math.Min(_preyPos._y + 1, _gridSize - 1);
                    break;
                case 1: // Move east.
                    _preyPos._x = Math.Min(_preyPos._x + 1, _gridSize - 1);
                    break;
                case 2: // Move south.
                    _preyPos._y = Math.Max(_preyPos._y - 1, 0);
                    break;
                case 3: // Move west (is the best?)
                    _preyPos._x = Math.Max(_preyPos._x - 1, 0);
                    break;
            }
        }