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 
00040 template <class Atom>
00041 class eoAtomExchange : public eoBF<unsigned, Atom &, bool>
00042 {
00043 public:
00045   virtual void randomize(unsigned int, unsigned int){}
00047   virtual std::string className() const=0;
00048 };
00049 
00051 template <class Atom>
00052 class eoUniformAtomExchange: public eoAtomExchange<Atom>
00053 {
00054 public:
00055     eoUniformAtomExchange(double _rate=0.5):rate(_rate){}
00056 
00061   void randomize(unsigned _size1, unsigned _size2)
00062   {
00063     mask.resize(_size1 + _size2);
00064     for (unsigned i=0; i<_size1+_size2; i++)
00065         mask[i]=eo::rng.flip(rate);
00066   }
00067 
00069     bool operator()(unsigned _i, Atom & )
00070     {
00071       return mask[_i];
00072     }
00073 
00075   virtual std::string className() const {return "eoUniformAtomExchange";}
00076 
00077 private:
00078   double rate;
00079   std::vector<bool> mask;
00080 };
00081 
00085 
00088 template <class EOT>
00089 class eoVlAtomExchangeQuadOp : public eoQuadOp<EOT>
00090 {
00091 public :
00092 
00093   typedef typename EOT::AtomType AtomType;
00094 
00096   eoVlAtomExchangeQuadOp(unsigned _Min, unsigned _Max,
00097                          eoAtomExchange<AtomType>& _atomExchange):
00098     Min(_Min), Max(_Max), atomExchange(_atomExchange) {}
00099 
00100   bool operator()(EOT & _eo1, EOT & _eo2)
00101   {
00102     EOT tmp1, tmp2;                // empty individuals
00103     unsigned index=0;
00104     // main loop: until sizes are OK, do only simulated exchange
00105     unsigned i, i1, i2;
00106     do {
00107       // "initialize the AtomExchange
00108       atomExchange.randomize(_eo1.size(), _eo2.size());
00109       // simulate crossover
00110       i1=i2=0;
00111       for (i=0; i<_eo1.size(); i++)
00112         {
00113           if (atomExchange(i, _eo1[i]))
00114             i1++;
00115           else
00116             i2++;
00117         }
00118       for (i=0; i<_eo2.size(); i++)
00119         {
00120           if (atomExchange(i, _eo2[i]))
00121             i2++;
00122           else
00123             i1++;
00124         }
00125       index++;
00126     } while ( ( (i1<Min) || (i2<Min) ||
00127                 (i1>Max) || (i2>Max) )
00128               && (index<10000) );
00129     if (index >= 10000)
00130       {
00131         std::cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
00132         return false;
00133       }
00134   // here we know we have the right sizes: do the actual exchange
00135       for (i=0; i<_eo1.size(); i++)
00136         {
00137           if (atomExchange(i, _eo1[i]))
00138             tmp1.push_back(_eo1[i]);
00139           else
00140             tmp2.push_back(_eo1[i]);
00141         }
00142       for (i=0; i<_eo2.size(); i++)
00143         {
00144           if (atomExchange(i, _eo2[i]))
00145             tmp2.push_back(_eo2[i]);
00146           else
00147             tmp1.push_back(_eo2[i]);
00148         }
00149       // and put everything back in place
00150     _eo1.swap(tmp1);
00151     _eo2.swap(tmp2);
00152     return true;         // should we test that? Yes, but no time now
00153   }
00154 
00156   virtual std::string className() const
00157   {
00158       std::ostringstream os;
00159       os << "eoVlAtomExchangeQuadOp(" << atomExchange.className() << ")";
00160       return os.str();
00161   }
00162 
00163 private:
00164   unsigned Min, Max;
00165   eoAtomExchange<AtomType> & atomExchange;
00166 };
00167 
00171 template <class EOT>
00172 class eoInnerExchangeQuadOp : public eoQuadOp<EOT>
00173 {
00174 public :
00175 
00176   typedef typename EOT::AtomType AtomType;
00177 
00179   eoInnerExchangeQuadOp( eoQuadOp<AtomType>& _op, float _rate = 0.5):
00180     op(_op), rate( _rate ) {}
00181 
00183   bool operator()(EOT & _eo1, EOT & _eo2)
00184   {
00185     unsigned size1 = _eo1.size(), size2 = _eo2.size(), minsize = ( size1 > size2)?size2:size1;
00186     bool changed = false;
00187     for ( unsigned i = 0; i < minsize; i ++ ) {
00188       if ( rng.flip( rate ) ) {
00189         bool changedHere = op( _eo1[i], _eo2[i] );
00190         changed |= changedHere;
00191       }
00192     }
00193     return changed;      // should we test that? Yes, but no time now
00194   }
00195 
00196   virtual std::string className() const
00197   {
00198     return "eoInnerExchangeQuadOp(" + op.className() + ")";
00199   }
00200 
00201 private:
00202   float rate;
00203   eoQuadOp<AtomType> & op;
00204 };
00205 
00206 
00207 
00208 
00218 template <class EOT>
00219 class eoVlUniformQuadOp : public eoQuadOp<EOT>
00220 {
00221 public :
00222 
00223   typedef typename EOT::AtomType AtomType;
00224 
00225   // default ctor: requires bounds on number of genes + a rate
00226   eoVlUniformQuadOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
00227     Min(_Min), Max(_Max), rate(_rate) {}
00228 
00229   bool operator()(EOT & _eo1, EOT & _eo2)
00230   {
00231     unsigned i;
00232     EOT tmp1, tmp2;
00233     unsigned index=0;
00234     do {
00235       for (i=0; i<_eo1.size(); i++)
00236         {
00237           if (eo::rng.flip(rate))
00238             tmp1.push_back(_eo1[i]);
00239           else
00240             tmp2.push_back(_eo1[i]);
00241           // here we should look for _eo1[i] inside _eo2 and erase it if found!
00242         }
00243       for (i=0; i<_eo2.size(); i++)
00244         {
00245           if (eo::rng.flip(rate))
00246             tmp1.push_back(_eo2[i]);
00247           else
00248             tmp2.push_back(_eo2[i]);
00249         }
00250       index++;
00251     } while ( ( (tmp1.size()<Min) || (tmp2.size()<Min) ||
00252               (tmp1.size()>Max) || (tmp2.size()>Max) )
00253               && (index<10000) );
00254     if (index >= 10000)
00255       {
00256         std::cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
00257         return false;
00258       }
00259 
00260     _eo1.swap(tmp1);
00261     _eo2.swap(tmp2);
00262     return true;                   // should we test that?
00263   }
00264 private:
00265   unsigned Min, Max;
00266   double rate;
00267 };
00268 
00269 
00279 template <class EOT>
00280 class eoVlUniformBinOp : public eoBinOp<EOT>
00281 {
00282 public :
00283 
00284   typedef typename EOT::AtomType AtomType;
00285 
00286   // default ctor: requires bounds on number of genes + a rate
00287   eoVlUniformBinOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
00288     Min(_Min), Max(_Max), rate(_rate) {}
00289 
00290   bool operator()(EOT & _eo1, const EOT & _eo2)
00291   {
00292     unsigned i;
00293     EOT tmp1;
00294     bool tmpIsOne=true, tmpIsTwo=true;
00295     unsigned index=0;
00296     do {
00297       for (i=0; i<_eo1.size(); i++)
00298         {
00299           if (eo::rng.flip(rate))
00300             {
00301               tmp1.push_back(_eo1[i]);
00302               tmpIsTwo = false;
00303             }
00304           else
00305             tmpIsOne=false;
00306         // we should look for _eo1[i] inside _eo2 and erase it there if found!
00307         }
00308       for (i=0; i<_eo2.size(); i++)
00309         {
00310           if (! eo::rng.flip(rate))
00311             {
00312               tmp1.push_back(_eo2[i]);
00313               tmpIsOne = false;
00314             }
00315           else
00316             tmpIsTwo = false;
00317         }
00318       index++;
00319     } while ( ( (tmp1.size()<Min) || (tmp1.size()>Max) )
00320               && (index<10000) );
00321     // this while condition is not optimal, as it may take some time
00322     if (index >= 10000)
00323       {
00324         std::cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
00325         return false;
00326       }
00327 
00328     _eo1.swap(tmp1);
00329     if (tmpIsTwo)
00330       {
00331         //      _eo1.fitness(_eo2.fitness());     NO FITNESS EXISTS HERE!
00332         return false;
00333       }
00334     if (tmpIsOne)                  // already has the right fitness
00335       {                            // WRONG: NO FITNESS EXISTS HERE!
00336         return false;
00337       }
00338     return true;                   // there were some modifications...
00339   }
00340 
00341 private:
00342   unsigned Min, Max;
00343   double rate;
00344 };
00345 
00346 
00347 
00348 #endif

Generated on Thu Oct 19 05:06:39 2006 for EO by  doxygen 1.3.9.1