00001 00006 /* 00007 Template for creating a new representation in EO 00008 ================================================ 00009 00010 This is the template main file. 00011 It includes all other files that have been generated by the script create.sh 00012 so it is the only file to compile. 00013 00014 In case you want to build up a separate library for your new Evolving Object, 00015 you'll need some work - follow what's done in the src/ga dir, used in the 00016 main file BitEA in tutorial/Lesson4 dir. 00017 Or you can wait until we do it :-) 00018 */ 00019 00020 // Miscilaneous include and declaration 00021 #include <iostream> 00022 using namespace std; 00023 00024 // eo general include 00025 #include "eo" 00026 // the real bounds (not yet in general eo include) 00027 #include "utils/eoRealVectorBounds.h" 00028 00029 // include here whatever specific files for your representation 00030 // Basically, this should include at least the following 00031 00035 #include "eoMyStruct.h" 00036 00040 #include "eoMyStructInit.h" 00041 00047 #include "eoMyStructEvalFunc.h" 00048 00053 #include "eoMyStructQuadCrossover.h" 00054 #include "eoMyStructMutation.h" 00055 00056 /* and (possibly) your personal statistics */ 00057 #include "eoMyStructStat.h" 00058 00059 // GENOTYPE eoMyStruct ***MUST*** be templatized over the fitness 00060 00061 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00062 // START fitness type: double or eoMaximizingFitness if you are maximizing 00063 // eoMinimizingFitness if you are minimizing 00064 typedef eoMinimizingFitness MyFitT ; // type of fitness 00065 // END fitness type 00066 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00067 00068 // Then define your EO objects using that fitness type 00069 typedef eoMyStruct<MyFitT> Indi; // ***MUST*** derive from EO 00070 00071 00072 // Use existing modules to define representation independent routines 00073 00074 // how to initialize the population 00075 // it IS representation independent if an eoInit is given 00076 #include <make_pop.h> 00077 eoPop<Indi >& make_pop(eoParser& _parser, eoState& _state, eoInit<Indi> & _init) 00078 { 00079 return do_make_pop(_parser, _state, _init); 00080 } 00081 00082 // the stopping criterion 00083 #include <make_continue.h> 00084 eoContinue<Indi>& make_continue(eoParser& _parser, eoState& _state, eoEvalFuncCounter<Indi> & _eval) 00085 { 00086 return do_make_continue(_parser, _state, _eval); 00087 } 00088 00089 // outputs (stats, population dumps, ...) 00090 #include <make_checkpoint.h> 00091 eoCheckPoint<Indi>& make_checkpoint(eoParser& _parser, eoState& _state, eoEvalFuncCounter<Indi>& _eval, eoContinue<Indi>& _continue) 00092 { 00093 return do_make_checkpoint(_parser, _state, _eval, _continue); 00094 } 00095 00096 // evolution engine (selection and replacement) 00097 #include <make_algo_scalar.h> 00098 eoAlgo<Indi>& make_algo_scalar(eoParser& _parser, eoState& _state, eoEvalFunc<Indi>& _eval, eoContinue<Indi>& _continue, eoGenOp<Indi>& _op, eoDistance<Indi> *_dist = NULL) 00099 { 00100 return do_make_algo_scalar(_parser, _state, _eval, _continue, _op, _dist); 00101 } 00102 00103 // simple call to the algo. stays there for consistency reasons 00104 // no template for that one 00105 #include <make_run.h> 00106 // the instanciating fitnesses 00107 #include <eoScalarFitness.h> 00108 void run_ea(eoAlgo<Indi>& _ga, eoPop<Indi>& _pop) 00109 { 00110 do_run(_ga, _pop); 00111 } 00112 00113 // checks for help demand, and writes the status file 00114 // and make_help; in libutils 00115 void make_help(eoParser & _parser); 00116 00117 // now use all of the above, + representation dependent things 00118 int main(int argc, char* argv[]) 00119 { 00120 try 00121 { 00122 eoParser parser(argc, argv); // for user-parameter reading 00123 00124 eoState state; // keeps all things allocated 00125 00126 // The fitness 00128 eoMyStructEvalFunc<Indi> plainEval/* (varType _anyVariable) */; 00129 // turn that object into an evaluation counter 00130 eoEvalFuncCounter<Indi> eval(plainEval); 00131 00132 // a genotype initializer 00133 eoMyStructInit<Indi> init; 00134 // or, if you need some parameters, you might as well 00135 // - write a constructor of the eoMyStructInit that uses a parser 00136 // - call it from here: 00137 // eoMyStructInit<Indi> init(parser); 00138 00139 // if you want to do sharing, you'll need a distance. 00140 // see file utils/eoDistance.h 00141 // 00142 // IF you representation has an operator[]() double-castable, 00143 // then you can use for instance the quadratic distance (L2 norm) 00144 // eoQuadDistance<Indi> dist; 00145 // or the Hamming distance (L1 norm) 00146 // eoHammingDistance<Indi> dist; 00147 00148 00149 // Build the variation operator (any seq/prop construct) 00150 // here, a simple example with only 1 crossover (2->2, a QuadOp) and 00151 // one mutation, is given. 00152 // Hints to have choice among multiple crossovers and mutations are given 00153 00154 // A (first) crossover (possibly use the parser in its Ctor) 00155 eoMyStructQuadCrossover<Indi> cross /* (eoParser parser) */; 00156 00157 // IF MORE THAN ONE: 00158 00159 // read its relative rate in the combination 00160 // double cross1Rate = parser.createParam(1.0, "cross1Rate", "Relative rate for crossover 1", '1', "Variation Operators").value(); 00161 00162 // create the combined operator with the first one (rename it cross1 !!!) 00163 // eoPropCombinedQuadOp<Indi> cross(cross1, cross1Rate); 00164 00165 // and as many as you want the following way: 00166 // 1- write the new class by mimicking eoMyStructQuadCrossover.h 00167 // 2- include that file here together with eoMyStructQuadCrossover above 00168 // 3- uncomment and duplicate the following lines: 00169 // 00170 // eoMyStructSecondCrossover<Indi> cross2(eoParser parser); 00171 // double cross2Rate = parser.createParam(1.0, "cross2Rate", "Relative rate for crossover 2", '2', "Variation Operators").value(); 00172 // cross.add(cross2, cross2Rate); 00173 00174 // NOTE: if you want some gentle output, the last one shoudl be like 00175 // cross.add(cross, crossXXXRate, true); 00176 00178 00179 // a (first) mutation (possibly use the parser in its Ctor) 00180 eoMyStructMutation<Indi> mut /* (parser) */; 00181 00182 // IF MORE THAN ONE: 00183 00184 // read its relative rate in the combination 00185 // double mut1Rate = parser.createParam(1.0, "mut1Rate", "Relative rate for mutation 1", '1', "Variation Operators").value(); 00186 00187 // create the combined operator with the first one (rename it cross1 !!!) 00188 // eoPropCombinedMonOp<Indi> mut(mut1, mut1Rate); 00189 00190 // and as many as you want the following way: 00191 // 1- write the new class by mimicking eoMyStructMutation.h 00192 // 2- include that file here together with eoMyStructMutation above 00193 // 3- uncomment and duplicate the following lines: 00194 // 00195 // eoMyStructSecondMutation<Indi> mut2(eoParser parser); 00196 // double mut2Rate = parser.createParam(1.0, "mut2Rate", "Relative rate for mutation 2", '2', "Variation Operators").value(); 00197 // mut.add(mut2, mut2Rate); 00198 00199 // NOTE: if you want some gentle output, the last one shoudl be like 00200 // mut.add(mut, mutXXXRate, true); 00201 00202 // now encapsulate your crossover(s) and mutation(s) into an eoGeneralOp 00203 // so you can fully benefit of the existing evolution engines 00204 00205 // First read the individual level parameters 00206 double pCross = parser.createParam(0.6, "pCross", "Probability of Crossover", 'C', "Variation Operators" ).value(); 00207 // minimum check 00208 if ( (pCross < 0) || (pCross > 1) ) 00209 throw runtime_error("Invalid pCross"); 00210 00211 double pMut = parser.createParam(0.1, "pMut", "Probability of Mutation", 'M', "Variation Operators" ).value(); 00212 // minimum check 00213 if ( (pMut < 0) || (pMut > 1) ) 00214 throw runtime_error("Invalid pMut"); 00215 00216 // now create the generalOp 00217 eoSGAGenOp<Indi> op(cross, pCross, mut, pMut); 00218 00219 00221 // 00222 // You do not need to modify anything beyond this point 00223 // unless you want to add specific statistics to the checkpoint 00224 // in which case you should uncomment the corresponding block 00225 // and possibly modify the parameters in the stat object creation 00227 00228 // initialize the population 00229 // yes, this is representation indepedent once you have an eoInit 00230 eoPop<Indi>& pop = make_pop(parser, state, init); 00231 00232 // stopping criteria 00233 eoContinue<Indi> & term = make_continue(parser, state, eval); 00234 // output 00235 eoCheckPoint<Indi> & checkpoint = make_checkpoint(parser, state, eval, term); 00236 00237 00238 // UNCOMMENT the following commented block if you want to add you stats 00239 00240 // if uncommented, it is assumed that you will want to print some stat. 00241 // if not, then the following objects will be created uselessly - but what the heck! 00242 00243 eoMyStructStat<Indi> myStat; // or maybe myStat(parser); 00244 checkpoint.add(myStat); 00245 // This one is probably redundant with the one in make_checkpoint, but w.t.h. 00246 eoIncrementorParam<unsigned> generationCounter("Gen."); 00247 checkpoint.add(generationCounter); 00248 // need to get the name of the redDir param (if any) 00249 std::string dirName = parser.getORcreateParam(std::string("Res"), "resDir", "Directory to store DISK outputs", '\0', "Output - Disk").value() + "/"; 00250 00251 00252 // those need to be pointers because of the if's 00253 eoStdoutMonitor *myStdOutMonitor; 00254 eoFileMonitor *myFileMonitor; 00255 #ifdef HAVE_GNUPLOT 00256 eoGnuplot1DMonitor *myGnuMonitor; 00257 #endif 00258 00259 // now check how you want to output the stat: 00260 bool printMyStructStat = parser.createParam(false, "coutMyStructStat", "Prints my stat to screen, one line per generation", '\0', "My application").value(); 00261 bool fileMyStructStat = parser.createParam(false, "fileMyStructStat", "Saves my stat to file (in resDir", '\0', "My application").value(); 00262 bool plotMyStructStat = parser.createParam(false, "plotMyStructStat", "On-line plots my stat using gnuplot", '\0', "My application").value(); 00263 00264 // should we write it on StdOut ? 00265 if (printMyStructStat) 00266 { 00267 myStdOutMonitor = new eoStdoutMonitor(false); 00268 // don't forget to store the memory in the state 00269 state.storeFunctor(myStdOutMonitor); 00270 // and of course to add the monitor to the checkpoint 00271 checkpoint.add(*myStdOutMonitor); 00272 // and the different fields to the monitor 00273 myStdOutMonitor->add(generationCounter); 00274 myStdOutMonitor->add(eval); 00275 myStdOutMonitor->add(myStat); 00276 } 00277 00278 // first check the directory (and creates it if not exists already): 00279 if (fileMyStructStat || plotMyStructStat) 00280 if (! testDirRes(dirName, true) ) 00281 throw runtime_error("Problem with resDir"); 00282 00283 // should we write it to a file ? 00284 if (fileMyStructStat) 00285 { 00286 // the file name is hard-coded - of course you can read 00287 // a string parameter in the parser if you prefer 00288 myFileMonitor = new eoFileMonitor(dirName + "myStat.xg"); 00289 // don't forget to store the memory in the state 00290 state.storeFunctor(myFileMonitor); 00291 // and of course to add the monitor to the checkpoint 00292 checkpoint.add(*myFileMonitor); 00293 // and the different fields to the monitor 00294 myFileMonitor->add(generationCounter); 00295 myFileMonitor->add(eval); 00296 myFileMonitor->add(myStat); 00297 } 00298 00299 #ifdef HAVE_GNUPLOT 00300 // should we PLOT it on StdOut ? (one dot per generation, incremental plot) 00301 if (plotMyStructStat) 00302 { 00303 myGnuMonitor = new eoGnuplot1DMonitor(dirName+"plot_myStat.xg",minimizing_fitness<Indi>()); 00304 // NOTE: you cand send commands to gnuplot at any time with the method 00305 // myGnuMonitor->gnuplotCommand(string) 00306 // par exemple, gnuplotCommand("set logscale y") 00307 00308 // don't forget to store the memory in the state 00309 state.storeFunctor(myGnuMonitor); 00310 // and of course to add the monitor to the checkpoint 00311 checkpoint.add(*myGnuMonitor); 00312 // and the different fields to the monitor (X = eval, Y = myStat) 00313 myGnuMonitor->add(eval); 00314 myGnuMonitor->add(myStat); 00315 } 00316 #endif 00317 00318 // algorithm (need the operator!) 00319 eoAlgo<Indi>& ga = make_algo_scalar(parser, state, eval, checkpoint, op); 00320 // and the distance if you want to do sharing 00321 // eoAlgo<Indi>& ga = make_algo_scalar(parser, state, eval, checkpoint, op, &dist); 00322 00324 00326 // to be called AFTER all parameters have been read!!! 00327 make_help(parser); 00328 00331 // evaluate intial population AFTER help and status in case it takes time 00332 apply<Indi>(eval, pop); 00333 // if you want to print it out 00334 // cout << "Initial Population\n"; 00335 // pop.sortedPrintOn(cout); 00336 // cout << endl; 00337 00338 run_ea(ga, pop); // run the ga 00339 00340 cout << "Final Population\n"; 00341 pop.sortedPrintOn(cout); 00342 cout << endl; 00343 00344 } 00345 catch(exception& e) 00346 { 00347 cout << e.what() << endl; 00348 } 00349 return 0; 00350 }