diff --git a/eo/tutorial/html/SecondRealEA.html b/eo/tutorial/html/SecondRealEA.html new file mode 100644 index 00000000..551faec9 --- /dev/null +++ b/eo/tutorial/html/SecondRealEA.html @@ -0,0 +1,468 @@ + + + + + + SecondRealEA + + +Back to Lesson 3 - Tutorial +main page - Top-Down page - Bottom-up +page - Programming hints - EO +documentation +
+
+
+

+SecondRealEA

+Click on the figure to see the corresponding code.
+In the code, the colors are meaningfull
+The actual code is in boldface and the comment in normal face. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
  + + + + + +
+//-----------------------------------------------------------------------------
+// SecondRealEA.cpp
+//-----------------------------------------------------------------------------
+//*
+// Same code than FirstBitEA as far as Evolutionary Computation is concerned
+// but now you learn to enter the parameters in a more flexible way
+// (also slightly different than in SecondBitEA.cpp)
+// and to twidle the output to your preferences (as in SecondBitEA.cpp)
+//
+//-----------------------------------------------------------------------------
+// standard includes
+#include <stdexcept>  // runtime_error
+#include <iostream>    // cout
+#include <strstream>  // ostrstream, istrstream
+// the general include for eo
+#include <eo>
+#include <es.h>
+
+
+ + + + +
+ +//-----------------------------------------------------------------------------
+// define your individuals
+typedef eoReal<eoMinimizingFitness> Indi;
+
+
+ + + + +
+ +//-----------------------------------------------------------------------------
+// a simple fitness function that computes the euclidian norm of a real vector
+// Now in a separate file, and declared as binary_value(const vector<bool> &)
+#include "real_value.h"
+
+
+ + + + +
+ +//-----------------------------------------------------------------------------
+void main_function(int argc, char **argv)
+{
+
+
+ + + + +
+ +//-----------------------------------------------------------------------------
+// instead of having all values of useful parameters as constants, read them:
+// either on the command line (--option=value or -o=value)
+//        or in a parameter file (same syntax, order independent,
+//                                                        # = usual comment character
+//        or in the environment (TODO)
+  // First define a parser from the command-line arguments
+  eoParser parser(argc, argv);
+  
+  // For each parameter, you can in on single line
+  // define the parameter, read it through the parser, and assign it
+  
+ +  unsigned seed = parser.createParam(unsigned(time(0)), "seed", "Random number seed", 'S').value(); // will be in default section General
+  
+  // description of genotype
+  unsigned vecSize = parser.createParam(unsigned(8), "vecSize", "Genotype size",'V', "Representation" ).value();
+    // parameters for evolution engine
+      unsigned popSize = parser.createParam(unsigned(10), "popSize", "Population size",'P', "Evolution engine" ).value();
+      unsigned tSize = parser.createParam(unsigned(2), "tSize", "Tournament size",'T', "Evolution Engine" ).value();
+    // init and stop
+      string loadName = parser.createParam(string(""), "Load","A save file to restart from",'L', "Persistence" ).value();
+
+      unsigned maxGen = parser.createParam(unsigned(100), "maxGen", "Maximum number of generations",'G', "Stopping criterion" ).value();
+      unsigned minGen = parser.createParam(unsigned(100), "minGen", "Minimum number of generations",'g', "Stopping criterion" ).value();
+      unsigned steadyGen = parser.createParam(unsigned(100), "steadyGen", "Number of generations with no improvement",'s', "Stopping criterion" ).value();
+    // operators probabilities at the algorithm level
+      double pCross = parser.createParam(double(0.6), "pCross", "Probability of Crossover", 'C', "Genetic Operators" ).value();
+      double pMut = parser.createParam(double(0.1), "pMut", "Probability of Mutation", 'M', "Genetic Operators" ).value();
+    // relative rates for crossovers
+      double hypercubeRate = parser.createParam(double(1), "hypercubeRate", "Relative rate for hypercube crossover", '\0', "Genetic Operators" ).value();
+      double segmentRate = parser.createParam(double(1), "segmentRate", "Relative rate for segment crossover", '\0', "Genetic Operators" ).value();
+      // internal parameters for the mutations
+      double EPSILON = parser.createParam(double(0.01), "EPSILON", "Width for uniform mutation", '\0', "Genetic Operators" ).value();
+      
+      double SIGMA = parser.createParam(double(0.3), "SIGMA", "Sigma for normal mutation", '\0', "Genetic Operators" ).value();
+    // relative rates for mutations
+      double uniformMutRate = parser.createParam(double(1), "uniformMutRate", "Relative rate for uniform mutation", '\0', "Genetic Operators" ).value();
+      double detMutRate = parser.createParam(double(1), "detMutRate", "Relative rate for det-uniform mutation", '\0', "Genetic Operators" ).value();
+      double normalMutRate = parser.createParam(double(1), "normalMutRate", "Relative rate for normal mutation", '\0', "Genetic Operators" ).value();
+      // the name of the "status" file where all actual parameter values will be saved
+      string str_status = parser.ProgramName() + ".status"; // default value
+      string statusName = parser.createParam(str_status, "status","Status file",'S', "Persistence" ).value();
+    // do the following AFTER ALL PARAMETERS HAVE BEEN PROCESSED
+    // i.e. in case you need parameters somewhere else, postpone these
+      if (parser.userNeedsHelp())
+          {
+              parser.printHelp(cout);
+              exit(1);
+          }
+      if (statusName != "")
+          {
+ofstream os(statusName.c_str());
+os << parser; // and you can use that file as parameter file
+          }
+
+
+ + + + +
+ +  /////////////////////////////
+  // Fitness function
+  ////////////////////////////
+  // Evaluation: from a plain C++ fn to an EvalFunc Object
+  // you need to give the full description of the function
+  eoEvalFuncPtr<Indi, double, const vector<double>& > plainEval(  real_value );
+  // ... to an object that counts the nb of actual evaluations
+  eoEvalFuncCounter<Indi> eval(plainEval);
+
+
+ + + + +
+ +  ////////////////////////////////
+  // Initilisation of population
+  ////////////////////////////////
+  // Either load or initialize
+  // create an empty pop
+  eoPop<Indi> pop;
+  // create a state for reading
+  eoState inState; // a state for loading - WITHOUT the parser
+  // register the rng and the pop in the state, so they can be loaded,
+  // and the present run will be the exact conitnuation of the saved run
+  // eventually with different parameters
+  inState.registerObject(rng);
+  inState.registerObject(pop);
+      
+  if (loadName != "")
+      {
+          inState.load(loadName); //  load the pop and the rng
+          // the fitness is read in the file:
+          // do only evaluate the pop if the fitness has changed
+      }
+  else
+      {
+          rng.reseed(seed);
+          // a Indi random initializer
+          // based on boolean_generator class (see utils/rnd_generator.h)
+          eoUniformGenerator<double> uGen(-1.0, 1.0);
+          eoInitFixedLength<Indi> random(vecSize, uGen);
+          // Init pop from the randomizer: need to use the append function
+          pop.append(popSize, random);          
+          // and evaluate pop (STL syntax)      
+          apply<Indi>(eval, pop);
+      } // end of initializatio of the population
+
+
+ + + + +
+ +  // sort pop before printing it!
+  pop.sort();
+  // Print (sorted) intial population (raw printout)
+  cout << "Initial Population" << endl;
+  cout << pop;
+
+
+ + + + +
+ +  /////////////////////////////////////
+  // selection and replacement
+  ////////////////////////////////////
+
+
+ + + + +
+ +  // The robust tournament selection
+  eoDetTournamentSelect<Indi> selectOne(tSize);
+  // is now encapsulated in a eoSelectPerc (entage)
+  eoSelectPerc<Indi> select(selectOne);// by default rate==1
+
+
+ + + + +
+ +  // And we now have the full slection/replacement - though with
+  // no replacement (== generational replacement) at the moment :-)
+  eoGenerationalReplacement<Indi> replace;
+
+
+ + + + +
+ +  //////////////////////////////////////
+  // The variation operators
+  //////////////////////////////////////
+
+
+ + + + +
+ +  // uniform chooce on segment made by the parents
+  eoSegmentCrossover<Indi> xoverS;
+  // uniform choice in hypercube built by the parents
+  eoHypercubeCrossover<Indi> xoverA;
+  // Combine them with relative weights
+  eoPropCombinedQuadOp<Indi> xover(xoverS, segmentRate);
+  xover.add(xoverA, hypercubeRate, true);
+
+
+ + + + +
+ +  // offspring(i) uniformly chosen in [parent(i)-epsilon, parent(i)+epsilon]
+  eoUniformMutation<Indi>  mutationU(EPSILON);
+  // k (=1) coordinates of parents are uniformly modified
+  eoDetUniformMutation<Indi>  mutationD(EPSILON);
+  // all coordinates of parents are normally modified (stDev SIGMA)
+  eoNormalMutation<Indi>  mutationN(SIGMA);
+  // Combine them with relative weights
+  eoPropCombinedMonOp<Indi> mutation(mutationU, uniformMutRate);
+  mutation.add(mutationD, detMutRate);
+  mutation.add(mutationN, normalMutRate, true);
+  // The operators are  encapsulated into an eoTRansform object
+  eoSGATransform<Indi> transform(xover, pCross, mutation, pMut);
+
+
+ + + + +
+ +  //////////////////////////////////////
+  // termination condition see FirstBitEA.cpp
+  /////////////////////////////////////
+  eoGenContinue<Indi> genCont(maxGen);
+  eoSteadyFitContinue<Indi> steadyCont(minGen, steadyGen);
+  eoFitContinue<Indi> fitCont(0);
+  eoCombinedContinue<Indi> continuator(genCont);
+  continuator.add(steadyCont);
+  continuator.add(fitCont);
+  
+  
+
+
+ + + + +
+ +  // but now you want to make many different things every generation
+  // (e.g. statistics, plots, ...).
+  // the class eoCheckPoint is dedicated to just that:
+  // Declare a checkpoint (from a continuator: an eoCheckPoint
+  // IS AN eoContinue and will be called in the loop of all algorithms)
+  eoCheckPoint<Indi> checkpoint(continuator);
+  
+      // Create a counter parameter
+      eoValueParam<unsigned> generationCounter(0, "Gen.");
+      
+      // Create an incrementor (sub-class of eoUpdater). Note that the
+      // parameter's value is passed by reference,
+      // so every time the incrementer is updated (every generation),
+      // the data in generationCounter will change.
+      eoIncrementor<unsigned> increment(generationCounter.value());
+      // Add it to the checkpoint,
+      // so the counter is updated (here, incremented) every generation
+      checkpoint.add(increment);
+      // now some statistics on the population:
+      // Best fitness in population
+      eoBestFitnessStat<Indi> bestStat;
+      // Second moment stats: average and stdev
+      eoSecondMomentStats<Indi> SecondStat;
+      // Add them to the checkpoint to get them called at the appropriate time
+      checkpoint.add(bestStat);
+      checkpoint.add(SecondStat);
+      // The Stdout monitor will print parameters to the screen ...
+      eoStdoutMonitor monitor(false);
+        
+      // when called by the checkpoint (i.e. at every generation)
+      checkpoint.add(monitor);
+      // the monitor will output a series of parameters: add them
+      monitor.add(generationCounter);
+      monitor.add(eval); // because now eval is an eoEvalFuncCounter!
+      monitor.add(bestStat);
+      monitor.add(SecondStat);
+      // A file monitor: will print parameters to ... a File, yes, you got it!
+      eoFileMonitor fileMonitor("stats.xg", " ");
+        
+      // the checkpoint mechanism can handle multiple monitors
+      checkpoint.add(fileMonitor);
+      // the fileMonitor can monitor parameters, too, but you must tell it!
+      fileMonitor.add(generationCounter);
+      fileMonitor.add(bestStat);
+      fileMonitor.add(SecondStat);
+      // Last type of item the eoCheckpoint can handle: state savers:
+      eoState outState;
+      // Register the algorithm into the state (so it has something to save!!)
+      outState.registerObject(parser);
+      outState.registerObject(pop);
+      outState.registerObject(rng);
+      // and feed the state to state savers
+      // save state every 100th  generation
+      eoCountedStateSaver stateSaver1(20, outState, "generation");
+      // save state every 1 seconds
+      eoTimedStateSaver    stateSaver2(1, outState, "time");
+      // Don't forget to add the two savers to the checkpoint
+      checkpoint.add(stateSaver1);
+      checkpoint.add(stateSaver2);
+      // and that's it for the (control and) output
+
+
+ + + + +
+ +  /////////////////////////////////////////
+  // the algorithm
+  ////////////////////////////////////////
+  // Easy EA requires
+  // stopping criterion, eval, selection, transformation, replacement
+  eoEasyEA<Indi> gga(checkpoint, eval, select, transform, replace);
+  // Apply algo to pop - that's it!
+  gga(pop);
+  
+
+
+ + + + +
+ +  // Print (sorted) intial population
+  pop.sort();
+  cout << "FINAL Population\n" << pop << endl;
+
+
+ + + + +
+ +}
+// A main that catches the exceptions
+int main(int argc, char **argv)
+{
+      try
+      {
+              main_function(argc, argv);
+      }
+      catch(exception& e)
+      {
+              cout << "Exception: " << e.what() << '\n';
+      }
+      return 1;
+}
+
+
Back to Lesson 3 - Tutorial +main page - Top-Down page - Bottom-up +page - Programming hints - EO +documentation +
+
+Marc Schoenauer
+
Last +modified: Sun Apr 28 06:42:44 2002 + + + diff --git a/eo/tutorial/html/eoLesson3.html b/eo/tutorial/html/eoLesson3.html index 8563769e..40c36e11 100644 --- a/eo/tutorial/html/eoLesson3.html +++ b/eo/tutorial/html/eoLesson3.html @@ -42,13 +42,13 @@ First, but you should now have done it without being told, go into the sub-dir of the tutorial dir and type make. This will compile the SecondBitEA -program (and, some day, SecondRealEA). +and SecondRealEA +programs.

