Esempio n. 1
0
        /// <summary>
        /// Handle specific case where all genomes/species have a zero fitness.
        /// </summary>
        private static int CalcSpeciesTargetSizesInner_ZeroTotalMeanFitness(NeatPopulation <T> pop, IRandomSource rng)
        {
            // Assign all species an equal targetSize.
            Species <T>[] speciesArr     = pop.SpeciesArray;
            double        popSizeReal    = pop.GenomeList.Count;
            double        targetSizeReal = popSizeReal / speciesArr.Length;

            // Keep a total of all allocated target sizes, typically this will vary slightly from the
            // required target population size due to rounding of each real valued target size.
            int totalTargetSizeInt = 0;

            for (int i = 0; i < speciesArr.Length; i++)
            {
                SpeciesStats stats = speciesArr[i].Stats;
                stats.TargetSizeReal = targetSizeReal;

                // Stochastic rounding will result in equal allocation if targetSizeReal is a whole
                // number, otherwise it will help to distribute allocations fairly.
                stats.TargetSizeInt = (int)NumericsUtils.ProbabilisticRound(targetSizeReal, rng);

                // Total up discretized target sizes.
                totalTargetSizeInt += stats.TargetSizeInt;
            }

            return(totalTargetSizeInt);
        }
Esempio n. 2
0
        private static void AdjustSpeciesTargetSizes(
            NeatPopulation <T> pop,
            int totalTargetSizeInt,
            IRandomSource rng)
        {
            // Discretized target sizes may total up to a value that is not equal to the required population size.
            // Here we check this and if the total does not match the required population size then we adjust the
            // species' targetSizeInt values to compensate for the difference.
            int targetSizeDeltaInt = totalTargetSizeInt - pop.PopulationSize;

            if (targetSizeDeltaInt < 0)
            {
                // Target size is too low; adjust up.
                AdjustSpeciesTargetSizesUp(pop.SpeciesArray, targetSizeDeltaInt, rng);
            }
            else if (targetSizeDeltaInt > 0)
            {
                // Target size is too high; adjust down.
                AdjustSpeciesTargetSizesDown(pop.SpeciesArray, targetSizeDeltaInt, rng);
            }

            // Ensure a non-zero target size for the species that contains the best genome.
            AdjustSpeciesTargetSizes_AccommodateBestGenomeSpecies(pop, rng);

            // Assert that Sum(TargetSizeInt) == popSize.
            Debug.Assert(pop.SpeciesArray.Sum(x => x.Stats.TargetSizeInt) == pop.PopulationSize);
        }
Esempio n. 3
0
        private static void UpdateSpeciesTargetSizes(
            NeatPopulation <T> pop, IRandomSource rng)
        {
            double totalMeanFitness   = pop.NeatPopulationStats.SumSpeciesMeanFitness;
            int    totalTargetSizeInt = 0;

            // Handle specific case where all genomes/species have a zero fitness.
            // Assign all species an equal targetSize.
            if (0.0 == totalMeanFitness)
            {
                totalTargetSizeInt = CalcSpeciesTargetSizesInner_ZeroTotalMeanFitness(pop, rng);
            }
            else
            {
                // Calculate the new target size of each species using fitness sharing.
                double        popSizeReal = pop.GenomeList.Count;
                Species <T>[] speciesArr  = pop.SpeciesArray;

                // The size of each specie is based on its fitness relative to the other species.
                for (int i = 0; i < speciesArr.Length; i++)
                {
                    SpeciesStats stats = speciesArr[i].Stats;
                    stats.TargetSizeReal = (stats.MeanFitness / totalMeanFitness) * popSizeReal;

                    // Discretize targetSize (stochastic rounding).
                    stats.TargetSizeInt = (int)NumericsUtils.ProbabilisticRound(stats.TargetSizeReal, rng);

                    // Total up discretized target sizes.
                    totalTargetSizeInt += stats.TargetSizeInt;
                }
            }

            // Adjust each species' target allocation such that the sum total matches the required population size.
            AdjustSpeciesTargetSizes(pop, totalTargetSizeInt, rng);
        }
Esempio n. 4
0
        /// <summary>
        /// Create a new instance of <see cref="NeatEvolutionAlgorithm{T}"/> for the given neat experiment.
        /// </summary>
        /// <param name="neatExperiment">A neat experiment instance; this conveys everything required to create a new evolution algorithm instance that is ready to be run.</param>
        /// <returns>A new instance of <see cref="NeatEvolutionAlgorithm{T}"/>.</returns>
        public static NeatEvolutionAlgorithm <double> CreateNeatEvolutionAlgorithm(
            INeatExperiment <double> neatExperiment)
        {
            // Create a genomeList evaluator based on the experiment's configuration settings.
            var genomeListEvaluator = CreateGenomeListEvaluator(neatExperiment);

            // Create a MetaNeatGenome.
            var metaNeatGenome = CreateMetaNeatGenome(neatExperiment);

            // Create an initial population of genomes.
            NeatPopulation <double> neatPop = NeatPopulationFactory <double> .CreatePopulation(
                metaNeatGenome,
                connectionsProportion : neatExperiment.InitialInterconnectionsProportion,
                popSize : neatExperiment.PopulationSize);

            // Create a speciation strategy based on the experiment's configuration settings.
            var speciationStrategy = CreateSpeciationStrategy(neatExperiment);

            // Create an instance of the default connection weight mutation scheme.
            var weightMutationScheme = WeightMutationSchemeFactory.CreateDefaultScheme(neatExperiment.ConnectionWeightScale);

            // Pull all of the parts together into an evolution algorithm instance.
            var ea = new NeatEvolutionAlgorithm <double>(
                neatExperiment.NeatEvolutionAlgorithmSettings,
                genomeListEvaluator,
                speciationStrategy,
                neatPop,
                neatExperiment.ComplexityRegulationStrategy,
                neatExperiment.ReproductionAsexualSettings,
                neatExperiment.ReproductionSexualSettings,
                weightMutationScheme);

            return(ea);
        }
Esempio n. 5
0
        /// <summary>
        /// Create a new instance of <see cref="NeatEvolutionAlgorithm{T}"/> for the given neat experiment, and neat population.
        /// </summary>
        /// <param name="neatExperiment">A neat experiment instance; this conveys everything required to create a new evolution algorithm instance that is ready to be run.</param>
        /// <param name="neatPop">A pre constructed/loaded neat population; this must be compatible with the provided neat experiment, otherwise an exception will be thrown.</param>
        /// <returns>A new instance of <see cref="NeatEvolutionAlgorithm{T}"/>.</returns>
        public static NeatEvolutionAlgorithm <double> CreateNeatEvolutionAlgorithm(
            INeatExperiment <double> neatExperiment,
            NeatPopulation <double> neatPop)
        {
            // Validate MetaNeatGenome and NeatExperiment are compatible; normally the former should have been created based on the latter, but this is not enforced.
            MetaNeatGenome <double> metaNeatGenome = neatPop.MetaNeatGenome;

            ValidateCompatible(neatExperiment, metaNeatGenome);

            // Create a genomeList evaluator based on the experiment's configuration settings.
            var genomeListEvaluator = CreateGenomeListEvaluator(neatExperiment);

            // Create a speciation strategy based on the experiment's configuration settings.
            var speciationStrategy = CreateSpeciationStrategy(neatExperiment);

            // Create an instance of the default connection weight mutation scheme.
            var weightMutationScheme = WeightMutationSchemeFactory.CreateDefaultScheme(neatExperiment.ConnectionWeightScale);

            // Pull all of the parts together into an evolution algorithm instance.
            var ea = new NeatEvolutionAlgorithm <double>(
                neatExperiment.NeatEvolutionAlgorithmSettings,
                genomeListEvaluator,
                speciationStrategy,
                neatPop,
                neatExperiment.ComplexityRegulationStrategy,
                neatExperiment.ReproductionAsexualSettings,
                neatExperiment.ReproductionSexualSettings,
                weightMutationScheme);

            return(ea);
        }
