void freePopulation(sPopulation * pop) { int i; for (i = 0; i < pop->iNumGenomes; i++) { freeGenome(pop->vGenomes[i]); } free(pop->vGenomes); free(pop->vDepths); freeInnovTable(pop->sInnovTable); freeSpecies(pop); free(pop); }
int test(int argc, char *argv[]) { int start, stop; if (argc != 9 && argc != 10) usageErr(); inName = argv[0]; cdnaName = argv[1]; chromDir = argv[2]; goodLogName = argv[3]; badLogName = argv[4]; unusualName = argv[5]; errName = argv[6]; start = atoi(argv[7]); stop = atoi(argv[8]); if (start >= stop) usageErr(); if (argc == 10) c2gName = argv[9]; inFile = mustOpen(inName, "r"); goodLogFile = mustOpen(goodLogName, "w"); badLogFile = mustOpen(badLogName, "w"); unusualFile = mustOpen(unusualName, "w"); errFile = mustOpen(errName, "w"); pushWarnHandler(reportWarning); dnaUtilOpen(); printf("Loading chromosomes\n"); loadGenome(chromDir, &chroms, &chromNames, &chromCount); startRedoHash(); printf("Analysing %s\n", inName); if (weAreWeb()) htmlHorizontalLine(); analyse(start, stop); //endRedoHash(); freeGenome(&chroms, &chromNames, chromCount); popWarnHandler(); fclose(inFile); fclose(goodLogFile); fclose(badLogFile); fclose(unusualFile); fclose(errFile); return 0; }
/* This function performs one epoch of the genetic algorithm and returns * a vector of pointers to the new phenotypes */ void epoch(sPopulation * pop) { int spec, gen; // reset appropriate values and kill off the existing phenotypes and // any poorly performing species resetAndKill(pop); // sort genomes sortGenomes(pop); // separate the population into species of similar topology, adjust // fitnesses and calculate spawn levels speciateAndCalculateSpawnLevels(pop); if (Verbose) dumpSpecies(stdout, pop); if (GlobalLog) dumpSpecies(GlobalLogFile, pop); // this will hold the new population of genomes sGenome ** newGenomes = calloc( pop->sParams->iNumIndividuals, sizeof(*newGenomes) ); // request the offspring from each species. The number of children to // spawn is a double which we need to convert to an int. int numSpawnedSoFar = 0; sGenome * baby; // now to iterate through each species selecting offspring to be mated and // mutated for (spec = 0; spec < pop->iNumSpecies; spec++) { // because of the number to spawn from each species is a double // rounded up or down to an integer it is possible to get an overflow // of genomes spawned. This statement just makes sure that doesn't happen if (numSpawnedSoFar < pop->sParams->iNumIndividuals) { //this is the amount of offspring this species is required to // spawn. Round simply rounds the double up or down. int numToSpawn = round(pop->vSpecies[spec]->dSpawnsRqd); bool bChosenBestYet = E_FALSE; while (numToSpawn--) { // first grab the best performing genome from this species and transfer // to the new population without mutation. This provides per species // elitism // => Stanley recommends to do this only if the species has more than // five networks, in Neat1.1 he used the futur number of individual // instead of the current one... if (!bChosenBestYet) { // && numToSpawn > 5 baby = copyGenome(pop->vSpecies[spec]->sLeader); bChosenBestYet = E_TRUE; } else { // if the number of individuals in this species is only one // then we can only perform mutation if (pop->vSpecies[spec]->iNumMembers == 1) { // spawn a child baby = copyGenome(randomAmongBest( pop->vSpecies[spec], pop->sParams->dSurvivalRate )); } //if greater than one we can use the crossover operator else { // spawn1 sGenome * g1 = randomAmongBest( pop->vSpecies[spec], pop->sParams->dSurvivalRate ); if (randFloat() < pop->sParams->dCrossoverRate) { // spawn2, make sure it's not the same as g1 sGenome * g2 = randomAmongBest( pop->vSpecies[spec], pop->sParams->dSurvivalRate ); // number of attempts at finding a different genome int numAttempts = pop->sParams->iNumTrysToFindMate; while (g1->iId == g2->iId && numAttempts--) g2 = randomAmongBest( pop->vSpecies[spec], pop->sParams->dSurvivalRate); if (g1->iId != g2->iId) baby = crossover(g1, g2); else baby = copyGenome(g1); // crossover fail } else { baby = copyGenome(g1); // no crossover } } // adjust new genome id baby->iId = pop->iNextGenomeId++; // now we have a spawned child lets mutate it! First there is the // chance a neuron may be added if (randFloat() < pop->sParams->dChanceAddNode) addNeuron(baby, pop); // now there's the chance a link may be added else if (randFloat() < pop->sParams->dChanceAddLink) addLink(baby, pop); else { // mutate the weights mutateWeigth(baby, pop->sParams); // mutate the activation response mutateActivationResponse(baby, pop->sParams); // enable or disable a random gene if (randFloat() < 0.1) // mutate_toggle_enable_prob = 0.1 mutateToggleEnable(baby); // find first disabled gene and enable it if (randFloat() < 0.05) // mutate_gene_reenable_prob = 0.05 mutateReenableFirst(baby); } } // end choice of a baby //sort the babies genes by their innovation numbers qsort(baby->vLinks, baby->iNumLinks, sizeof(sLinkGene *), (int (*) (const void *, const void *)) cmpLinksByInnovIds); //add to new pop newGenomes[numSpawnedSoFar++] = baby; if (numSpawnedSoFar == pop->sParams->iNumIndividuals) goto newGenerationReady; } // end while not enougth babies } // end if to much babies } // next species // if there is an underflow due to the rounding error and the amount // of offspring falls short of the population size additional children // need to be created and added to the new population. This is achieved // simply, by using tournament selection over the entire population. if (numSpawnedSoFar < pop->sParams->iNumIndividuals) { //calculate amount of additional children required int rqd = pop->sParams->iNumIndividuals - numSpawnedSoFar; //grab them while (rqd--) { sGenome * chosenOne = tournamentSelection(pop, pop->iNumGenomes / 5); newGenomes[numSpawnedSoFar++] = copyGenome(chosenOne); } } newGenerationReady: // free the old vector of genomes for (gen = 0; gen < pop->iNumGenomes; gen++) freeGenome(pop->vGenomes[gen]); // free the genome itself free(pop->vGenomes); // free the vector containing the genomes //replace the current population with the new one pop->vGenomes = newGenomes; //create the new phenotypes for (gen = 0; gen < pop->iNumGenomes; gen++) { if (UltraVerbose) dumpGenome(stdout, pop->vGenomes[gen]); //calculate max network depth //int depth = calculateNetDepth(pop->vGenomes[gen]); createPhenotype(pop->vGenomes[gen], pop->iNumDepth + pop->vGenomes[gen]->iNumRecur); if (UltraVerbose) dumpPhenotype(pop->vGenomes[gen]->pPhenotype, pop->vGenomes[gen]->iId); } //increase generation counter pop->iGeneration++; }