/// <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> /// <param name="rng">Random source.</param> /// <returns>An array of indexes that are the selected items.</returns> public int[] SelectSubset(int supersetCount, IRandomSource rng) { // 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 = (int)NumericsUtils.StochasticRound(supersetCount * _selectionProportion, rng); int[] idxArr = new int[selectionCount]; DiscreteDistribution.SampleUniformWithoutReplacement(rng, supersetCount, idxArr); return(idxArr); }
public void SampleUniformWithoutReplacement_SampleAllChoices() { const int size = 5; IRandomSource rng = RandomDefaults.CreateRandomSource(); // Sample all of the elements. int[] sampleArr = new int[size]; DiscreteDistribution.SampleUniformWithoutReplacement(rng, size, sampleArr); // Sort the samples. Array.Sort(sampleArr); // Confirm that all of the choices were selected. for (int i = 0; i < size; i++) { Assert.Equal(i, sampleArr[i]); } }
private static void AssignGenomeFitnessScores( Species <double> species, int champGenomeCount, double champFitness, IRandomSource rng) { // Assign a fitness less than the champ fitness to all genomes. foreach (var genome in species.GenomeList) { double fitness = champFitness * rng.NextDouble(); genome.FitnessInfo = new FitnessInfo(fitness); } // Select a random subset to be the champ genomes, and assign them the champ fitness. int[] idxArr = DiscreteDistribution.SampleUniformWithoutReplacement(rng, species.GenomeList.Count, champGenomeCount); foreach (int idx in idxArr) { var genome = species.GenomeList[idx]; genome.FitnessInfo = new FitnessInfo(champFitness); } }
/// <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.StochasticRound(_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]; DiscreteDistribution.SampleUniformWithoutReplacement( _rng, _connectionDefArr.Length, sampleArr); // 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(_rng); } // Get create a new genome with a new ID, birth generation of zero. int id = _genomeIdSeq.Next(); return(_genomeBuilder.Create(id, 0, connGenes)); }