/* ---------------------------------------------------------------------------- ex13.C mbwall 29apr95 Copyright (c) 1995-1996 Massachusetts Institute of Technology DESCRIPTION: This example illustrates the use of a GA-within-a-GA. It uses a steady state GA to find the smiley face, then it uses another steady state GA to match a sequence of random numbers. It doesn't try to do the random numbers until it has gotten 90% of the way to the smiley face. This is very similar in function to the composite genome example, but here we evolve the two genomes separately rather than as a single entity. This kind of application can be useful for situations where the computational cost of calculating feasibility is rather high and the feasible space is sparse. ---------------------------------------------------------------------------- */ #include #include #include #include #include #include typedef struct _UserData { int width, height; short **picture_target; float *numbers_target; GA2DBinaryStringGenome *picture_genome; GABin2DecGenome *numbers_genome; } UserData; float PictureObjective(GAGenome &); float NumbersObjective(GAGenome &); int main(int argc, char *argv[]) { cout << "Example 13\n\n"; cout << "This program runs a GA-within-GA. The outer level GA tries to\n"; cout << "match the pattern read in from a file. The inner level GA is\n"; cout << "run only when the outer GA reaches a threshhold objective score\n"; cout << "then it tries to match a sequence of numbers that were generated\n"; cout << "randomly at the beginning of the program's execution.\n\n"; cout << "You might have to run the primary GA for more than 5000\n"; cout << "generations to get a score high enough to kick in the secondary\n"; cout << "genetic algorithm. Use the ngen option to do this on the\n"; cout << "command line.\n\n"; // See if we've been given a seed to use (for testing purposes). When you // specify a random seed, the evolution will be exactly the same each time // you use that seed number. unsigned int seed = 0; for(int ii=1; ii> data.height >> data.width; data.picture_target = new short*[data.width]; for(i=0; i> data.picture_target[i][j]; inStream.close(); // Print out the pattern to be sure we got the right one. cout << "input pattern:\n"; for(j=0; jpicture_target[i][j]); float correct = value / ((float)genome.width() * (float)genome.height()); // if we get at least 95% of the pixels right, then run the secondary ga. if(correct > 0.95) { GABin2DecGenome& num_genome = (GABin2DecGenome&)(*data->numbers_genome); GAIncrementalGA ga(num_genome); ga.populationSize(550); ga.nGenerations(50); ga.pMutation(0.01); ga.pCrossover(0.9); ga.evolve(); *data->numbers_genome = ga.statistics().bestIndividual(); correct += data->numbers_genome->score(); } return correct; } // This is the objective function for matching the sequence of numbers. float NumbersObjective(GAGenome & c) { GABin2DecGenome & genome = (GABin2DecGenome &)c; UserData * data = (UserData *)c.userData(); float value=genome.nPhenotypes(); for(int i=0; inumbers_target[i])); value /= genome.nPhenotypes(); return value; }