//Population.cpp #include "Population.h" //constructors/destructors template Population::Population () {} template Population::Population (int populationSize, int chromosomeSize) { size = populationSize; selectionWheel = new double[size]; chromosome = new Chromosome[size]; for (int counter = 0; counter < size; ++counter) { chromosome[counter].initialize(chromosomeSize); } v.initialize(chromosomeSize); } template Population::~Population () { delete []chromosome; delete []selectionWheel; } //assignment operator template Population& Population::operator= (const Population &pop) { if (this != &pop) { size = pop.size; fitness = pop.fitness; for (int counter = 0; counter < size; ++counter) { chromosome[counter] = pop.chromosome[counter]; } } return *this; } //readers template inline double Population::readFitness () {return fitness;} template inline int Population::readSize () {return size;} //display the entire population template void Population::displayPopulation () { for (int counter = 0; counter < size; ++counter) { for (int counter2 = 0; counter2 < chromosome[counter].size; ++counter2) { cout << chromosome[counter].gene[counter2] << " "; } cout << endl; } } //display part of the population template void Population::displayPopulation (int first, int last) { if ((first >= 0) && (last < size) && (last >= first)) { for (int counter = first; counter <= last; ++counter) { for (int counter2 = 0; counter2 < chromosome[counter].size; ++counter2) { cout << chromosome[counter].gene[counter2] << " "; } cout << endl; } } } //write a fitness into a selected chromomosome template void Population::writeChromosomeFitness (int chromosomeNumber, double newFitness) { chromosome[chromosomeNumber].fitness = newFitness; } //determine population fitness template double Population::determineFitness () { fitness = 0; for (int counter = 0; counter < size; ++counter) { fitness += chromosome[counter].fitness; } return fitness; } //set up fitness-proportionate selection //this function sets up a roulette wheel with slots proportional in size to the // fitness of each chromosome template void Population::setSelectionCriteria () { double scratch = 0; for (int counter = 0; counter < size; ++counter) { selectionWheel[counter] = chromosome[counter].fitness / fitness + scratch; scratch = selectionWheel[counter]; } } //return number of next selected chromosome template int Population::selectNextChromosome () { double scratch = double (rand()) / double (RAND_MAX); int chromosomeNumber = -1; while (selectionWheel[++chromosomeNumber] < scratch) { if (chromosomeNumber == (size-1)) break; } return chromosomeNumber; } //return a chromosome template inline Chromosome Population::returnChromosome (int chromosomeNumber){ return chromosome[chromosomeNumber]; } //replace a chromosome in the population template inline void Population::replaceChromosome (int chromosomeNumber, const Chromosome &chrom) { chromosome[chromosomeNumber] = chrom; } //reproduce two chromosomes template inline void Population::reproduce (int chromosome1, int chromosome2, int crossoverType) { chromosome[chromosome1].reproduce(chromosome[chromosome2], crossoverType); } //reproduce the entire population //write the new population into a second population object //use fitness-proportionate selection with replacement template void Population::reproduce (Population &targetPopulation, int crossoverType) { determineFitness(); //determine overall population fitness based on individual chromosome fitness values setSelectionCriteria(); //set up selection wheel for fitness-proportionate selection (or overload) //over entire population . . . for (int counter = 0; counter < size; counter +=2) { //select two parents int first = 0, second = 0; while (first == second) { //don't choose the same parent twice first = selectNextChromosome(); second = selectNextChromosome(); } targetPopulation.chromosome[counter] = chromosome[first]; targetPopulation.chromosome[counter+1] = chromosome[second]; chromosome[counter].reproduce(chromosome[counter+1], crossoverType); } } //reproduce the entire population //use fitness-proportionate selection without replacement // (each parent reproduces only once) //NOTE: this zeros the fitness values in the parent population template void Population::reproduceWithoutReplacement (Population &targetPopulation, int crossoverType) { determineFitness(); //determine overall population fitness based on individual chromosome fitness values setSelectionCriteria(); //set up selection wheel for fitness-proportionate selection (or overload) //over entire population . . . for (int counter = 0; counter < size; counter +=2) { int first, second; //select two parents do { do {first = selectNextChromosome();} while (chromosome[first].fitness==0); do {second = selectNextChromosome();} while (chromosome[second].fitness==0); } while (first==second); //don't select the same parent twice targetPopulation.chromosome[counter] = chromosome[first]; targetPopulation.chromosome[counter+1] = chromosome[second]; chromosome[counter].reproduce(chromosome[counter+1], crossoverType); } } //mutate the entire population template int Population::mutate (double mutationProbability = 0.01) { int numberMutations = 0; for (int counter = 0; counter < size; ++counter) { numberMutations += chromosome[counter].mutate(mutationProbability); } return numberMutations; } //used by quicksort template void Population::swap (int a, int b) { v = chromosome[a]; chromosome[a] = chromosome[b]; chromosome[b] = v; } //quicksort - orders genes by increasing fitness template void Population::quicksort (int left, int right) { int i, j; double scratch; if (right > left) { scratch = chromosome[right].fitness; i = left - 1; j = right; for (;;) { while (chromosome[++i].fitness > scratch); while (chromosome[--j].fitness < scratch); if (i >= j) break; swap (i, j); } swap (i, right); quicksort (left, i-1); quicksort (i+1, right); } }