/// <summary>
        /// Select a subset of items from a superset of a given size.
        /// </summary>
        /// <param name="supersetCount">The size of the superset to select from.</param>
        /// <returns>An array of indexes that are the selected items.</returns>
        public int[] SelectSubset(int supersetCount)
        {
            // Note. Ideally we'd return a sorted list of indexes to improve performance of the code that consumes them,
            // however, the sampling process inherently produces samples in randomized order, thus the decision of whether
            // to sort or not depends on the cost to the code using the samples. I.e. don't sort here!
            int selectionCount = Math.Min(_selectCount, supersetCount);

            int[] idxArr = new int[selectionCount];
            DiscreteDistributionUtils.SampleUniformWithoutReplacement(supersetCount, idxArr, _rng);
            return(idxArr);
        }
        public void SampleUniformWithoutReplacement_SampleAllChoices()
        {
            const int      size = 5;
            XorShiftRandom rng  = new XorShiftRandom();

            // Sample all of the elements.
            int[] sampleArr = new int[size];
            DiscreteDistributionUtils.SampleUniformWithoutReplacement(size, sampleArr, rng);

            // Sort the samples.
            Array.Sort(sampleArr);

            // Confirm that all of the choices were selected.
            for (int i = 0; i < size; i++)
            {
                Assert.AreEqual(i, sampleArr[i]);
            }
        }
        /// <summary>
        /// Creates a single randomly initialised genome.
        /// </summary>
        private NeatGenome <T> CreateGenome()
        {
            // Determine how many connections to create in the new genome, as a proportion of all possible connections
            // between the input and output nodes.
            int connectionCount = (int)NumericsUtils.ProbabilisticRound(_connectionDefArr.Length * _connectionsProportion, _rng);

            // Ensure there is at least one connection.
            connectionCount = Math.Max(1, connectionCount);

            // Select a random subset of all possible connections between the input and output nodes.
            int[] sampleArr = new int[connectionCount];
            DiscreteDistributionUtils.SampleUniformWithoutReplacement(
                _connectionDefArr.Length, sampleArr, _rng);

            // Sort the samples.
            // Note. This results in the neural net connections being sorted by sourceID then targetID.
            Array.Sort(sampleArr);

            // Create the connection gene arrays and populate them.
            var connGenes = new ConnectionGenes <T>(connectionCount);
            var connArr   = connGenes._connArr;
            var weightArr = connGenes._weightArr;

            for (int i = 0; i < sampleArr.Length; i++)
            {
                DirectedConnection cdef = _connectionDefArr[sampleArr[i]];

                connArr[i] = new DirectedConnection(
                    cdef.SourceId,
                    cdef.TargetId);

                weightArr[i] = _connWeightDist.Sample(_metaNeatGenome.ConnectionWeightRange, true);
            }

            // Get create a new genome with a new ID, birth generation of zero.
            int id = _genomeIdSeq.Next();

            return(_genomeBuilder.Create(id, 0, connGenes));
        }