EvolvingObjects
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  * This function builds the algorithm (i.e. selection and replacement)
00062  *      from existing continue (or checkpoint) and operators
00063  *
00064  * It uses a parser (to get user parameters) and a state (to store the memory)
00065  * the last argument is an individual, needed for 2 reasons
00066  *     it disambiguates the call after instanciations
00067  *     some operator might need some private information about the indis
00068  *
00069  * This is why the template is the complete EOT even though only the fitness
00070  * is actually templatized here
00071  *
00072  *
00073  * @ingroup Builders
00074 */
00075 template <class EOT>
00076 eoAlgo<EOT> & do_make_algo_scalar(eoParser& _parser, eoState& _state, eoPopEvalFunc<EOT>& _popeval, eoContinue<EOT>& _continue, eoGenOp<EOT>& _op)
00077 {
00078   // the selection
00079   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");
00080 
00081   eoParamParamType & ppSelect = selectionParam.value(); // std::pair<std::string,std::vector<std::string> >
00082 
00083   eoSelectOne<EOT>* select ;
00084   if (ppSelect.first == std::string("DetTour"))
00085   {
00086     unsigned detSize;
00087 
00088     if (!ppSelect.second.size())   // no parameter added
00089       {
00090         std::cerr << "WARNING, no parameter passed to DetTour, using 2" << std::endl;
00091         detSize = 2;
00092         // put back 2 in parameter for consistency (and status file)
00093         ppSelect.second.push_back(std::string("2"));
00094       }
00095     else          // parameter passed by user as DetTour(T)
00096       detSize = atoi(ppSelect.second[0].c_str());
00097     select = new eoDetTournamentSelect<EOT>(detSize);
00098   }
00099   else if (ppSelect.first == std::string("StochTour"))
00100     {
00101       double p;
00102       if (!ppSelect.second.size())   // no parameter added
00103         {
00104           std::cerr << "WARNING, no parameter passed to StochTour, using 1" << std::endl;
00105           p = 1;
00106           // put back p in parameter for consistency (and status file)
00107           ppSelect.second.push_back(std::string("1"));
00108         }
00109       else        // parameter passed by user as DetTour(T)
00110         p = atof(ppSelect.second[0].c_str());
00111 
00112       select = new eoStochTournamentSelect<EOT>(p);
00113     }
00114   else if (ppSelect.first == std::string("Ranking"))
00115     {
00116       double p,e;
00117       if (ppSelect.second.size()==2)   // 2 parameters: pressure and exponent
00118         {
00119           p = atof(ppSelect.second[0].c_str());
00120           e = atof(ppSelect.second[1].c_str());
00121         }
00122       else if (ppSelect.second.size()==1)   // 1 parameter: pressure
00123         {
00124           std::cerr << "WARNING, no exponent to Ranking, using 1" << std::endl;
00125           e = 1;
00126           ppSelect.second.push_back(std::string("1"));
00127           p = atof(ppSelect.second[0].c_str());
00128         }
00129       else // no parameters ... or garbage
00130         {
00131           std::cerr << "WARNING, no parameter to Ranking, using (2,1)" << std::endl;
00132           p=2;
00133           e=1;
00134           // put back in parameter for consistency (and status file)
00135           ppSelect.second.resize(2); // just in case
00136           ppSelect.second[0] = (std::string("2"));
00137           ppSelect.second[1] = (std::string("1"));
00138         }
00139       // check for authorized values
00140       // pressure in (0,1]
00141       if ( (p<=1) || (p>2) )
00142         {
00143           std::cerr << "WARNING, selective pressure must be in (1,2] in Ranking, using 2\n";
00144           p=2;
00145           ppSelect.second[0] = (std::string("2"));
00146         }
00147       // exponent >0
00148       if (e<=0)
00149         {
00150           std::cerr << "WARNING, exponent must be positive in Ranking, using 1\n";
00151           e=1;
00152           ppSelect.second[1] = (std::string("1"));
00153         }
00154       // now we're OK
00155       eoPerf2Worth<EOT> & p2w = _state.storeFunctor( new eoRanking<EOT>(p,e) );
00156       select = new eoRouletteWorthSelect<EOT>(p2w);
00157     }
00158   else if (ppSelect.first == std::string("Sequential")) // one after the other
00159     {
00160       bool b;
00161       if (ppSelect.second.size() == 0)   // no argument -> default = ordered
00162         {
00163           b=true;
00164           // put back in parameter for consistency (and status file)
00165           ppSelect.second.push_back(std::string("ordered"));
00166         }
00167       else
00168         b = !(ppSelect.second[0] == std::string("unordered"));
00169       select = new eoSequentialSelect<EOT>(b);
00170     }
00171   else if (ppSelect.first == std::string("EliteSequential")) // Best first, one after the other in random order afterwards
00172     {
00173       select = new eoEliteSequentialSelect<EOT>;
00174     }
00175   else if (ppSelect.first == std::string("Roulette")) // no argument (yet)
00176     {
00177       select = new eoProportionalSelect<EOT>;
00178     }
00179   else if (ppSelect.first == std::string("Random")) // no argument
00180     {
00181       select = new eoRandomSelect<EOT>;
00182     }
00183   else
00184     {
00185       std::string stmp = std::string("Invalid selection: ") + ppSelect.first;
00186       throw std::runtime_error(stmp.c_str());
00187     }
00188 
00189   _state.storeFunctor(select);
00190 
00191   // the number of offspring
00192     eoValueParam<eoHowMany>& offspringRateParam =  _parser.createParam(eoHowMany(1.0), "nbOffspring", "Nb of offspring (percentage or absolute)", 'O', "Evolution Engine");
00193 
00195   // the replacement
00197 
00226   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();
00227   // the pointer
00228   eoReplacement<EOT> * ptReplace;
00229 
00230   // first, separate G3 and MGG
00231   // maybe one day we have a common class - but is it really necessary???
00232   if (replacementParam.first == std::string("G3"))
00233     {
00234     // reduce the parents: by default, survive parents = -2 === 2 parents die
00235     eoHowMany surviveParents =  _parser.createParam(eoHowMany(-2,false), "surviveParents", "Nb of surviving parents (percentage or absolute)", '\0', "Evolution Engine / Replacement").value();
00236     // at the moment, this is the only argument
00237     ptReplace = new eoG3Replacement<EOT>(-surviveParents);    // must receive nb of eliminated parets!
00238     _state.storeFunctor(ptReplace);
00239     }
00240   else  if (replacementParam.first == std::string("MGG"))
00241     {
00242       float t;
00243       unsigned tSize;
00244     // reduce the parents: by default, survive parents = -2 === 2 parents die
00245     eoHowMany surviveParents =  _parser.createParam(eoHowMany(-2,false), "surviveParents", "Nb of surviving parents (percentage or absolute)", '\0', "Evolution Engine / Replacement").value();
00246     // the tournament size
00247     if (!replacementParam.second.size())   // no parameter added
00248       {
00249         std::cerr << "WARNING, no parameter passed to MGG replacement, using 2" << std::endl;
00250         tSize = 2;
00251         // put back 2 in parameter for consistency (and status file)
00252         replacementParam.second.push_back(std::string("2"));
00253       }
00254     else
00255       {
00256         t = atof(replacementParam.second[0].c_str());
00257         if (t>=2)
00258           {                        // build the appropriate deafult value
00259             tSize = unsigned(t);
00260           }
00261         else
00262           {
00263             throw std::runtime_error("Sorry, only deterministic tournament available at the moment");
00264           }
00265       }
00266     ptReplace = new eoMGGReplacement<EOT>(-surviveParents, tSize);
00267     _state.storeFunctor(ptReplace);
00268     }
00269   else {   // until the end of what was the only loop/switch
00270 
00271   // the default deafult values
00272   eoHowMany elite (0.0);
00273   bool strongElitism (false);
00274   eoHowMany surviveParents (0.0);
00275   eoParamParamType reduceParentType ("Deterministic");
00276   eoHowMany surviveOffspring (1.0);
00277   eoParamParamType reduceOffspringType ("Deterministic");
00278   eoParamParamType reduceFinalType ("Deterministic");
00279 
00280   // depending on the value entered by the user, change some of the above
00281   double t;
00282 
00283   // ---------- General
00284   if (replacementParam.first == std::string("General"))
00285   {
00286     ;                              // defaults OK
00287   }
00288   // ---------- ESComma
00289   else if (replacementParam.first == std::string("ESComma"))
00290   {
00291     ;                              // OK too
00292   }
00293   // ---------- ESPlus
00294   else if (replacementParam.first == std::string("ESPlus"))
00295   {
00296     surviveParents = eoHowMany(1.0);
00297   }
00298   // ---------- Generational
00299   else if (replacementParam.first == std::string("Generational"))
00300   {
00301     ;                        // OK too (we should check nb of offspring)
00302   }
00303   // ---------- EP
00304   else if (replacementParam.first == std::string("EP"))
00305   {
00306     if (!replacementParam.second.size())   // no parameter added
00307       {
00308         std::cerr << "WARNING, no parameter passed to EP replacement, using 6" << std::endl;
00309         // put back 6 in parameter for consistency (and status file)
00310         replacementParam.second.push_back(std::string("6"));
00311       }
00312     // by coincidence, the syntax for the EP reducer is the same than here:
00313     reduceFinalType = replacementParam;
00314     surviveParents = eoHowMany(1.0);
00315   }
00316   // ---------- SSGA
00317   else if (replacementParam.first == std::string("SSGA"))
00318   {
00319     if (!replacementParam.second.size())   // no parameter added
00320       {
00321         std::cerr << "WARNING, no parameter passed to SSGA replacement, using 2" << std::endl;
00322         // put back 2 in parameter for consistency (and status file)
00323         replacementParam.second.push_back(std::string("2"));
00324         reduceParentType = eoParamParamType(std::string("DetTour(2)"));
00325       }
00326     else
00327       {
00328         t = atof(replacementParam.second[0].c_str());
00329         if (t>=2)
00330           {                        // build the appropriate deafult value
00331             reduceParentType = eoParamParamType(std::string("DetTour(") + replacementParam.second[0].c_str() + ")");
00332           }
00333         else   // check for [0.5,1] will be made in make_general_replacement
00334           {                        // build the appropriate deafult value
00335             reduceParentType = eoParamParamType(std::string("StochTour(") + replacementParam.second[0].c_str() + ")");
00336           }
00337       }
00338     //
00339     surviveParents = eoHowMany(-1);
00340     surviveOffspring = eoHowMany(1);
00341   }
00342   else                 // no replacement recognized
00343     {
00344       throw std::runtime_error("Invalid replacement type " + replacementParam.first);
00345     }
00346 
00347   ptReplace = & make_general_replacement<EOT>(
00348      _parser, _state, elite, strongElitism, surviveParents, reduceParentType, surviveOffspring, reduceOffspringType, reduceFinalType);
00349 
00350   } // end of the ugly construct due to G3 and MGG - totaly heterogeneous at the moment
00351 
00352 
00354   // the general breeder
00356   eoGeneralBreeder<EOT> *breed =
00357     new eoGeneralBreeder<EOT>(*select, _op, offspringRateParam.value());
00358   _state.storeFunctor(breed);
00359 
00361   // now the eoEasyEA
00363   eoAlgo<EOT> *algo = new eoEasyEA<EOT>(_continue, _popeval, *breed, *ptReplace);
00364   _state.storeFunctor(algo);
00365   // that's it!
00366   return *algo;
00367 }
00368 
00369 /*
00370  * This function builds the algorithm (i.e. selection and replacement)
00371  *      from existing continue (or checkpoint) and operators
00372  *
00373  * It uses a parser (to get user parameters) and a state (to store the memory)
00374  * the last argument is an individual, needed for 2 reasons
00375  *     it disambiguates the call after instanciations
00376  *     some operator might need some private information about the indis
00377  *
00378  * This is why the template is the complete EOT even though only the fitness
00379  * is actually templatized here
00380 */
00381 template <class EOT>
00382 eoAlgo<EOT> & do_make_algo_scalar(eoParser& _parser, eoState& _state, eoEvalFunc<EOT>& _eval, eoContinue<EOT>& _continue, eoGenOp<EOT>& _op)
00383 {
00384          do_make_algo_scalar( _parser, _state, *(new eoPopLoopEval<EOT>(_eval)), _continue, _op);
00385 }
00386 
00387 
00388 
00389 #endif
 All Classes Namespaces Files Functions Variables Typedefs Friends