You can then either


eoParser: @@ -171,7 +172,7 @@ and optionally by a short (1 character) keyword. -
              +
             --longKeyword=value     or     -cvalue    @@ -183,12 +184,12 @@ so, after compiling the executable for Lesson 3 (ma lesson3 at system prompt in Unix), you can try to type in -
               +
              SecondBitEA
and see the algorithm run as before (OneMax optimized on 8-bits bitstrings). But you can now type in -
               +
              SecondBitEA --vecSize=100
and see the output of the optimization of OneMax on 100-bit bitstrings. @@ -196,7 +197,7 @@ But you can now type in
  • Take a look at all available parameters by typing in
  • -
                   +
                  SecondBitEA --help
    or by going into the code: all parameter inputs have been grouped in @@ -209,7 +210,7 @@ it contains the list of all actual parameters used, and can directly be used as parameter input file: change the file name (e.g. to SecondBitEA.param), edit it, change whichever parameter you want, and type in -
                     +
                    SecondBitEA @SecondBitEA.param
    and you will see all values that you defined into the file taken into account. @@ -249,7 +250,17 @@ somewhere else later (though of course this is not any useful for variable seed!). There is however another way to achieve the same result in less lines of -code - with a different memory management (see Lesson4). +code - with a different memory management. This is what is done in the +code for eoRealEA. The same parameter for the random +number generator seed +is read, but in one single line of code.  +The only difference is that now you cannot access the eoValueParam object +itself - but this is not often necessary. +
    Be careful to ensure that the type of the default value in the call +to eoParameterLoader::createParam +method as this is the only way the compiler can desambiguate the template +(remember that eoParameterLoader is a +base class for eoParser.


    eoState: