コード例 #1
0
 private void RecalcCentroids_GenomeById(Species <T>[] speciesArr, bool[] updateBits)
 {
     Parallel.ForEach(Enumerable.Range(0, speciesArr.Length).Where(i => updateBits[i]), _parallelOptions, (i) =>
     {
         var species      = speciesArr[i];
         species.Centroid = _distanceMetric.CalculateCentroid(species.GenomeById.Values.Select(x => x.ConnectionGenes));
     });
 }
コード例 #2
0
 private void RecalcCentroids_GenomeById(Species <T>[] speciesArr, bool[] updateBits)
 {
     for (int i = 0; i < speciesArr.Length; i++)
     {
         if (updateBits[i])
         {
             var species = speciesArr[i];
             species.Centroid = _distanceMetric.CalculateCentroid(species.GenomeById.Values.Select(x => x.ConnectionGenes));
         }
     }
 }
コード例 #3
0
 private void RecalcCentroids_GenomeById(Species <T>[] speciesArr, bool[] updateBits)
 {
     Parallel.ForEach(
         Enumerable.Range(0, speciesArr.Length).Where(i => updateBits[i]),
         _parallelOptions,
         () => new List <ConnectionGenes <T> >(),
         (speciesIdx, loopState, connGenesList) =>
     {
         var species = speciesArr[speciesIdx];
         SpeciationUtils.ExtractConnectionGenes(connGenesList, species.GenomeById);
         species.Centroid = _distanceMetric.CalculateCentroid(connGenesList);
         return(connGenesList);
     },
         (connGenesList) => connGenesList.Clear());
 }
コード例 #4
0
        public Species <T>[] InitialiseSpecies(
            IList <NeatGenome <T> > genomeList,
            int speciesCount,
            IRandomSource rng)
        {
            // Create an array of seed genomes, i.e. each of these genomes will become the initial
            // seed/centroid of one species.
            var seedGenomeList = new List <NeatGenome <T> >(speciesCount);

            // Create a list of genomes to select and remove seed genomes from.
            var remainingGenomes = new List <NeatGenome <T> >(genomeList);

            // Select first genome at random.
            seedGenomeList.Add(GetAndRemove(remainingGenomes, rng.Next(remainingGenomes.Count)));

            // Select all other seed genomes using k-means++ method.
            for (int i = 1; i < speciesCount; i++)
            {
                var seedGenome = GetSeedGenome(seedGenomeList, remainingGenomes, rng);
                seedGenomeList.Add(seedGenome);
            }

            // Create an array of species initialised with the chosen seed genomes.

            // Each species is created with an initial capacity that will reduce the need for memory
            // reallocation but that isn't too wasteful of memory.
            int initialCapacity = (genomeList.Count * 2) / speciesCount;

            var speciesArr = new Species <T> [speciesCount];

            for (int i = 0; i < speciesCount; i++)
            {
                var seedGenome = seedGenomeList[i];
                speciesArr[i] = new Species <T>(i, seedGenome.ConnectionGenes, initialCapacity);
                speciesArr[i].GenomeList.Add(seedGenome);
            }

            // Allocate all other genomes to the species centroid they are nearest too.
            Parallel.ForEach(remainingGenomes, _parallelOptions, genome =>
            {
                var nearestSpeciesIdx = GetNearestSpecies(_distanceMetric, genome, speciesArr);
                var nearestSpecies    = speciesArr[nearestSpeciesIdx];

                lock (nearestSpecies.GenomeList) {
                    nearestSpecies.GenomeList.Add(genome);
                }
            });

            // Recalc species centroids.
            Parallel.ForEach(speciesArr, _parallelOptions, species => {
                species.Centroid = _distanceMetric.CalculateCentroid(species.GenomeList.Select(genome => genome.ConnectionGenes));
            });

            return(speciesArr);
        }
    private void RecalcCentroids_GenomeById(
        Species <T>[] speciesArr,
        bool[] updateBits)
    {
        // Create a temporary, reusable, working list.
        var tmpConnGenes = new List <ConnectionGenes <T> >();

        for (int i = 0; i < speciesArr.Length; i++)
        {
            if (updateBits[i])
            {
                var species = speciesArr[i];

                // Extract the ConnectionGenes<T> object from each genome in the GenomeById dictionary.
                SpeciationUtils.ExtractConnectionGenes(tmpConnGenes, species.GenomeById);

                // Calculate the centroid for the extracted connection genes.
                species.Centroid = _distanceMetric.CalculateCentroid(tmpConnGenes);
            }
        }

        tmpConnGenes.Clear();
    }
