// returns an individual randomly selected from the best N% Genome Species::GetIndividual(Parameters& a_Parameters, RNG& a_RNG) const { ASSERT(m_Individuals.size() > 0); // Make a pool of only evaluated individuals! std::vector<Genome> t_Evaluated; for(unsigned int i=0; i<m_Individuals.size(); i++) { if (m_Individuals[i].IsEvaluated()) t_Evaluated.push_back( m_Individuals[i] ); } ASSERT(t_Evaluated.size() > 0); if (t_Evaluated.size() == 1) { return (t_Evaluated[0]); } else if (t_Evaluated.size() == 2) { return (t_Evaluated[ Rounded(a_RNG.RandFloat()) ]); } // Warning!!!! The individuals must be sorted by best fitness for this to work int t_chosen_one=0; // Here might be introduced better selection scheme, but this works OK for now if (!a_Parameters.RouletteWheelSelection) { //start with the last one just for comparison sake int temp_genome; int t_num_parents = static_cast<int>( floor((a_Parameters.SurvivalRate * (static_cast<double>(t_Evaluated.size())))+1.0)); ASSERT(t_num_parents>0); if (t_num_parents>=t_Evaluated.size()) t_num_parents = t_Evaluated.size()-1; t_chosen_one = a_RNG.RandInt(0, t_num_parents); for (unsigned int i = 0; i < a_Parameters.TournamentSize; i++) { temp_genome = a_RNG.RandInt(0, t_num_parents); if (m_Individuals[temp_genome].GetFitness() > m_Individuals[t_chosen_one].GetFitness()) { t_chosen_one = temp_genome; } } } else { // roulette wheel selection std::vector<double> t_probs; for(unsigned int i=0; i<t_Evaluated.size(); i++) t_probs.push_back( t_Evaluated[i].GetFitness() ); t_chosen_one = a_RNG.Roulette(t_probs); } return (t_Evaluated[t_chosen_one]); }
// returns a completely random individual Genome Species::GetRandomIndividual(RNG& a_RNG) const { if (m_Individuals.size() == 0) // no members yet, return representative { return m_Representative; } else { int t_rand_choice = 0; t_rand_choice = a_RNG.RandInt(0, static_cast<int>(m_Individuals.size()-1)); return (m_Individuals[t_rand_choice]); } }
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(); } } } }