EvolvingObjects
|
00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- 00002 00003 //----------------------------------------------------------------------------- 00004 // eoVariableLengthCrossover.h 00005 // (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000 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: Marc.Schoenauer@polytechnique.fr 00022 mkeijzer@cs.vu.nl 00023 */ 00024 //----------------------------------------------------------------------------- 00025 00026 #ifndef _eoVariableLengthCrossover_h 00027 #define _eoVariableLengthCrossover_h 00028 00029 #include <eoFunctor.h> 00030 #include <eoOp.h> 00031 00044 template <class Atom> 00045 class eoAtomExchange : public eoBF<unsigned, Atom &, bool> 00046 { 00047 public: 00049 virtual void randomize(unsigned int, unsigned int){} 00051 virtual std::string className() const=0; 00052 }; 00053 00055 template <class Atom> 00056 class eoUniformAtomExchange: public eoAtomExchange<Atom> 00057 { 00058 public: 00059 eoUniformAtomExchange(double _rate=0.5):rate(_rate){} 00060 00065 void randomize(unsigned _size1, unsigned _size2) 00066 { 00067 mask.resize(_size1 + _size2); 00068 for (unsigned i=0; i<_size1+_size2; i++) 00069 mask[i]=eo::rng.flip(rate); 00070 } 00071 00073 bool operator()(unsigned _i, Atom & ) 00074 { 00075 return mask[_i]; 00076 } 00077 00079 virtual std::string className() const {return "eoUniformAtomExchange";} 00080 00081 private: 00082 double rate; 00083 std::vector<bool> mask; 00084 }; 00085 00089 00092 template <class EOT> 00093 class eoVlAtomExchangeQuadOp : public eoQuadOp<EOT> 00094 { 00095 public : 00096 00097 typedef typename EOT::AtomType AtomType; 00098 00100 eoVlAtomExchangeQuadOp(unsigned _Min, unsigned _Max, 00101 eoAtomExchange<AtomType>& _atomExchange): 00102 Min(_Min), Max(_Max), atomExchange(_atomExchange) {} 00103 00104 bool operator()(EOT & _eo1, EOT & _eo2) 00105 { 00106 EOT tmp1, tmp2; // empty individuals 00107 unsigned index=0; 00108 // main loop: until sizes are OK, do only simulated exchange 00109 unsigned i, i1, i2; 00110 do { 00111 // "initialize the AtomExchange 00112 atomExchange.randomize(_eo1.size(), _eo2.size()); 00113 // simulate crossover 00114 i1=i2=0; 00115 for (i=0; i<_eo1.size(); i++) 00116 { 00117 if (atomExchange(i, _eo1[i])) 00118 i1++; 00119 else 00120 i2++; 00121 } 00122 for (i=0; i<_eo2.size(); i++) 00123 { 00124 if (atomExchange(i, _eo2[i])) 00125 i2++; 00126 else 00127 i1++; 00128 } 00129 index++; 00130 } while ( ( (i1<Min) || (i2<Min) || 00131 (i1>Max) || (i2>Max) ) 00132 && (index<10000) ); 00133 if (index >= 10000) 00134 { 00135 eo::log << eo::warnings << "Warning: impossible to generate individual of the right size in 10000 trials" << std::endl; 00136 return false; 00137 } 00138 // here we know we have the right sizes: do the actual exchange 00139 for (i=0; i<_eo1.size(); i++) 00140 { 00141 if (atomExchange(i, _eo1[i])) 00142 tmp1.push_back(_eo1[i]); 00143 else 00144 tmp2.push_back(_eo1[i]); 00145 } 00146 for (i=0; i<_eo2.size(); i++) 00147 { 00148 if (atomExchange(i, _eo2[i])) 00149 tmp2.push_back(_eo2[i]); 00150 else 00151 tmp1.push_back(_eo2[i]); 00152 } 00153 // and put everything back in place 00154 _eo1.swap(tmp1); 00155 _eo2.swap(tmp2); 00156 return true; // should we test that? Yes, but no time now 00157 } 00158 00160 virtual std::string className() const 00161 { 00162 std::ostringstream os; 00163 os << "eoVlAtomExchangeQuadOp(" << atomExchange.className() << ")"; 00164 return os.str(); 00165 } 00166 00167 private: 00168 unsigned Min, Max; 00169 eoAtomExchange<AtomType> & atomExchange; 00170 }; 00171 00175 template <class EOT> 00176 class eoInnerExchangeQuadOp : public eoQuadOp<EOT> 00177 { 00178 public : 00179 00180 typedef typename EOT::AtomType AtomType; 00181 00183 eoInnerExchangeQuadOp( eoQuadOp<AtomType>& _op, float _rate = 0.5): 00184 op(_op), rate( _rate ) {} 00185 00187 bool operator()(EOT & _eo1, EOT & _eo2) 00188 { 00189 unsigned size1 = _eo1.size(), size2 = _eo2.size(), minsize = ( size1 > size2)?size2:size1; 00190 bool changed = false; 00191 for ( unsigned i = 0; i < minsize; i ++ ) { 00192 if ( rng.flip( rate ) ) { 00193 bool changedHere = op( _eo1[i], _eo2[i] ); 00194 changed |= changedHere; 00195 } 00196 } 00197 return changed; // should we test that? Yes, but no time now 00198 } 00199 00200 virtual std::string className() const 00201 { 00202 return "eoInnerExchangeQuadOp(" + op.className() + ")"; 00203 } 00204 00205 private: 00206 float rate; 00207 eoQuadOp<AtomType> & op; 00208 }; 00209 00210 00211 00212 00222 template <class EOT> 00223 class eoVlUniformQuadOp : public eoQuadOp<EOT> 00224 { 00225 public : 00226 00227 typedef typename EOT::AtomType AtomType; 00228 00229 // default ctor: requires bounds on number of genes + a rate 00230 eoVlUniformQuadOp(unsigned _Min, unsigned _Max, double _rate=0.5) : 00231 Min(_Min), Max(_Max), rate(_rate) {} 00232 00233 bool operator()(EOT & _eo1, EOT & _eo2) 00234 { 00235 unsigned i; 00236 EOT tmp1, tmp2; 00237 unsigned index=0; 00238 do { 00239 for (i=0; i<_eo1.size(); i++) 00240 { 00241 if (eo::rng.flip(rate)) 00242 tmp1.push_back(_eo1[i]); 00243 else 00244 tmp2.push_back(_eo1[i]); 00245 // here we should look for _eo1[i] inside _eo2 and erase it if found! 00246 } 00247 for (i=0; i<_eo2.size(); i++) 00248 { 00249 if (eo::rng.flip(rate)) 00250 tmp1.push_back(_eo2[i]); 00251 else 00252 tmp2.push_back(_eo2[i]); 00253 } 00254 index++; 00255 } while ( ( (tmp1.size()<Min) || (tmp2.size()<Min) || 00256 (tmp1.size()>Max) || (tmp2.size()>Max) ) 00257 && (index<10000) ); 00259 if (index >= 10000) 00260 { 00261 eo::log << eo::warnings << "Warning: impossible to generate individual of the right size in 10000 trials" << std::endl; 00262 return false; 00263 } 00264 00265 _eo1.swap(tmp1); 00266 _eo2.swap(tmp2); 00267 return true; // should we test that? 00268 } 00269 private: 00270 unsigned Min, Max; 00271 double rate; 00272 }; 00273 00274 00284 template <class EOT> 00285 class eoVlUniformBinOp : public eoBinOp<EOT> 00286 { 00287 public : 00288 00289 typedef typename EOT::AtomType AtomType; 00290 00291 // default ctor: requires bounds on number of genes + a rate 00292 eoVlUniformBinOp(unsigned _Min, unsigned _Max, double _rate=0.5) : 00293 Min(_Min), Max(_Max), rate(_rate) {} 00294 00295 bool operator()(EOT & _eo1, const EOT & _eo2) 00296 { 00297 unsigned i; 00298 EOT tmp1; 00299 bool tmpIsOne=true, tmpIsTwo=true; 00300 unsigned index=0; 00301 do { 00302 for (i=0; i<_eo1.size(); i++) 00303 { 00304 if (eo::rng.flip(rate)) 00305 { 00306 tmp1.push_back(_eo1[i]); 00307 tmpIsTwo = false; 00308 } 00309 else 00310 tmpIsOne=false; 00311 // we should look for _eo1[i] inside _eo2 and erase it there if found! 00312 } 00313 for (i=0; i<_eo2.size(); i++) 00314 { 00315 if (! eo::rng.flip(rate)) 00316 { 00317 tmp1.push_back(_eo2[i]); 00318 tmpIsOne = false; 00319 } 00320 else 00321 tmpIsTwo = false; 00322 } 00323 index++; 00324 } while ( ( (tmp1.size()<Min) || (tmp1.size()>Max) ) 00325 && (index<10000) ); 00326 // this while condition is not optimal, as it may take some time, see the FIXME above 00327 if (index >= 10000) 00328 { 00329 eo::log << eo::warnings << "Warning: impossible to generate individual of the right size in 10000 trials" << std::endl; 00330 return false; 00331 } 00332 00333 _eo1.swap(tmp1); 00334 if (tmpIsTwo) 00335 { 00336 // _eo1.fitness(_eo2.fitness()); NO FITNESS EXISTS HERE! 00337 return false; 00338 } 00339 if (tmpIsOne) // already has the right fitness 00340 { // WRONG: NO FITNESS EXISTS HERE! 00341 return false; 00342 } 00343 return true; // there were some modifications... 00344 } 00345 00346 private: 00347 unsigned Min, Max; 00348 double rate; 00349 }; 00350 00352 #endif