コード例 #6
0
        private static NeatGenome <T> GetGenomeForEmptySpecies <T>(
            IDistanceMetric <T> distanceMetric,
            Species <T>[] speciesArr)
            where T : struct
        {
            // Get the species with the highest number of genomes.
            Species <T> species = speciesArr.Aggregate((x, y) => x.GenomeById.Count > y.GenomeById.Count ?  x : y);

            // Get the genome furthest from the species centroid.
            var genome = species.GenomeById.Values.Aggregate((x, y) => distanceMetric.CalcDistance(species.Centroid, x.ConnectionGenes) > distanceMetric.CalcDistance(species.Centroid, y.ConnectionGenes) ? x : y);

            // Remove the genome from its current species.
            species.GenomeById.Remove(genome.Id);

            // Update the species centroid.
            species.Centroid = distanceMetric.CalculateCentroid(species.GenomeById.Values.Select(x => x.ConnectionGenes));

            // Return the selected genome.
            return(genome);
        }
コード例 #7
0
        /// <summary>
        /// Recalculate the specie centroid based on the genomes currently in the specie.
        /// </summary>
        private CoordinateVector CalculateSpecieCentroid(Specie <TGenome> specie)
        {
            // Special case - 1 genome in specie (its position *is* the specie centroid).
            if (1 == specie.GenomeList.Count)
            {
                return(new CoordinateVector(specie.GenomeList[0].Position.CoordArray));
            }

            // Create a temp list containing all of the genome positions.
            List <TGenome>          genomeList = specie.GenomeList;
            int                     count      = genomeList.Count;
            List <CoordinateVector> coordList  = new List <CoordinateVector>(count);

            for (int i = 0; i < count; i++)
            {
                coordList.Add(genomeList[i].Position);
            }

            // The centroid calculation is a function of the distance metric.
            return(_distanceMetric.CalculateCentroid(coordList));
        }
コード例 #8
0
        public static void ValidationTests(
            Species <double>[] speciesArr,
            IDistanceMetric <double> distanceMetric,
            int speciesCountExpected,
            List <NeatGenome <double> > fullGenomeList,
            bool validateNearestSpecies)
        {
            // Confirm correct number of species.
            Assert.Equal(speciesCountExpected, speciesArr.Length);

            // Confirm no empty species.
            int minSpeciesSize = speciesArr.Select(x => x.GenomeList.Count).Min();

            Assert.True(minSpeciesSize > 0);

            // Get IDs of all genomes in species.
            var idSet = GetAllGenomeIds(speciesArr);

            // Confirm number of IDs equals number of genomes in main population list.
            Assert.Equal(fullGenomeList.Count, idSet.Count);

            // Confirm the genome list IDs match up with the genomes in the species.
            fullGenomeList.ForEach(x => Assert.Contains(x.Id, idSet));

            // Confirm all species centroids are correct.
            Array.ForEach(
                speciesArr,
                x => Assert.Equal(
                    0.0,
                    distanceMetric.CalcDistance(x.Centroid, distanceMetric.CalculateCentroid(x.GenomeList.Select(y => y.ConnectionGenes).ToList()))));

            if (validateNearestSpecies)
            {
                // Confirm all genomes are in the species with the nearest centroid.
                // Note. If there are two or more species that are equally near then we test that a genome is in one of those.
                Array.ForEach(speciesArr, species => species.GenomeList.ForEach(genome => Assert.Contains(species, GetNearestSpeciesList(genome, speciesArr, distanceMetric))));
            }
        }
