/*************************************************************************** This is part of the evolver toolkit for exploring genetic progamming. Copyright (C) 1996 Benjamin Bennett and Yeasah G. Pell This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Contact information: Benjamin Bennett and Yeasah G. Pell *************************************************************************/ /********************************************************************** Main program for the Genetic Algorithm generator. This code sets up the program state and runs the evaluation and breeding routines until some condition is satisfied. ********************************************************************/ #ifdef WIN32 #include // getpid() #include "getopt/getopt.h" #else #include // getpid() #endif #include // srandom() #ifdef DEBUG_MEMORY int global_cnt = 0; #endif int num_arrays = 0; // make the models depending on which model we are using #if defined INT_MODEL #include "test_model.H" #elif defined NET_MODEL #include "network_model1.H" #endif // NET_MODEL #include "generation.H" #include "progfit.H" #define NUM_PROGS 16 #define NUM_RUNS 16 #define MAX_DEPTH 6 #define MIN_DEPTH 2 #define INITIAL_FACTOR 8 #define EXECUTIONS 100 void print_ranking(GGeneration &gen, int num_runs, int num_progs) { GArray ranks; int i; int num, num2; double average; // print top 10 programs and the bottom 5 cout << endl << "Generation " << gen.GetGeneration() << " of " << num_runs << " program rankings" << endl; gen.Rank(ranks); num = ranks.GetSize(); if (num > 15) { num = 10; num2 = 5; } else num2 = 0; // leave num unchanged if (num > 0) { cout << "Best " << num << " of " << ranks.GetSize() << ":" << endl; cout << "Fitness\t Hits\t Prog ID\t Length" << endl; for(i=0; i < num; i++) cout << ranks[i]->fitness << "\t " << ranks[i]->hits << "\t " << ranks[i]->prog_off << "\t\t " << gen.GetProgram(ranks[i]->prog_off)->GetRoot()->GetLength() << endl; } if (num2 > 0) { cout << "Worst 5:" << endl; for(i=num_progs-5; i < num_progs; i++) cout << ranks[i]->fitness << "\t " << ranks[i]->hits << "\t " << ranks[i]->prog_off << "\t\t " << gen.GetProgram(ranks[i]->prog_off)->GetRoot()->GetLength() << endl; } if (num > 0) { cout << "The best program (fitness " << ranks[0]->fitness << ", length " << gen.GetProgram(ranks[0]->prog_off)->GetRoot()->GetLength() << "): " << endl; // gen.GetProgram(ranks[0]->prog_off)->GetRoot()->Print(); average = 0.0; for (i = 0; i < ranks.GetSize(); i++) average += ranks[i]->fitness; average = average / ranks.GetSize(); cout << "Average fitness: " << average << endl; } } int main(int argc, char *argv[]) { int num_progs = NUM_PROGS; int num_runs = NUM_RUNS; int max_depth = MAX_DEPTH; int min_depth = MIN_DEPTH; int initial_factor = INITIAL_FACTOR; int model = -1; int executions = EXECUTIONS; int arg; GGeneration *gen; int seed; gen = new GGeneration; // parse the command line (taken liberally from getopt(3)) while(1) { arg = getopt(argc, argv, "m:p:r:u:l:f:x:h"); if (arg == -1) break; switch (arg) { case 'm': // set the network model = atoi(optarg); break; case 'p': // set the number of programs num_progs = atoi(optarg); break; case 'r': // set the number of runs num_runs = atoi(optarg); break; case 'u': // set the two depths max_depth = atoi(optarg); break; case 'l': min_depth = atoi(optarg); break; case 'f': // set the initial factor initial_factor = atoi(optarg); break; case 'x': // set the number of executions executions = atoi(optarg); break; case 'h': // print usage cout << "Usage:" << endl; cout << argv[0] << " -m model [-p num_progs] [-r num_runs] " << "[-u max_depth] [-l min_depth] [-f initial_factor] " << "[-x max_executions] " << endl; exit(0); // and quit break; default: // print error cout << "Invalid argument " << arg << endl; exit(1); } } if (model == -1) { cout << "Model must be set" << endl; exit(1); } // check that the program sizes are not invalid if (max_depth <= min_depth) { cout << "Max initial program size must be more than the min" << endl; exit(1); } // initialize the random number generator seed = (int)getpid(); #if defined DEBUG_EVALUATE || defined DEBUG_MEMORY seed = 207; #endif // DEBUG_EVALUATE || DEBUG_MEMORY srand(seed); // Print banner info cout << "Genetic running with:" << endl; cout << "\tnetwork:\t" << model << endl; cout << "\tnum_progs:\t" << num_progs << endl; cout << "\tnum_runs:\t" << num_runs << endl; cout << "\tmax_depth:\t" << max_depth << endl; cout << "\tmin_depth:\t" << min_depth << endl; cout << "\tinitial_factor:\t" << initial_factor << endl; cout << "\texecutions:\t" << executions << endl; cout << "\tseeded with:\t" << seed << endl << endl; // add the test model to the generation cout << "Setting Model" << endl << endl; // make the models depending on which model we are using #if defined INT_MODEL gen->AddModel(new GTestModel(4)); gen->AddModel(new GTestModel(5)); #elif defined NET_MODEL gen->AddModel(new GDistNetModel(model, executions)); #endif // NET_MODEL // make some test programs cout << "Generating Programs" << endl << endl; // seed the initial generation, the last numbers control the depth gen->GenerateNewGeneration(num_progs*initial_factor, min_depth, max_depth, -1); // print_progs(test_gen); // print the rankings of the first programs print_ranking(*gen, num_runs, num_progs*initial_factor); while (gen->GetGeneration() < num_runs) // end condition not satisfied { cout << endl; // breed next batch, the last three numbers control the // frequency of crossover, mutation and selection respectively // a negative selection indicates it will always select the best gen->BreedNewGeneration(num_progs, 9, 1, -1); // print_progs(gen); // print the rankings of the new programs print_ranking(*gen, num_runs, num_progs); // TODO: print ranking statisitics } cout << endl; // print best program GArray ranks; gen->Rank(ranks); gen->GetProgram(ranks[0]->prog_off)->GetRoot()->Print(); cout << endl; // delete generation (all memory should be freed now) delete gen; #ifdef DEBUG_MEMORY cout << "Number of leaky frees: " << global_cnt << endl; cout << "Number of leaky arrays: " << num_arrays << endl; #endif return 0; }