Genome Species::ReproduceOne(Population& a_Pop, Parameters& a_Parameters, RNG& a_RNG) { Genome t_baby; // for storing the result ////////////////////////// // Reproduction // Spawn only one baby // this tells us if the baby is a result of mating bool t_mated = false; // There must be individuals there.. ASSERT(NumIndividuals() > 0); // for a species of size 1 we can only mutate // NOTE: but does it make sense since we know this is the champ? if (NumIndividuals() == 1) { t_baby = GetIndividual(a_Parameters, a_RNG); t_mated = false; } // else we can mate else { Genome t_mom = GetIndividual(a_Parameters, a_RNG); // choose whether to mate at all // Do not allow crossover when in simplifying phase if ((a_RNG.RandFloat() < a_Parameters.CrossoverRate) && (a_Pop.GetSearchMode() != SIMPLIFYING)) { // get the father Genome t_dad; bool t_interspecies = false; // There is a probability that the father may come from another species if ((a_RNG.RandFloat() < a_Parameters.InterspeciesCrossoverRate) && (a_Pop.m_Species.size()>1)) { // Find different species (random one) // !!!!!!!!!!!!!!!!! // But the different species must have at least one evaluated individual int t_diffspec = 0; int t_giveup = 64; do { t_diffspec = a_RNG.RandInt(0, static_cast<int>(a_Pop.m_Species.size()-1)); } while ((a_Pop.m_Species[t_diffspec].m_AverageFitness == 0) && (t_giveup--)); if (a_Pop.m_Species[t_diffspec].m_AverageFitness == 0) t_dad = GetIndividual(a_Parameters, a_RNG); else t_dad = a_Pop.m_Species[t_diffspec].GetIndividual(a_Parameters, a_RNG); t_interspecies = true; } else { // Mate within species t_dad = GetIndividual(a_Parameters, a_RNG); // The other parent should be a different one // number of tries to find different parent int t_tries = 32; while(((t_mom.GetID() == t_dad.GetID()) || ((!a_Parameters.AllowClones) && (t_mom.CompatibilityDistance(t_dad, a_Parameters) <= 0.00001)) ) && (t_tries--)) { t_dad = GetIndividual(a_Parameters, a_RNG); } t_interspecies = false; } // OK we have both mom and dad so mate them // Choose randomly one of two types of crossover if (a_RNG.RandFloat() < a_Parameters.MultipointCrossoverRate) { t_baby = t_mom.Mate( t_dad, false, t_interspecies, a_RNG); } else { t_baby = t_mom.Mate( t_dad, true, t_interspecies, a_RNG); } t_mated = true; } // don't mate - reproduce the mother asexually else { t_baby = t_mom; t_mated = false; } } /* if (t_baby.HasDeadEnds()) { std::cout << "Dead ends in baby after crossover" << std::endl; // int p; // std::cin >> p; }*/ // OK we have the baby, so let's mutate it. bool t_baby_is_clone = false; if ((!t_mated) || (a_RNG.RandFloat() < a_Parameters.OverallMutationRate)) MutateGenome(t_baby_is_clone, a_Pop, t_baby, a_Parameters, a_RNG); // We have a new offspring now // give the offspring a new ID t_baby.SetID(a_Pop.GetNextGenomeID()); a_Pop.IncrementNextGenomeID(); // sort the baby's genes t_baby.SortGenes(); // clear the baby's fitness t_baby.SetFitness(0); t_baby.SetAdjFitness(0); t_baby.SetOffspringAmount(0); t_baby.ResetEvaluated(); // debug trap /* if (t_baby.NumLinks() == 0) { std::cout << "No links in baby after reproduction" << std::endl; // int p; // std::cin >> p; } if (t_baby.HasDeadEnds()) { std::cout << "Dead ends in baby after reproduction" << std::endl; // int p; // std::cin >> p; } */ return t_baby; }
// Reproduce mates & mutates the individuals of the species // It may access the global species list in the population // because some babies may turn out to belong in another species // that have to be created. // Also calls Birth() for every new baby void Species::Reproduce(Population &a_Pop, Parameters& a_Parameters, RNG& a_RNG) { Genome t_baby; // temp genome for reproduction int t_offspring_count = Rounded(GetOffspringRqd()); // no offspring?! yikes.. dead species! if (t_offspring_count == 0) { // maybe do something else? return; } ////////////////////////// // Reproduction // Spawn t_offspring_count babies bool t_champ_chosen = false; bool t_baby_exists_in_pop = false; while(t_offspring_count--) { bool t_new_individual = true; // if the champ was not chosen, do it now.. if (!t_champ_chosen) { t_baby = m_Individuals[0]; t_champ_chosen = true; t_new_individual = false; } // or if it was, then proceed with the others else { do // - while the baby already exists somewhere in the new population { // this tells us if the baby is a result of mating bool t_mated = false; // There must be individuals there.. ASSERT(NumIndividuals() > 0); // for a species of size 1 we can only mutate // NOTE: but does it make sense since we know this is the champ? if (NumIndividuals() == 1) { t_baby = GetIndividual(a_Parameters, a_RNG); t_mated = false; } // else we can mate else { do // keep trying to mate until a good offspring is produced { Genome t_mom = GetIndividual(a_Parameters, a_RNG); // choose whether to mate at all // Do not allow crossover when in simplifying phase if ((a_RNG.RandFloat() < a_Parameters.CrossoverRate) && (a_Pop.GetSearchMode() != SIMPLIFYING)) { // get the father Genome t_dad; bool t_interspecies = false; // There is a probability that the father may come from another species if ((a_RNG.RandFloat() < a_Parameters.InterspeciesCrossoverRate) && (a_Pop.m_Species.size()>1)) { // Find different species (random one) // !!!!!!!!!!!!!!!!! int t_diffspec = a_RNG.RandInt(0, static_cast<int>(a_Pop.m_Species.size()-1)); t_dad = a_Pop.m_Species[t_diffspec].GetIndividual(a_Parameters, a_RNG); t_interspecies = true; } else { // Mate within species t_dad = GetIndividual(a_Parameters, a_RNG); // The other parent should be a different one // number of tries to find different parent int t_tries = 32; if (!a_Parameters.AllowClones) while(((t_mom.GetID() == t_dad.GetID()) || (t_mom.CompatibilityDistance(t_dad, a_Parameters) < 0.00001) ) && (t_tries--)) { t_dad = GetIndividual(a_Parameters, a_RNG); } else while(((t_mom.GetID() == t_dad.GetID()) ) && (t_tries--)) { t_dad = GetIndividual(a_Parameters, a_RNG); } t_interspecies = false; } // OK we have both mom and dad so mate them // Choose randomly one of two types of crossover if (a_RNG.RandFloat() < a_Parameters.MultipointCrossoverRate) { t_baby = t_mom.Mate( t_dad, false, t_interspecies, a_RNG); } else { t_baby = t_mom.Mate( t_dad, true, t_interspecies, a_RNG); } t_mated = true; } // don't mate - reproduce the mother asexually else { t_baby = t_mom; t_mated = false; } } while (t_baby.HasDeadEnds() || (t_baby.NumLinks() == 0)); // in case of dead ends after crossover we will repeat crossover // until it works } // Mutate the baby if ((!t_mated) || (a_RNG.RandFloat() < a_Parameters.OverallMutationRate)) MutateGenome(t_baby_exists_in_pop, a_Pop, t_baby, a_Parameters, a_RNG); // Check if this baby is already present somewhere in the offspring // we don't want that t_baby_exists_in_pop = false; // Unless of course, we want if (!a_Parameters.AllowClones) { for(unsigned int i=0; i<a_Pop.m_TempSpecies.size(); i++) { for(unsigned int j=0; j<a_Pop.m_TempSpecies[i].m_Individuals.size(); j++) { if ( (t_baby.CompatibilityDistance(a_Pop.m_TempSpecies[i].m_Individuals[j], a_Parameters) < 0.00001) // identical genome? ) { t_baby_exists_in_pop = true; break; } } } } } while (t_baby_exists_in_pop); // end do } // Final place to test for problems // If there is anything wrong here, we will just // pick a random individual and leave him unchanged if ((t_baby.NumLinks() == 0) || t_baby.HasDeadEnds()) { t_baby = GetIndividual(a_Parameters, a_RNG); t_new_individual = false; } if (t_new_individual) { // We have a new offspring now // give the offspring a new ID t_baby.SetID(a_Pop.GetNextGenomeID()); a_Pop.IncrementNextGenomeID(); // sort the baby's genes t_baby.SortGenes(); // clear the baby's fitness t_baby.SetFitness(0); t_baby.SetAdjFitness(0); t_baby.SetOffspringAmount(0); t_baby.ResetEvaluated(); } ////////////////////////////////// // put the baby to its species // ////////////////////////////////// // before Reproduce() is invoked, it is assumed that a // clone of the population exists with the name of m_TempSpecies // we will store results there. // after all reproduction completes, the original species will be replaced back bool t_found = false; std::vector<Species>::iterator t_cur_species = a_Pop.m_TempSpecies.begin(); // No species yet? if (t_cur_species == a_Pop.m_TempSpecies.end()) { // create the first species and place the baby there a_Pop.m_TempSpecies.push_back( Species(t_baby, a_Pop.GetNextSpeciesID())); a_Pop.IncrementNextSpeciesID(); } else { // try to find a compatible species Genome t_to_compare = t_cur_species->GetRepresentative(); t_found = false; while((t_cur_species != a_Pop.m_TempSpecies.end()) && (!t_found)) { if (t_baby.IsCompatibleWith( t_to_compare, a_Parameters)) { // found a compatible species t_cur_species->AddIndividual(t_baby); t_found = true; // the search is over } else { // keep searching for a matching species t_cur_species++; if (t_cur_species != a_Pop.m_TempSpecies.end()) { t_to_compare = t_cur_species->GetRepresentative(); } } } // if couldn't find a match, make a new species if (!t_found) { a_Pop.m_TempSpecies.push_back( Species(t_baby, a_Pop.GetNextSpeciesID())); a_Pop.IncrementNextSpeciesID(); } } } }