EvolvingObjects
|
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