//------------------------- FitnessScaleBoltzmann ------------------------ // // This function applies Boltzmann scaling to a populations fitness // scores as described in Chapter 5. // The static value Temp is the boltzmann temperature which is reduced // each generation by a small amount. As Temp decreases the difference // spread between the high and low fitnesses increases. //------------------------------------------------------------------------ void CgaTSP::FitnessScaleBoltzmann(vector<SGenome> &pop) { //reduce the temp a little each generation m_dBoltzmannTemp -= BOLTZMANN_DT; //make sure it doesn't fall below minimum value if (m_dBoltzmannTemp< BOLTZMANN_MIN_TEMP) { m_dBoltzmannTemp = BOLTZMANN_MIN_TEMP; } //first calculate the average fitness/Temp double divider = m_dAverageFitness/m_dBoltzmannTemp; //now iterate through the population and calculate the new expected //values for (int gen=0; gen<pop.size(); ++gen) { double OldFitness = pop[gen].dFitness; pop[gen].dFitness = (OldFitness/m_dBoltzmannTemp)/divider; } //recalculate values used in selection CalculateBestWorstAvTot(); }
//-----------------------CalculatePopulationsFitness-------------------------- // // calculates the fitness of each member of the population, updates the // fittest, the worst, keeps a sum of the total fittness scores and the // average fitness score of the population (most of these stats are required // when we apply pre-selection fitness scaling. //----------------------------------------------------------------------------- void CgaTSP::CalculatePopulationsFitness() { for (int i=0; i<m_iPopSize; ++i) { double TourLength = m_pMap->GetTourLength(m_vecPopulation[i].vecCities); m_vecPopulation[i].dFitness = TourLength; //keep a track of the shortest route found each generation if (TourLength < m_dShortestRoute) { m_dShortestRoute = TourLength; } //keep a track of the worst tour each generation if (TourLength > m_dLongestRoute) { m_dLongestRoute = TourLength; } }//next chromo //Now we have calculated all the tour lengths we can assign //the fitness scores for (i=0; i<m_iPopSize; ++i) { m_vecPopulation[i].dFitness = m_dLongestRoute - m_vecPopulation[i].dFitness; } //calculate values used in selection CalculateBestWorstAvTot(); }
//----------------------------- FitnessScaleSigma ------------------------ // // Scales the fitness using sigma scaling based on the equations given // in Chapter 5 of the book. //------------------------------------------------------------------------ void CgaTSP::FitnessScaleSigma(vector<SGenome> &pop) { double RunningTotal = 0; //first iterate through the population to calculate the standard //deviation for (int gen=0; gen<pop.size(); ++gen) { RunningTotal += (pop[gen].dFitness - m_dAverageFitness) * (pop[gen].dFitness - m_dAverageFitness); } double variance = RunningTotal/(double)m_iPopSize; //standard deviation is the square root of the variance m_dSigma = sqrt(variance); //now iterate through the population to reassign the fitness scores for (gen=0; gen<pop.size(); ++gen) { double OldFitness = pop[gen].dFitness; pop[gen].dFitness = (OldFitness - m_dAverageFitness) / (2 * m_dSigma); } //recalculate values used in selection CalculateBestWorstAvTot(); }
//-----------------------------------Epoch()----------------------------- // // takes a population of chromosones and runs the algorithm through one // cycle. // Returns a new population of chromosones. //----------------------------------------------------------------------- vector<SGenome> CGenAlg::Epoch(vector<SGenome> &old_pop) { //assign the given population to the classes population m_vecPop = old_pop; //reset the appropriate variables Reset(); //create a temporary vector to store new chromosones vector <SGenome> vecNewPop; CalculateBestWorstAvTot(); //sort the population (for scaling and elitism) sort(m_vecPop.begin(), m_vecPop.end()); //Now to add a little elitism we shall add in some copies of the //fittest genomes. Make sure we add an EVEN number or the roulette //wheel sampling will crash if (!(CParams::iNumCopiesElite * CParams::iNumElite % 2)) { GrabNBest(CParams::iNumElite, CParams::iNumCopiesElite, vecNewPop); } //--------------now to enter the GA loop //repeat until a new population is generated while (vecNewPop.size() < m_iPopSize) { //select using tournament selection for a change SGenome mum = TournamentSelection(CParams::iTournamentCompetitors); SGenome dad = TournamentSelection(CParams::iTournamentCompetitors); //create some offspring via crossover vector<double> baby1, baby2; CrossoverAtSplits(mum.vecWeights, dad.vecWeights, baby1, baby2); //now we mutate Mutate(baby1); Mutate(baby2); //now copy into vecNewPop population vecNewPop.push_back( SGenome(baby1, 0) ); vecNewPop.push_back( SGenome(baby2, 0) ); } //finished so assign new pop back into m_vecPop m_vecPop = vecNewPop; return m_vecPop; }
//-----------------------------------Epoch()----------------------------- // // takes a population of chromosones and runs the algorithm through one // cycle. // Returns a new population of chromosones. // //----------------------------------------------------------------------- vector<Genome> GenAlg::Epoch(vector<Genome> &old_pop) { //assign the given population to the classes population mPop = old_pop; //reset the appropriate variables Reset(); //sort the population (for scaling and elitism) sort(mPop.begin(), mPop.end()); //calculate best, worst, average and total fitness CalculateBestWorstAvTot(); //create a temporary vector to store new chromosones vector <Genome> vecNewPop; //Now to add a little elitism we shall add in some copies of the //fittest genomes. Make sure we add an EVEN number or the roulette //wheel sampling will crash if (!(NUM_COPIES_ELITE * NUM_ELITE % 2)) { GrabNBest(NUM_ELITE, NUM_COPIES_ELITE, vecNewPop); } //now we enter the GA loop //repeat until a new population is generated while (vecNewPop.size() < mPopSize) { //grab two chromosones Genome mum = GetChromoRoulette(); Genome dad = GetChromoRoulette(); //create some offspring via crossover vector<double> baby1, baby2; Crossover(mum.weights, dad.weights, baby1, baby2); //now we mutate Mutate(baby1); Mutate(baby2); //now copy into vecNewPop population vecNewPop.push_back(Genome(baby1, 0)); vecNewPop.push_back(Genome(baby2, 0)); } //finished so assign new pop back into m_vecPop mPop = vecNewPop; return mPop; }
//----------------------- SUSSelection ----------------------------------- // // This function performs Stochasitic Universal Sampling. // // SUS uses N evenly spaced hands which are spun once to choose the // new population. As described in chapter 5. //------------------------------------------------------------------------ void CgaTSP::SUSSelection(vector<SGenome> &NewPop) { //this algorithm relies on all the fitnesses to be positive so //these few lines check and adjust accordingly (in this example //Sigma scaling can give negative fitnesses if (m_dWorstFitness < 0) { //recalculate for (int gen=0; gen<m_vecPopulation.size(); ++gen) { m_vecPopulation[gen].dFitness += fabs(m_dWorstFitness); } CalculateBestWorstAvTot(); } int curGen = 0; double sum = 0; //NumToAdd is the amount of individuals we need to select using SUS. //Remember, some may have already been selected through elitism int NumToAdd = m_iPopSize - NewPop.size(); //calculate the hand spacing double PointerGap = m_dTotalFitness/(double)NumToAdd; //choose a random start point for the wheel float ptr = RandFloat() * PointerGap; while (NewPop.size() < NumToAdd) { for(sum+=m_vecPopulation[curGen].dFitness; sum > ptr; ptr+=PointerGap) { NewPop.push_back(m_vecPopulation[curGen]); if( NewPop.size() == NumToAdd) { return; } } ++curGen; } }
//-----------------------------FitnessScaleRank---------------------- // // This type of fitness scaling sorts the population into ascending // order of fitness and then simply assigns a fitness score based // on its position in the ladder. (so if a genome ends up last it // gets score of zero, if best then it gets a score equal to the size // of the population. //--------------------------------------------------------------------- void CgaTSP::FitnessScaleRank(vector<SGenome> &pop) { //sort population into ascending order if (!m_bSorted) { sort(pop.begin(), pop.end()); m_bSorted = true; } //now assign fitness according to the genome's position on //this new fitness 'ladder' for (int i=0; i<pop.size(); i++) { pop[i].dFitness = i; } //recalculate values used in selection CalculateBestWorstAvTot(); }
TArray<FGenome> GeneticAlg::Epoch(TArray<FGenome> &OldPop) { PopArray = OldPop; Reset(); PopArray.Sort(); //sorts Fgenomes by fitness CalculateBestWorstAvTot(); TArray<FGenome> NewPop; if (!(NumCopiesElite * NumElites % 2)) { GrabNBest(NumElites, NumCopiesElite, NewPop); } while (NewPop.Num() < PopulationSize) { //grab two chromosones FGenome mum = GetChromoRoulette(); FGenome dad = GetChromoRoulette(); //create some offspring via crossover TArray<float> baby1, baby2; CrossOver(mum.WeightsArray, dad.WeightsArray, baby1, baby2); //now we mutate Mutate(baby1); Mutate(baby2); //now copy into vecNewPop population NewPop.Add(FGenome(baby1, 0)); NewPop.Add(FGenome(baby2, 0)); } //finished so assign new pop back into m_vecPop PopArray = NewPop; return PopArray; }