/// <summary> /// Gets the species with a centroid closest to the given genome. /// If multiple species are equally close then we return all of the those species. /// </summary> public static List <Species <T> > GetNearestSpeciesList <T>( NeatGenome <T> genome, Species <T>[] speciesArr, IDistanceMetric <T> distanceMetric) where T : struct { var nearestSpeciesList = new List <Species <T> >(4); nearestSpeciesList.Add(speciesArr[0]); double nearestDistance = distanceMetric.GetDistance(genome.ConnectionGenes, speciesArr[0].Centroid); for (int i = 1; i < speciesArr.Length; i++) { double distance = distanceMetric.GetDistance(genome.ConnectionGenes, speciesArr[i].Centroid); if (distance < nearestDistance) { nearestSpeciesList.Clear(); nearestSpeciesList.Add(speciesArr[i]); nearestDistance = distance; } else if (distance == nearestDistance) { nearestSpeciesList.Add(speciesArr[i]); } } return(nearestSpeciesList); }
// ENHANCEMENT: Optimization candidate. /// <summary> /// Gets an array of all genomes ordered by their distance from their current specie. /// </summary> private TGenome[] GetGenomesByDistanceFromSpecie(IList <TGenome> genomeList, IList <Specie <TGenome> > specieList) { // Build a list of all genomes paired with their distance from their centroid. int genomeCount = genomeList.Count; GenomeDistancePair <TGenome>[] genomeDistanceArr = new GenomeDistancePair <TGenome> [genomeCount]; for (int i = 0; i < genomeCount; i++) { TGenome genome = genomeList[i]; double distance = _distanceMetric.GetDistance(genome.Position, specieList[genome.SpecieIdx].Centroid); genomeDistanceArr[i] = new GenomeDistancePair <TGenome>(distance, genome); } // Sort list. Longest distance first. Array.Sort(genomeDistanceArr); // Put the sorted genomes in an array and return it. TGenome[] genomeArr = new TGenome[genomeCount]; for (int i = 0; i < genomeCount; i++) { genomeArr[i] = genomeDistanceArr[i]._genome; } return(genomeArr); }
// ENHANCEMENT: Optimization candidate. /// <summary> /// Gets an array of all genomes ordered by their distance from their current specie. /// </summary> private TGenome[] GetGenomesByDistanceFromSpecie(IList <TGenome> genomeList, IList <Specie <TGenome> > specieList) { // Build an array of all genomes paired with their distance from their centroid. int genomeCount = genomeList.Count; GenomeDistancePair <TGenome>[] genomeDistanceArr = new GenomeDistancePair <TGenome> [genomeCount]; Parallel.For(0, genomeCount, _parallelOptions, delegate(int i) { TGenome genome = genomeList[i]; double distance = _distanceMetric.GetDistance(genome.Position, specieList[genome.SpecieIdx].Centroid); genomeDistanceArr[i] = new GenomeDistancePair <TGenome>(distance, genome); }); // Sort list. Longest distance first. // TODO: Pass in parallel options. ParallelSort.QuicksortParallel(genomeDistanceArr); // Put the sorted genomes in an array and return it. TGenome[] genomeArr = new TGenome[genomeCount]; for (int i = 0; i < genomeCount; i++) { genomeArr[i] = genomeDistanceArr[i]._genome; } return(genomeArr); }
private double GetDistanceFromNearestSeed(List <NeatGenome <T> > seedGenomeList, NeatGenome <T> genome) { double minDistance = _distanceMetric.GetDistance(seedGenomeList[0].ConnectionGenes, genome.ConnectionGenes); for (int i = 1; i < seedGenomeList.Count; i++) { double distance = _distanceMetric.GetDistance(seedGenomeList[i].ConnectionGenes, genome.ConnectionGenes); distance = Math.Min(minDistance, distance); } return(minDistance); }
/// <summary> /// Gets an adjusted distance between the given genome and a species centroid. /// The adjustment introduces a regularization term. /// </summary> private double GetAdjustedDistance( NeatGenome <T> genome, Species <T> species, double populationCount, double maxIntraSpeciesDistance) { double distance = _distanceMetric.GetDistance(genome.ConnectionGenes, species.Centroid); // Calc regularization term. double clusterCount = species.GenomeById.Count; double r = (clusterCount / populationCount) * maxIntraSpeciesDistance * _regularizationConstant; // Return the distance plus the regularization term. return(distance + r); }
public static void ValidationTests( Species <double>[] speciesArr, IDistanceMetric <double> distanceMetric, int speciesCountExpected, List <NeatGenome <double> > fullGenomeList, bool validateNearestSpecies) { // Confirm correct number of species. Assert.AreEqual(speciesCountExpected, speciesArr.Length); // Confirm no empty species. int minSpeciesSize = speciesArr.Select(x => x.GenomeList.Count).Min(); Assert.IsTrue(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.AreEqual(fullGenomeList.Count, idSet.Count); // Confirm the genome list IDs match up with the genomes in the species. fullGenomeList.ForEach(x => Assert.IsTrue(idSet.Contains(x.Id))); // Confirm all species centroids are correct. Array.ForEach(speciesArr, x => Assert.AreEqual(0.0, distanceMetric.GetDistance(x.Centroid, distanceMetric.CalculateCentroid(x.GenomeList.Select(y => y.ConnectionGenes))))); 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.IsTrue(GetNearestSpeciesList(genome, speciesArr, distanceMetric).Contains(species)))); } }
/// <summary> /// Get the index of the species with a centroid that is nearest to the provided genome. /// </summary> public static int GetNearestSpecies <T>( IDistanceMetric <T> distanceMetric, NeatGenome <T> genome, Species <T>[] speciesArr) where T : struct { int nearestSpeciesIdx = 0; double nearestDistance = distanceMetric.GetDistance(genome.ConnectionGenes, speciesArr[0].Centroid); for (int i = 1; i < speciesArr.Length; i++) { double distance = distanceMetric.GetDistance(genome.ConnectionGenes, speciesArr[i].Centroid); if (distance < nearestDistance) { nearestSpeciesIdx = i; nearestDistance = distance; } } return(nearestSpeciesIdx); }
/// <summary> /// Calculate the mean distance of the specified coord from all of the other coords using /// the provided distance metric. /// </summary> /// <param name="distanceMetric">The distance metric.</param> /// <param name="coordList">The list of coordinates.</param> /// <param name="idx">The index of the coordinate to measure distance to.</param> private static double CalculateMeanDistanceFromCoords(IDistanceMetric distanceMetric, IList <CoordinateVector> coordList, int idx) { double totalDistance = 0.0; int count = coordList.Count; CoordinateVector targetCoord = coordList[idx]; // Measure distance to all coords before the target one. for (int i = 0; i < idx; i++) { totalDistance += distanceMetric.GetDistance(targetCoord, coordList[i]); } // Measure distance to all coords after the target one. for (int i = idx + 1; i < count; i++) { totalDistance += distanceMetric.GetDistance(targetCoord, coordList[i]); } return(totalDistance / (count - 1)); }
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.GetDistance(species.Centroid, x.ConnectionGenes) > distanceMetric.GetDistance(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); }