# 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