/** * In NEAT, we provide the algorithm with a start individual from file, * after read the start individual from file, we populate the subpopulation with * mutated version of that template individual. The number of individual we create is * determined by the "pop.subpop.X.size" parameter. */ public override Population InitialPopulation(IEvolutionState state, int thread) { // read in the start genome as the template Population p = SetupPopulation(state, thread); p.Populate(state, thread); // go through all the population and populate the NEAT subpop foreach (Subpopulation subpop in p.Subpops) { // NEAT uses a template to populate the population // we first read it in to form the population, then mutate the links if (subpop.Species is NEATSpecies) { NEATSpecies species = (NEATSpecies)subpop.Species; IList <Individual> inds = subpop.Individuals; // get the template NEATIndividual templateInd = (NEATIndividual)inds[0]; // clear the individuals inds.Clear(); // spawn the individuals with template int initialSize = subpop.InitialSize; for (int j = 0; j < initialSize; ++j) { NEATIndividual newInd = species.SpawnWithTemplate(state, species, thread, templateInd); inds.Add(newInd); } // state.output.warnOnce("Template genome found, populate the subpopulation with template individual"); // templateInd.printIndividual(state, 0); // set the next available innovation number and node id species.SetInnovationNumber(templateInd.GetGeneInnovationNumberSup()); species.CurrNodeId = templateInd.GetNodeIdSup(); // speciate foreach (Individual ind in inds) { species.Speciate(state, ind); } // switch to the new generation foreach (NEATSubspecies s in species.Subspecies) { s.ToNewGeneration(); } } } return(p); }
/** Spawn a new individual with given individual as template. */ public NEATIndividual SpawnWithTemplate(IEvolutionState state, NEATSpecies species, int thread, NEATIndividual ind) { // we clone but do not reset the individual, since these individuals are // made from template NEATIndividual newInd = (NEATIndividual)ind.Clone(); // for first generation of population, we do not use the weight mutation // power from the file newInd.MutateLinkWeights(state, thread, species, 1.0, 1.0, NEATSpecies.MutationType.GAUSSIAN); newInd.SetGeneration(state); newInd.CreateNetwork(); // we create the network after we have the // complete genome return(newInd); }
/** * This method simply call breedNewPopulation method in NEATSpecies,where * all the critical work in done. */ public override Population BreedPopulation(IEvolutionState state) { Population pop = state.Population; for (int i = 0; i < pop.Subpops.Count; i++) { Subpopulation subpop = pop.Subpops[i]; if (!(subpop.Species is NEATSpecies)) // uh oh { state.Output.Fatal("To use NEATSpecies, subpopulation " + i + " must contain a NEATSpecies. But it contains a " + subpop.Species); } NEATSpecies species = (NEATSpecies)subpop.Species; species.BreedNewPopulation(state, i, 0); } return(pop); }
/** * Where the actual reproduce is happening, it will grab the candidate * parents, and calls the crossover or mutation method on these parents * individuals. */ public bool Reproduce(IEvolutionState state, int thread, int subpop, IList <NEATSubspecies> sortedSubspecies) { if (ExpectedOffspring > 0 && Individuals.Count == 0) { state.Output.Fatal("Attempt to reproduce out of empty subspecies"); return(false); } if (ExpectedOffspring > state.Population.Subpops[subpop].InitialSize) { state.Output.Fatal("Attempt to reproduce too many individuals"); return(false); } NEATSpecies species = (NEATSpecies)state.Population.Subpops[subpop].Species; // bestIndividual of the 'this' specie is the first element of the // species // note, we already sort the individuals based on the fitness (not sure // if this is still correct to say) NEATIndividual bestIndividual = (NEATIndividual)First(); // create the designated number of offspring for the Species one at a // time bool bestIndividualDone = false; for (int i = 0; i < ExpectedOffspring; ++i) { NEATIndividual newInd; if (bestIndividual.SuperChampionOffspring > 0) { newInd = (NEATIndividual)bestIndividual.Clone(); // Most super champion offspring will have their connection // weights mutated only // The last offspring will be an exact duplicate of this super // champion // Note: Super champion offspring only occur with stolen babies! // Settings used for published experiments did not use this if (bestIndividual.SuperChampionOffspring > 1) { if (state.Random[thread].NextBoolean(0.8) || species.MutateAddLinkProb.Equals(0.0)) { newInd.MutateLinkWeights(state, thread, species, species.WeightMutationPower, 1.0, NEATSpecies.MutationType.GAUSSIAN); } else { // Sometime we add a link to a superchamp newInd.CreateNetwork(); // make sure we have the network newInd.MutateAddLink(state, thread); } } if (bestIndividual.SuperChampionOffspring == 1) { if (bestIndividual.PopChampion) { newInd.PopChampionChild = true; newInd.HighFit = bestIndividual.Fitness.Value; } } bestIndividual.SuperChampionOffspring--; } else if (!bestIndividualDone && ExpectedOffspring > 5) { newInd = (NEATIndividual)bestIndividual.Clone(); bestIndividualDone = true; } // Decide whether to mate or mutate // If there is only one individual, then always mutate else if (state.Random[thread].NextBoolean(species.MutateOnlyProb) || Individuals.Count == 1) { // Choose the random parent int parentIndex = state.Random[thread].NextInt(Individuals.Count); Individual parent = Individuals[parentIndex]; newInd = (NEATIndividual)parent.Clone(); newInd.DefaultMutate((EvolutionState)state, thread); } else // Otherwise we should mate { // random choose the first parent int parentIndex = state.Random[thread].NextInt(Individuals.Count); NEATIndividual firstParent = (NEATIndividual)Individuals[parentIndex]; NEATIndividual secondParent; // Mate within subspecies, choose random second parent if (state.Random[thread].NextBoolean(1.0 - species.InterspeciesMateRate)) { parentIndex = state.Random[thread].NextInt(Individuals.Count); secondParent = (NEATIndividual)Individuals[parentIndex]; } else // Mate outside subspecies { // Select a random species NEATSubspecies randomSubspecies = this; // Give up if you cant find a different Species int giveUp = 0; while (randomSubspecies == this && giveUp < 5) { // Choose a random species tending towards better // species double value = state.Random[thread].NextGaussian() / 4; if (value > 1.0) { value = 1.0; } // This tends to select better species int upperBound = (int)Math.Floor(value * (sortedSubspecies.Count - 1.0) + 0.5); int index = 0; while (index < upperBound) { index++; } randomSubspecies = sortedSubspecies[index]; giveUp++; } secondParent = (NEATIndividual)randomSubspecies.First(); } newInd = firstParent.Crossover(state, thread, secondParent); // Determine whether to mutate the baby's Genome // This is done randomly or if the parents are the same // individual if (state.Random[thread].NextBoolean(1.0 - species.MateOnlyProb) || firstParent == secondParent || species.Compatibility(firstParent, secondParent).Equals(0.0)) { newInd.DefaultMutate((EvolutionState)state, thread); } } newInd.SetGeneration(state); newInd.CreateNetwork(); // Add the new individual to its proper subspecies // this could create new subspecies species.Speciate(state, newInd); } return(true); }