예제 #1
0
        public void MutateChild(Genome child)
        {
            if (child == null)
            {
                throw new ArgumentNullException(nameof(child));
            }

            if (this.random.NextDouble() < this.ParentSimulation.Parameters.AddNodeProbability)
            {
                child.AddNodeMutation(this.Innovations);
            }
            else if (this.random.NextDouble() < this.ParentSimulation.Parameters.AddConnectionProbability)
            {
                child.AddConnectionMutation(this.Innovations);
            }
            else
            {
                if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateConnectionWeightsProbability)
                {
                    child.MutateWeights(this.ParentSimulation.Parameters.WeightMutationPower);
                }
                if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateToggleEnabledProbability)
                {
                    child.ToggleEnabledMutation();
                }
                if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateReenableProbability)
                {
                    child.ReenableMutation();
                }
            }
        }
예제 #2
0
        // Performs reproduction of organisms in the genomes list
        public void Reproduce(List <Genome> nextGeneration, List <Innovation> innovations)
        {
            if (nextGeneration == null)
            {
                throw new ArgumentNullException(nameof(nextGeneration));
            }

            if (this.Offspring <= 0)
            {
                return;
            }

            bool championCloned = false;

            for (int i = 0; i < this.Offspring; ++i)
            {
                Genome child = null;
                if (this.ChampionOffspring > 0)
                {
                    child = this.GetChampion().Copy();
                    child.ParentSimulation = this.ParentSimulation;
                    if (this.ChampionOffspring > 1)
                    {
                        child.IsPopulationChampion = false;
                        child.Fitness         = 0.0;
                        child.OriginalFitness = 0.0;
                        if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateConnectionWeightsProbability)
                        {
                            child.MutateWeights(this.ParentSimulation.Parameters.WeightMutationPower);
                        }
                        else
                        {
                            child.AddConnectionMutation(innovations);
                        }
                    }
                    else
                    {
                        child.IsPopulationChampion = true;
                    }

                    --this.ChampionOffspring;
                }
                else if (!championCloned && this.Offspring > 5)
                {
                    child = this.GetChampion().Copy();
                    child.ParentSimulation     = this.ParentSimulation;
                    child.IsPopulationChampion = true;
                    championCloned             = true;
                }
                else
                {
                    // Mutate only (without crossover)
                    if (this.random.NextDouble() < this.ParentSimulation.Parameters.MutateWithoutCrossover)
                    {
                        // Select random genome to mutate
                        child = this.genomes[this.random.Next(this.genomes.Count)].Copy();
                        child.ParentSimulation     = this.ParentSimulation;
                        child.Fitness              = 0.0;
                        child.OriginalFitness      = 0.0;
                        child.IsPopulationChampion = false;
                        this.MutateChild(child);
                    }
                    // Perform crossover
                    else
                    {
                        // Select random parents
                        Genome parent1 = this.genomes[this.random.Next(this.genomes.Count)];
                        Genome parent2 = null;

                        // Find second parent INSIDE this species
                        if (this.random.NextDouble() > this.ParentSimulation.Parameters.InterspeciesMateRate)
                        {
                            parent2 = this.genomes[this.random.Next(this.genomes.Count)];
                        }
                        // Find second parent OUTSIDE this species - this should happen very very rarely
                        else
                        {
                            // TODO: possible modification - select only from better performing species
                            Species speciesFound = this;
                            int     tries        = 0;
                            while (speciesFound == this && tries++ < 5)
                            {
                                speciesFound = this.ParentSimulation.Species[this.random.Next(this.ParentSimulation.Species.Count)];
                            }
                            if (speciesFound.Genomes.Count == 0)
                            {
                                speciesFound = this;
                            }

                            parent2 = speciesFound.Genomes[this.random.Next(speciesFound.Genomes.Count)];
                        }

                        if (this.random.NextDouble() > this.ParentSimulation.Parameters.AverageCrossoverProbability)
                        {
                            child = parent1.Crossover(parent2, this.random);
                        }
                        else
                        {
                            child = parent2.CrossoverAverage(parent2, this.random);
                        }

                        // Mutate child
                        if (this.random.NextDouble() > this.ParentSimulation.Parameters.MateWithoutMutatingProbability || parent1 == parent2 || parent1.CompatibilityDistance(parent2) < 0.00001f)
                        {
                            this.MutateChild(child);
                        }
                    }
                }

                if (child != null)
                {
                    nextGeneration.Add(child);
                }
            }
        }