MyStructSEA.cpp

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 <do/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 <do/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 <do/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 <do/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 <do/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 }

Generated on Thu Apr 19 11:02:29 2007 for EO by  doxygen 1.4.7