# eoBitOp.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoBitOp.h
    00005 // (c) GeNeura Team, 2000 - EEAAX 2000 - 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: todos@geneura.ugr.es, http://geneura.ugr.es
    00022              Marc.Schoenauer@polytechnique.fr
    00023              mak@dhi.dk
    00024  CVS Info: $Date: 2003/06/06 10:29:13 $ $Header: /cvsroot/eodev/eo/src/ga/eoBitOp.h,v 1.17 2003/06/06 10:29:13 maartenkeijzer Exp $ $Author: maartenkeijzer $
    00025  */
    00026 //-----------------------------------------------------------------------------
    00027
    00028 #ifndef eoBitOp_h
    00029 #define eoBitOp_h
    00030
    00031 //-----------------------------------------------------------------------------
    00032
    00033 #include <algorithm>    // swap_ranges
    00034 #include <utils/eoRNG.h>
    00035 #include <eoInit.h>       // eoMonOp
    00036 #include <ga/eoBit.h>
    00037
    00038
    00044 template<class Chrom> class eoOneBitFlip: public eoMonOp<Chrom>
    00045 {
    00046  public:
    00048   virtual std::string className() const { return "eoOneBitFlip"; }
    00049
    00054   bool operator()(Chrom& chrom)
    00055     {
    00056       unsigned i = eo::rng.random(chrom.size());
    00057       chrom[i] = (chrom[i]) ? false : true;
    00058       return true;
    00059     }
    00060 };
    00061
    00067 template<class Chrom> class eoDetBitFlip: public eoMonOp<Chrom>
    00068 {
    00069  public:
    00075   eoDetBitFlip(const unsigned& _num_bit = 1): num_bit(_num_bit) {}
    00076
    00078   virtual std::string className() const { return "eoDetBitFlip"; }
    00079
    00084   bool operator()(Chrom& chrom)
    00085     {
    00086       // does not check for duplicate: if someone volunteers ....
    00087       for (unsigned k=0; k<num_bit; k++)
    00088         {
    00089           unsigned i = eo::rng.random(chrom.size());
    00090           chrom[i] = (chrom[i]) ? false : true;
    00091         }
    00092       return true;
    00093     }
    00094  private:
    00095   unsigned num_bit;
    00096 };
    00097
    00098
    00104 template<class Chrom> class eoBitMutation: public eoMonOp<Chrom>
    00105 {
    00106  public:
    00111   eoBitMutation(const double& _rate = 0.01, bool _normalize=false):
    00112     rate(_rate), normalize(_normalize) {}
    00113
    00115   virtual std::string className() const { return "eoBitMutation"; }
    00116
    00121   bool operator()(Chrom& chrom)
    00122     {
    00123       double actualRate = (normalize ? rate/chrom.size() : rate);
    00124       bool changed_something = false;
    00125       for (unsigned i = 0; i < chrom.size(); i++)
    00126             if (eo::rng.flip(actualRate))
    00127         {
    00128                 chrom[i] = !chrom[i];
    00129             changed_something = true;
    00130         }
    00131
    00132         return changed_something;
    00133     }
    00134
    00135  private:
    00136   double rate;
    00137   bool normalize;                  // divide rate by chromSize
    00138 };
    00139
    00140
    00146 template<class Chrom> class eoBitInversion: public eoMonOp<Chrom>
    00147 {
    00148  public:
    00150   virtual std::string className() const { return "eoBitInversion"; }
    00151
    00156   bool operator()(Chrom& chrom)
    00157     {
    00158
    00159       unsigned u1 = eo::rng.random(chrom.size() + 1) , u2;
    00160       do u2 = eo::rng.random(chrom.size() + 1); while (u1 == u2);
    00161       unsigned r1 = std::min(u1, u2), r2 = std::max(u1, u2);
    00162
    00163       std::reverse(chrom.begin() + r1, chrom.begin() + r2);
    00164       return true;
    00165     }
    00166 };
    00167
    00168
    00174 template<class Chrom> class eoBitNext: public eoMonOp<Chrom>
    00175 {
    00176  public:
    00178   virtual std::string className() const { return "eoBitNext"; }
    00179
    00184   bool operator()(Chrom& chrom)
    00185     {
    00186       for (int i = chrom.size() - 1; i >= 0; i--)
    00187         if (chrom[i])
    00188           {
    00189             chrom[i] = 0;
    00190             continue;
    00191           }
    00192         else
    00193           {
    00194             chrom[i] = 1;
    00195             break;
    00196           }
    00197
    00198     return true;
    00199     }
    00200 };
    00201
    00202
    00208 template<class Chrom> class eoBitPrev: public eoMonOp<Chrom>
    00209 {
    00210  public:
    00212   virtual std::string className() const { return "eoBitPrev"; }
    00213
    00218   bool operator()(Chrom& chrom)
    00219     {
    00220       for (int i = chrom.size() - 1; i >= 0; i--)
    00221         if (chrom[i])
    00222           {
    00223             chrom[i] = 0;
    00224             break;
    00225           }
    00226         else
    00227           {
    00228             chrom[i] = 1;
    00229             continue;
    00230           }
    00231
    00232     return true;
    00233     }
    00234 };
    00235
    00236
    00242 template<class Chrom> class eo1PtBitXover: public eoQuadOp<Chrom>
    00243 {
    00244  public:
    00246   virtual std::string className() const { return "eo1PtBitXover"; }
    00247
    00253   bool operator()(Chrom& chrom1, Chrom& chrom2)
    00254     {
    00255       unsigned site = eo::rng.random(std::min(chrom1.size(), chrom2.size()));
    00256
    00257       if (!std::equal(chrom1.begin(), chrom1.begin()+site, chrom2.begin()))
    00258       {
    00259
    00260         std::swap_ranges(chrom1.begin(), chrom1.begin() + site, chrom2.begin());
    00261
    00262         return true;
    00263       }
    00264       return false;
    00265   }
    00266 };
    00267
    00268
    00274 template<class Chrom> class eoUBitXover: public eoQuadOp<Chrom>
    00275 {
    00276  public:
    00278   eoUBitXover(const float& _preference = 0.5): preference(_preference)
    00279     {
    00280       if ( (_preference <= 0.0) || (_preference >= 1.0) )
    00281         std::runtime_error("UxOver --> invalid preference");
    00282     }
    00284   virtual std::string className() const { return "eoUBitXover"; }
    00285
    00292   bool operator()(Chrom& chrom1, Chrom& chrom2)
    00293     {
    00294       if ( chrom1.size() != chrom2.size())
    00295             std::runtime_error("UxOver --> chromosomes sizes don't match" );
    00296       bool changed = false;
    00297       for (unsigned int i=0; i<chrom1.size(); i++)
    00298         {
    00299           if (chrom1[i] != chrom2[i] && eo::rng.flip(preference))
    00300             {
    00301               bool tmp = chrom1[i];
    00302               chrom1[i]=chrom2[i];
    00303               chrom2[i] = tmp;
    00304               changed = true;
    00305             }
    00306         }
    00307     return changed;
    00308   }
    00309     private:
    00310       float preference;
    00311 };
    00312
    00313
    00319 template<class Chrom> class eoNPtsBitXover: public eoQuadOp<Chrom>
    00320 {
    00321  public:
    00323   eoNPtsBitXover(const unsigned& _num_points = 2): num_points(_num_points)
    00324     {
    00325       if (num_points < 1)
    00326         std::runtime_error("NxOver --> invalid number of points");
    00327     }
    00328
    00330   virtual std::string className() const { return "eoNPtsBitXover"; }
    00331
    00337   bool operator()(Chrom& chrom1, Chrom& chrom2)
    00338     {
    00339       unsigned max_size = std::min(chrom1.size(), chrom2.size());
    00340       unsigned max_points = std::min(max_size - 1, num_points);
    00341
    00342       std::vector<bool> points(max_size, false);
    00343
    00344       // select ranges of bits to swap
    00345       do {
    00346         unsigned bit = eo::rng.random(max_size) + 1;
    00347         if (points[bit])
    00348           continue;
    00349         else
    00350           {
    00351             points[bit] = true;
    00352             max_points--;
    00353           }
    00354       } while (max_points);
    00355
    00356
    00357       // swap bits between chromosomes
    00358       bool change = false;
    00359       for (unsigned bit = 1; bit < points.size(); bit++)
    00360         {
    00361           if (points[bit])
    00362             change = !change;
    00363
    00364           if (change)
    00365           {
    00366                 typename Chrom::AtomType tmp= chrom1[bit];
    00367                 chrom1[bit] = chrom2[bit];
    00368                 chrom2[bit] = tmp;
    00369           }
    00370         }
    00371
    00372     return true;
    00373     }
    00374
    00375  private:
    00376   unsigned num_points;
    00377 };
    00378
    00379
    00380
    00388 template<class Chrom> class eoBitGxOver: public eoQuadOp<Chrom>
    00389 {
    00390  public:
    00392   eoBitGxOver(const unsigned _gene_size, const unsigned _num_points = 2):
    00393     gene_size(_gene_size), num_points(_num_points)
    00394     {
    00395       if (gene_size < 1)
    00396         std::runtime_error("GxOver --> invalid gene size");
    00397       if (num_points < 1)
    00398         std::runtime_error("GxOver --> invalid number of points");
    00399     }
    00400
    00402   virtual std::string className() const { return "eoBitGxOver"; }
    00403
    00409   bool operator()(Chrom& chrom1, Chrom& chrom2)
    00410     {
    00411       unsigned max_genes = std::min(chrom1.size(), chrom2.size()) / gene_size;
    00412       unsigned cut_genes = std::min(max_genes, num_points);
    00413
    00414       std::vector<bool> points(max_genes, false);
    00415
    00416       // selects genes to swap
    00417       do {
    00418         unsigned bit = eo::rng.random(max_genes);
    00419         if (points[bit])
    00420           continue;
    00421         else
    00422           {
    00423             points[bit] = true;
    00424             cut_genes--;
    00425           }
    00426       } while (cut_genes);
    00427
    00428       // swaps genes
    00429       for (unsigned i = 0; i < points.size(); i++)
    00430         if (points[i])
    00431           std::swap_ranges(chrom1.begin() + i * gene_size,
    00432                       chrom1.begin() + i * gene_size + gene_size,
    00433                       chrom2.begin() + i * gene_size);
    00434
    00435     return true;
    00436   }
    00437
    00438  private:
    00439   unsigned gene_size;
    00440   unsigned num_points;
    00441 };
    00442
    00443
    00444
    00445 //-----------------------------------------------------------------------------
    00447 #endif
    00448