# 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 }