# make_algo_easea.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // make_algo_easea.h
    00005 // (c) Marc Schoenauer and Pierre Collet, 2002
    00006 /*
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Lesser General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Lesser General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Lesser General Public
    00018     License along with this library; if not, write to the Free Software
    00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020
    00021     Contact: Pierre.Collet@polytechnique.fr
    00022              Marc.Schoenauer@polytechnique.fr
    00023              mkeijzer@dhi.dk
    00024  */
    00025 //-----------------------------------------------------------------------------
    00026
    00027 #ifndef _make_algo_easea_h
    00028 #define _make_algo_easea_h
    00029
    00030 #include <utils/eoData.h>     // for eo_is_a_rate
    00031 // everything tha's needed for the algorithms - SCALAR fitness
    00032
    00033 // Selection
    00034 // the eoSelectOne's
    00035 #include <eoRandomSelect.h>
    00036 #include <eoSequentialSelect.h>
    00037 #include <eoDetTournamentSelect.h>
    00038 #include <eoProportionalSelect.h>
    00039 #include <eoFitnessScalingSelect.h>
    00040 #include <eoRankingSelect.h>
    00041 #include <eoStochTournamentSelect.h>
    00042 // #include <eoSelect.h>    included in all others
    00043
    00044 // Breeders
    00045 #include <eoGeneralBreeder.h>
    00046
    00047 // Replacement
    00048 #include "make_general_replacement.h"
    00049 #include "eoMGGReplacement.h"
    00050 #include "eoG3Replacement.h"
    00051
    00052
    00053 // Algorithm (only this one needed)
    00054 #include <eoEasyEA.h>
    00055
    00056   // also need the parser and param includes
    00057 #include <utils/eoParser.h>
    00058 #include <utils/eoState.h>
    00059
    00060
    00061 /*
    00062  * This function builds the algorithm (i.e. selection and replacement)
    00063  *      from existing continue (or checkpoint) and operators
    00064  *
    00065  * It uses a parser (to get user parameters) and a state (to store the memory)
    00066  * the last argument is an individual, needed for 2 reasons
    00067  *     it disambiguates the call after instanciations
    00068  *     some operator might need some private information about the indis
    00069  *
    00070  * This is why the template is the complete EOT even though only the fitness
    00071  * is actually templatized here
    00072 */
    00073
    00074 template <class EOT>
    00075 eoAlgo<EOT> & do_make_algo_scalar(eoParser& _parser, eoState& _state, eoEvalFunc<EOT>& _eval, eoContinue<EOT>& _continue, eoGenOp<EOT>& _op)
    00076 {
    00077   // the selection
    00078   eoValueParam<eoParamParamType>& selectionParam = _parser.createParam(eoParamParamType("DetTour(2)"), "selection", "Selection: Roulette, Ranking(p,e), DetTour(T), StochTour(t), Sequential(ordered/unordered) or EliteSequentialSelect", 'S', "Evolution Engine");
    00079
    00080   eoParamParamType & ppSelect = selectionParam.value(); // std::pair<std::string,std::vector<std::string> >
    00081
    00082   eoSelectOne<EOT>* select ;
    00083   if (ppSelect.first == std::string("DetTour"))
    00084   {
    00085     unsigned detSize;
    00086
    00087     if (!ppSelect.second.size())   // no parameter added
    00088       {
    00089         std::cerr << "WARNING, no parameter passed to DetTour, using 2" << std::endl;
    00090         detSize = 2;
    00091         // put back 2 in parameter for consistency (and status file)
    00092         ppSelect.second.push_back(std::string("2"));
    00093       }
    00094     else          // parameter passed by user as DetTour(T)
    00095       detSize = atoi(ppSelect.second[0].c_str());
    00096     select = new eoDetTournamentSelect<EOT>(detSize);
    00097   }
    00098   else if (ppSelect.first == std::string("StochTour"))
    00099     {
    00100       double p;
    00101       if (!ppSelect.second.size())   // no parameter added
    00102         {
    00103           std::cerr << "WARNING, no parameter passed to StochTour, using 1" << std::endl;
    00104           p = 1;
    00105           // put back p in parameter for consistency (and status file)
    00106           ppSelect.second.push_back(std::string("1"));
    00107         }
    00108       else        // parameter passed by user as DetTour(T)
    00109         p = atof(ppSelect.second[0].c_str());
    00110
    00111       select = new eoStochTournamentSelect<EOT>(p);
    00112     }
    00113   else if (ppSelect.first == std::string("Ranking"))
    00114     {
    00115       double p,e;
    00116       if (ppSelect.second.size()==2)   // 2 parameters: pressure and exponent
    00117         {
    00118           p = atof(ppSelect.second[0].c_str());
    00119           e = atof(ppSelect.second[1].c_str());
    00120         }
    00121       else if (ppSelect.second.size()==1)   // 1 parameter: pressure
    00122         {
    00123           std::cerr << "WARNING, no exponent to Ranking, using 1" << std::endl;
    00124           e = 1;
    00125           ppSelect.second.push_back(std::string("1"));
    00126           p = atof(ppSelect.second[0].c_str());
    00127         }
    00128       else // no parameters ... or garbage
    00129         {
    00130           std::cerr << "WARNING, no parameter to Ranking, using (2,1)" << std::endl;
    00131           p=2;
    00132           e=1;
    00133           // put back in parameter for consistency (and status file)
    00134           ppSelect.second.resize(2); // just in case
    00135           ppSelect.second[0] = (std::string("2"));
    00136           ppSelect.second[1] = (std::string("1"));
    00137         }
    00138       // check for authorized values
    00139       // pressure in (0,1]
    00140       if ( (p<=1) || (p>2) )
    00141         {
    00142           std::cerr << "WARNING, selective pressure must be in (1,2] in Ranking, using 2\n";
    00143           p=2;
    00144           ppSelect.second[0] = (std::string("2"));
    00145         }
    00146       // exponent >0
    00147       if (e<=0)
    00148         {
    00149           std::cerr << "WARNING, exponent must be positive in Ranking, using 1\n";
    00150           e=1;
    00151           ppSelect.second[1] = (std::string("1"));
    00152         }
    00153       // now we're OK
    00154       eoPerf2Worth<EOT> & p2w = _state.storeFunctor( new eoRanking<EOT>(p,e) );
    00155       select = new eoRouletteWorthSelect<EOT>(p2w);
    00156     }
    00157   else if (ppSelect.first == std::string("Sequential")) // one after the other
    00158     {
    00159       bool b;
    00160       if (ppSelect.second.size() == 0)   // no argument -> default = ordered
    00161         {
    00162           b=true;
    00163           // put back in parameter for consistency (and status file)
    00164           ppSelect.second.push_back(std::string("ordered"));
    00165         }
    00166       else
    00167         b = !(ppSelect.second[0] == std::string("unordered"));
    00168       select = new eoSequentialSelect<EOT>(b);
    00169     }
    00170   else if (ppSelect.first == std::string("EliteSequential")) // Best first, one after the other in random order afterwards
    00171     {
    00172       select = new eoEliteSequentialSelect<EOT>;
    00173     }
    00174   else if (ppSelect.first == std::string("Roulette")) // no argument (yet)
    00175     {
    00176       select = new eoProportionalSelect<EOT>;
    00177     }
    00178   else if (ppSelect.first == std::string("Random")) // no argument
    00179     {
    00180       select = new eoRandomSelect<EOT>;
    00181     }
    00182   else
    00183     {
    00184       std::string stmp = std::string("Invalid selection: ") + ppSelect.first;
    00185       throw std::runtime_error(stmp.c_str());
    00186     }
    00187
    00188   _state.storeFunctor(select);
    00189
    00190   // the number of offspring
    00191     eoValueParam<eoHowMany>& offspringRateParam =  _parser.createParam(eoHowMany(1.0), "nbOffspring", "Nb of offspring (percentage or absolute)", 'O', "Evolution Engine");
    00192
    00194   // the replacement
    00196
    00225   eoParamParamType & replacementParam = _parser.createParam(eoParamParamType("General"), "replacement", "Type of replacement: General, or Generational, ESComma, ESPlus, SSGA(T), EP(T), G3, MGG(T)", '\0', "Evolution Engine").value();
    00226   // the pointer
    00227   eoReplacement<EOT> * ptReplace;
    00228
    00229   // first, separate G3 and MGG
    00230   // maybe one day we have a common class - but is it really necessary???
    00231   if (replacementParam.first == std::string("G3"))
    00232     {
    00233     // reduce the parents: by default, survive parents = -2 === 2 parents die
    00234     eoHowMany surviveParents =  _parser.createParam(eoHowMany(-2,false), "surviveParents", "Nb of surviving parents (percentage or absolute)", '\0', "Evolution Engine / Replacement").value();
    00235     // at the moment, this is the only argument
    00236     ptReplace = new eoG3Replacement<EOT>(-surviveParents);    // must receive nb of eliminated parets!
    00237     _state.storeFunctor(ptReplace);
    00238     }
    00239   else  if (replacementParam.first == std::string("MGG"))
    00240     {
    00241       float t;
    00242       unsigned tSize;
    00243     // reduce the parents: by default, survive parents = -2 === 2 parents die
    00244     eoHowMany surviveParents =  _parser.createParam(eoHowMany(-2,false), "surviveParents", "Nb of surviving parents (percentage or absolute)", '\0', "Evolution Engine / Replacement").value();
    00245     // the tournament size
    00246     if (!replacementParam.second.size())   // no parameter added
    00247       {
    00248         std::cerr << "WARNING, no parameter passed to MGG replacement, using 2" << std::endl;
    00249         tSize = 2;
    00250         // put back 2 in parameter for consistency (and status file)
    00251         replacementParam.second.push_back(std::string("2"));
    00252       }
    00253     else
    00254       {
    00255         t = atof(replacementParam.second[0].c_str());
    00256         if (t>=2)
    00257           {                        // build the appropriate deafult value
    00258             tSize = unsigned(t);
    00259           }
    00260         else
    00261           {
    00262             throw std::runtime_error("Sorry, only deterministic tournament available at the moment");
    00263           }
    00264       }
    00265     ptReplace = new eoMGGReplacement<EOT>(-surviveParents, tSize);
    00266     _state.storeFunctor(ptReplace);
    00267     }
    00268   else {   // until the end of what was the only loop/switch
    00269
    00270   // the default deafult values
    00271   eoHowMany elite (0.0);
    00272   bool strongElitism (false);
    00273   eoHowMany surviveParents (0.0);
    00274   eoParamParamType reduceParentType ("Deterministic");
    00275   eoHowMany surviveOffspring (1.0);
    00276   eoParamParamType reduceOffspringType ("Deterministic");
    00277   eoParamParamType reduceFinalType ("Deterministic");
    00278
    00279   // depending on the value entered by the user, change some of the above
    00280   double t;
    00281
    00282   // ---------- General
    00283   if (replacementParam.first == std::string("General"))
    00284   {
    00285     ;                              // defaults OK
    00286   }
    00287   // ---------- ESComma
    00288   else if (replacementParam.first == std::string("ESComma"))
    00289   {
    00290     ;                              // OK too
    00291   }
    00292   // ---------- ESPlus
    00293   else if (replacementParam.first == std::string("ESPlus"))
    00294   {
    00295     surviveParents = eoHowMany(1.0);
    00296   }
    00297   // ---------- Generational
    00298   else if (replacementParam.first == std::string("Generational"))
    00299   {
    00300     ;                        // OK too (we should check nb of offspring)
    00301   }
    00302   // ---------- EP
    00303   else if (replacementParam.first == std::string("EP"))
    00304   {
    00305     if (!replacementParam.second.size())   // no parameter added
    00306       {
    00307         std::cerr << "WARNING, no parameter passed to EP replacement, using 6" << std::endl;
    00308         // put back 6 in parameter for consistency (and status file)
    00309         replacementParam.second.push_back(std::string("6"));
    00310       }
    00311     // by coincidence, the syntax for the EP reducer is the same than here:
    00312     reduceFinalType = replacementParam;
    00313     surviveParents = eoHowMany(1.0);
    00314   }
    00315   // ---------- SSGA
    00316   else if (replacementParam.first == std::string("SSGA"))
    00317   {
    00318     if (!replacementParam.second.size())   // no parameter added
    00319       {
    00320         std::cerr << "WARNING, no parameter passed to SSGA replacement, using 2" << std::endl;
    00321         // put back 2 in parameter for consistency (and status file)
    00322         replacementParam.second.push_back(std::string("2"));
    00323         reduceParentType = eoParamParamType(std::string("DetTour(2)"));
    00324       }
    00325     else
    00326       {
    00327         t = atof(replacementParam.second[0].c_str());
    00328         if (t>=2)
    00329           {                        // build the appropriate deafult value
    00330             reduceParentType = eoParamParamType(std::string("DetTour(") + replacementParam.second[0].c_str() + ")");
    00331           }
    00332         else   // check for [0.5,1] will be made in make_general_replacement
    00333           {                        // build the appropriate deafult value
    00334             reduceParentType = eoParamParamType(std::string("StochTour(") + replacementParam.second[0].c_str() + ")");
    00335           }
    00336       }
    00337     //
    00338     surviveParents = eoHowMany(-1);
    00339     surviveOffspring = eoHowMany(1);
    00340   }
    00341   else                 // no replacement recognized
    00342     {
    00343       throw std::runtime_error("Invalid replacement type " + replacementParam.first);
    00344     }
    00345
    00346   ptReplace = & make_general_replacement<EOT>(
    00347      _parser, _state, elite, strongElitism, surviveParents, reduceParentType, surviveOffspring, reduceOffspringType, reduceFinalType);
    00348
    00349   } // end of the ugly construct due to G3 and MGG - totaly heterogeneous at the moment
    00350
    00351
    00353   // the general breeder
    00355   eoGeneralBreeder<EOT> *breed =
    00356     new eoGeneralBreeder<EOT>(*select, _op, offspringRateParam.value());
    00357   _state.storeFunctor(breed);
    00358
    00360   // now the eoEasyEA
    00362   eoAlgo<EOT> *algo = new eoEasyEA<EOT>(_continue, _eval, *breed, *ptReplace);
    00363   _state.storeFunctor(algo);
    00364   // that's it!
    00365   return *algo;
    00366 }
    00367
    00368 #endif