Esempio n. 6
0
        /// <summary>
        /// Calc and store species target sizes based on relative mean fitness of each species, i.e. as per NEAT fitness sharing method.
        /// Then calc and store the elite, selection and offspring allocations/counts, per species.
        /// </summary>
        public static void UpdateSpeciesAllocationSizes(
            NeatPopulation <T> pop,
            NeatEvolutionAlgorithmSettings eaSettings,
            IRandomSource rng)
        {
            // Calculate the new target size of each species using fitness sharing.
            UpdateSpeciesTargetSizes(pop, rng);

            // Calculate elite, selection and offspring counts, per species.
            UpdateEliteSelectionOffspringCounts(pop, eaSettings, rng);
        }
Esempio n. 7
0
        private static void AdjustSpeciesTargetSizes_AccommodateBestGenomeSpecies(
            NeatPopulation <T> pop, IRandomSource rng)
        {
            // Test if the best genome is in a species with a zero target size allocation.
            int bestGenomeSpeciesIdx = pop.NeatPopulationStats.BestGenomeSpeciesIdx;

            Species <T>[] speciesArr = pop.SpeciesArray;
            if (speciesArr[bestGenomeSpeciesIdx].Stats.TargetSizeInt > 0)
            {
                // Nothing to do. The best genome is in a species with a non-zero allocation.
                return;
            }

            // Set the target size of the best genome species to a allow the best genome to survive to the next generation.
            speciesArr[bestGenomeSpeciesIdx].Stats.TargetSizeInt++;

            // Adjust down the target size of one of the other species to compensate.
            // Pick a species at random (but not the champ species). Note that this may result in a species with a zero
            // target size, this is OK at this stage. We handle allocations of zero elsewhere.

            // Create an array of shuffled indexes to select from, i.e. all of the species except for the one with the best genome in it.
            int speciesCount = speciesArr.Length;

            int[] speciesIdxArr = new int[speciesCount - 1];

            for (int i = 0; i < bestGenomeSpeciesIdx; i++)
            {
                speciesIdxArr[i] = i;
            }
            for (int i = bestGenomeSpeciesIdx + 1; i < speciesCount; i++)
            {
                speciesIdxArr[i - 1] = i;
            }
            SortUtils.Shuffle(speciesIdxArr, rng);

            // Loop the species indexes.
            bool success = false;

            foreach (int speciesIdx in speciesIdxArr)
            {
                if (speciesArr[speciesIdx].Stats.TargetSizeInt > 0)
                {
                    speciesArr[speciesIdx].Stats.TargetSizeInt--;
                    success = true;
                    break;
                }
            }

            if (!success)
            {
                throw new Exception("All species have a zero target size.");
            }
        }
Esempio n. 8
0
        /// <summary>
        /// For each species, allocate the EliteSizeInt, OffspringCount (broken down into OffspringAsexualCount and OffspringSexualCount),
        /// and SelectionSizeInt values.
        /// </summary>
        /// <param name="pop"></param>
        /// <param name="eaSettings"></param>
        /// <param name="rng"></param>
        private static void UpdateEliteSelectionOffspringCounts(
            NeatPopulation <T> pop,
            NeatEvolutionAlgorithmSettings eaSettings,
            IRandomSource rng)
        {
            Species <T>[] speciesArr = pop.SpeciesArray;

            // Loop the species, calculating and storing the various size/count properties.
            int bestGenomeSpeciesIdx = pop.NeatPopulationStats.BestGenomeSpeciesIdx;

            for (int i = 0; i < speciesArr.Length; i++)
            {
                bool isBestGenomeSpecies = (bestGenomeSpeciesIdx == i);
                AllocateEliteSelectionOffspringCounts(speciesArr[i], eaSettings, isBestGenomeSpecies, rng);
            }
        }