// Return 0 if everything is OK, non-zero if error. If we did not set anything // then we return non-zero (this is not an error, but we indicate that we did // not do anything). // The set method must set both the GA's parameter and the value in the // parameter list (kind of stupid to maintain two copies of the same data, but // oh well). The call to set on params is redundant for the times when this // method is called *after* the parameter list has been updated, but it is // necessary when this method is called directly by the user. int GAGeneticAlgorithm::setptr(const char* name, const void* value){ int status=1; params.set(name, value); // redundant for some cases, but not others if(strcmp(name, gaNnBestGenomes) == 0 || strcmp(name, gaSNnBestGenomes) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif nBestGenomes(*((int*)value)); status = 0; } else if(strcmp(name, gaNpopulationSize) == 0 || strcmp(name, gaSNpopulationSize) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif populationSize(*((int*)value)); status = 0; } else if(strcmp(name, gaNminimaxi) == 0 || strcmp(name, gaSNminimaxi) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif minimaxi(*((int*)value)); status = 0; } else if(strcmp(name, gaNnGenerations) == 0 || strcmp(name, gaSNnGenerations) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif nGenerations(*((int*)value)); status = 0; } else if(strcmp(name, gaNpConvergence) == 0 || strcmp(name, gaSNpConvergence) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((float*)value) << "'\n"; #endif pConvergence(*((float*)value)); status = 0; } else if(strcmp(name, gaNnConvergence) == 0 || strcmp(name, gaSNnConvergence) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif nConvergence(*((int*)value)); status = 0; } else if(strcmp(name, gaNpCrossover) == 0 || strcmp(name, gaSNpCrossover) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((float*)value) << "'\n"; #endif pCrossover(*((float*)value)); status = 0; } else if(strcmp(name, gaNpMutation) == 0 || strcmp(name, gaSNpMutation) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((float*)value) << "'\n"; #endif pMutation(*((float*)value)); status = 0; } else if(strcmp(name,gaNscoreFrequency) == 0 || strcmp(name,gaSNscoreFrequency) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif stats.scoreFrequency(*((int*)value)); status = 0; } else if(strcmp(name,gaNflushFrequency) == 0 || strcmp(name,gaSNflushFrequency) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif stats.flushFrequency(*((int*)value)); status = 0; } else if(strcmp(name,gaNrecordDiversity) == 0 || strcmp(name,gaSNrecordDiversity) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif stats.recordDiversity(*((int*)value) ? gaTrue : gaFalse); status = 0; } else if(strcmp(name,gaNselectScores) == 0 || strcmp(name,gaSNselectScores)==0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << *((int*)value) << "'\n"; #endif stats.selectScores(*((int*)value)); status = 0; } else if(strcmp(name,gaNscoreFilename) == 0 || strcmp(name,gaSNscoreFilename) == 0){ #ifdef GA_DEBUG cerr << "GAGeneticAlgorithm::setptr\n setting '" << name << "' to '" << ((char*)value) << "'\n"; #endif char tmpname[64]; memcpy(tmpname, value, strlen((char*)value)+1); stats.scoreFilename(tmpname); status = 0; } return status; }
// Evolve a new generation of genomes. When we start this routine, pop // contains the current generation. When we finish, pop contains the new // generation and oldPop contains the (no longer) current generation. The // previous old generation is lost. We don't deallocate any memory, we just // reset the contents of the genomes. // The selection routine must return a pointer to a genome from the old // population. void GASimpleGA::step() { int i, mut, c1, c2; GAGenome *mom, *dad; // tmp holders for selected genomes GAPopulation *tmppop; // Swap the old population with the new pop. tmppop = oldPop; // When we finish the ++ we want the newly oldPop = pop; // generated population to be current (for pop = tmppop; // references to it from member functions). // Generate the individuals in the temporary population from individuals in // the main population. for(i=0; i<pop->size()-1; i+=2){ // takes care of odd population mom = &(oldPop->select()); dad = &(oldPop->select()); stats.numsel += 2; // keep track of number of selections c1 = c2 = 0; if(GAFlipCoin(pCrossover())){ stats.numcro += (*scross)(*mom, *dad, &pop->individual(i), &pop->individual(i+1)); c1 = c2 = 1; } else{ pop->individual( i ).copy(*mom); pop->individual(i+1).copy(*dad); } stats.nummut += (mut = pop->individual( i ).mutate(pMutation())); if(mut > 0) c1 = 1; stats.nummut += (mut = pop->individual(i+1).mutate(pMutation())); if(mut > 0) c2 = 1; stats.numeval += c1 + c2; } if(pop->size() % 2 != 0){ // do the remaining population member mom = &(oldPop->select()); dad = &(oldPop->select()); stats.numsel += 2; // keep track of number of selections c1 = 0; if(GAFlipCoin(pCrossover())){ stats.numcro += (*scross)(*mom, *dad, &pop->individual(i), (GAGenome*)0); c1 = 1; } else{ if(GARandomBit()) pop->individual( i ).copy(*mom); else pop->individual( i ).copy(*dad); } stats.nummut += (mut = pop->individual( i ).mutate(pMutation())); if(mut > 0) c1 = 1; stats.numeval += c1; } // Pass mpi_tasks and mpi_rank to the population clas pop->mpi_tasks(vmpi_tasks); pop->mpi_rank(vmpi_rank); stats.numrep += pop->size(); pop->evaluate(gaTrue); // get info about current pop for next time // If we are supposed to be elitist, carry the best individual from the old // population into the current population. Be sure to check whether we are // supposed to minimize or maximize. if(minimaxi() == GAGeneticAlgorithm::MAXIMIZE) { if(el && oldPop->best().score() > pop->best().score()) oldPop->replace(pop->replace(&(oldPop->best()), GAPopulation::WORST), GAPopulation::BEST); } else { if(el && oldPop->best().score() < pop->best().score()) oldPop->replace(pop->replace(&(oldPop->best()), GAPopulation::WORST), GAPopulation::BEST); } stats.update(*pop); // update the statistics by one generation }