EvolvingObjects
eoVariableLengthCrossover.h
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
 All Classes Namespaces Files Functions Variables Typedefs Friends