コード例 #9
0
    private static NeatGenome <T> GetGenomeForEmptySpecies <T>(
        IDistanceMetric <T> distanceMetric,
        Species <T>[] speciesArr,
        List <ConnectionGenes <T> > tmpPointList)
        where T : struct
    {
        // TODO: Select donor species stochastically from a pool of the largest species.

        // Get the species with the highest number of genomes.
        Species <T> species = speciesArr.Aggregate((x, y) => x.GenomeById.Count > y.GenomeById.Count ? x : y);

        // Get the genome furthest from the species centroid.
        double         maxDistance  = -1.0;
        NeatGenome <T>?chosenGenome = null;

        foreach (var genome in species.GenomeById.Values)
        {
            double distance = distanceMetric.CalcDistance(species.Centroid, genome.ConnectionGenes);
            if (distance > maxDistance)
            {
                maxDistance  = distance;
                chosenGenome = genome;
            }
        }

        // Remove the genome from its current species.
        species.GenomeById.Remove(chosenGenome !.Id);

        // Extract the ConnectionGenes<T> object from each genome in the species' genome list.
        ExtractConnectionGenes(tmpPointList, species.GenomeById);

        // Calc and update species centroid.
        species.Centroid = distanceMetric.CalculateCentroid(tmpPointList);

        // Return the selected genome.
        return(chosenGenome);
    }
コード例 #10
0
    /// <summary>
    /// Group the provided genomes into new species.
    /// </summary>
    /// <param name="genomeList">The genomes to partition into groups/species.</param>
    /// <param name="speciesCount">The required number of species.</param>
    /// <param name="rng">Random source.</param>
    /// <returns>A new array of <see cref="Species{T}"/>, with each species containing a subset of the genomes from <paramref name="genomeList"/>.</returns>
    public Species <T>[] InitialiseSpecies(
        IList <NeatGenome <T> > genomeList,
        int speciesCount,
        IRandomSource rng)
    {
        // Create an array of seed genomes, i.e. each of these genomes will become the initial
        // seed/centroid of one species.
        var seedGenomeList = new List <NeatGenome <T> >(speciesCount);

        // Create a list of genomes to select and remove seed genomes from.
        var remainingGenomes = new List <NeatGenome <T> >(genomeList);

        // Select first genome at random.
        seedGenomeList.Add(GetAndRemove(remainingGenomes, rng.Next(remainingGenomes.Count)));

        // Select all other seed genomes using k-means++ method.
        for (int i = 1; i < speciesCount; i++)
        {
            var seedGenome = GetSeedGenome(seedGenomeList, remainingGenomes, rng);
            seedGenomeList.Add(seedGenome);
        }

        // Create an array of species initialised with the chosen seed genomes.

        // Each species is created with an initial capacity that will reduce the need for memory
        // reallocation but that isn't too wasteful of memory.
        int initialCapacity = (genomeList.Count * 2) / speciesCount;

        var speciesArr = new Species <T> [speciesCount];

        for (int i = 0; i < speciesCount; i++)
        {
            var seedGenome = seedGenomeList[i];
            speciesArr[i] = new Species <T>(i, seedGenome.ConnectionGenes, initialCapacity);
            speciesArr[i].GenomeList.Add(seedGenome);
        }

        // Allocate all other genomes to the species centroid they are nearest too.
        foreach (var genome in remainingGenomes)
        {
            var nearestSpeciesIdx = GetNearestSpecies(_distanceMetric, genome, speciesArr);
            speciesArr[nearestSpeciesIdx].GenomeList.Add(genome);
        }

        // Recalc species centroids.
        // Create a temporary, reusable, working list.
        var tmpConnGenes = new List <ConnectionGenes <T> >();

        foreach (var species in speciesArr)
        {
            // Extract the ConnectionGenes<T> object from each genome in the species' genome list.
            ExtractConnectionGenes(tmpConnGenes, species.GenomeList);

            // Calculate the centroid for the extracted connection genes.
            species.Centroid = _distanceMetric.CalculateCentroid(tmpConnGenes);
        }

        tmpConnGenes.Clear();

        return(speciesArr);
    }