EvolvingObjects
eoNormalMutation.h
00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
00002 
00003 //-----------------------------------------------------------------------------
00004 // eoNormalMutation.h
00005 // (c) EEAAX 2001 - 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              mak@dhi.dk
00023  */
00024 //-----------------------------------------------------------------------------
00025 
00026 #ifndef eoNormalMutation_h
00027 #define eoNormalMutation_h
00028 
00029 //-----------------------------------------------------------------------------
00030 
00031 #include <algorithm>    // swap_ranges
00032 #include <utils/eoRNG.h>
00033 #include <utils/eoUpdatable.h>
00034 #include <eoEvalFunc.h>
00035 #include <es/eoReal.h>
00036 #include <utils/eoRealBounds.h>
00037 //-----------------------------------------------------------------------------
00038 
00050 template<class EOT> class eoNormalVecMutation: public eoMonOp<EOT>
00051 {
00052  public:
00060   eoNormalVecMutation(double _sigma, const double& _p_change = 1.0):
00061     sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
00062 
00071   eoNormalVecMutation(eoRealVectorBounds & _bounds,
00072                     double _sigma, const double& _p_change = 1.0):
00073     sigma(_bounds.size(), _sigma), bounds(_bounds), p_change(_p_change)
00074   {
00075     // scale to the range - if any
00076     for (unsigned i=0; i<bounds.size(); i++)
00077       if (bounds.isBounded(i))
00078           sigma[i] *= _sigma*bounds.range(i);
00079   }
00080 
00082   virtual std::string className() const { return "eoNormalVecMutation"; }
00083 
00088   bool operator()(EOT& _eo)
00089     {
00090       bool hasChanged=false;
00091       for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00092         {
00093           if (rng.flip(p_change))
00094             {
00095               _eo[lieu] += sigma[lieu]*rng.normal();
00096               bounds.foldsInBounds(lieu, _eo[lieu]);
00097               hasChanged = true;
00098             }
00099         }
00100       return hasChanged;
00101     }
00102 
00103 private:
00104   std::vector<double> sigma;
00105   eoRealVectorBounds & bounds;
00106   double p_change;
00107 };
00108 
00120 template<class EOT> class eoNormalMutation
00121     : public eoMonOp<EOT>
00122 {
00123 public:
00131   eoNormalMutation(double & _sigma, const double& _p_change = 1.0):
00132     sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
00133 
00140   eoNormalMutation(eoRealVectorBounds & _bounds,
00141                     double _sigma, const double& _p_change = 1.0):
00142     sigma(_sigma), bounds(_bounds), p_change(_p_change) {}
00143 
00145   virtual std::string className() const { return "eoNormalMutation"; }
00146 
00151   bool operator()(EOT& _eo)
00152     {
00153       bool hasChanged=false;
00154       for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00155         {
00156           if (rng.flip(p_change))
00157             {
00158               _eo[lieu] += sigma*rng.normal();
00159               bounds.foldsInBounds(lieu, _eo[lieu]);
00160               hasChanged = true;
00161             }
00162         }
00163       return hasChanged;
00164     }
00165 
00167   double & Sigma() {return sigma;}
00168 
00169 private:
00170   double & sigma;
00171   eoRealVectorBounds & bounds;
00172   double p_change;
00173 };
00174 
00183 template<class EOT> class eoOneFifthMutation :
00184   public eoNormalMutation<EOT>, public eoUpdatable
00185 {
00186 public:
00187 
00188     using eoNormalMutation< EOT >::Sigma;
00189 
00190     typedef typename EOT::Fitness Fitness;
00191 
00201   eoOneFifthMutation(eoEvalFunc<EOT> & _eval, double & _sigmaInit,
00202                      unsigned _windowSize = 10, double _updateFactor=0.83,
00203                      double _threshold=0.2):
00204     eoNormalMutation<EOT>(_sigmaInit), eval(_eval),
00205     threshold(_threshold), updateFactor(_updateFactor),
00206     nbMut(_windowSize, 0), nbSuccess(_windowSize, 0), genIndex(0)
00207   {
00208     // minimal check
00209     if (updateFactor>=1)
00210       throw std::runtime_error("Update factor must be < 1 in eoOneFifthMutation");
00211   }
00212 
00214   virtual std::string className() const { return "eoOneFifthMutation"; }
00215 
00222   bool operator()(EOT & _eo)
00223     {
00224       if (_eo.invalid())           // due to some crossover???
00225         eval(_eo);
00226       Fitness oldFitness = _eo.fitness(); // save old fitness
00227 
00228       // call standard operator - then count the successes
00229       if (eoNormalMutation<EOT>::operator()(_eo)) // _eo has been modified
00230         {
00231           _eo.invalidate();        // don't forget!!!
00232           nbMut[genIndex]++;
00233           eval(_eo);               // compute fitness of offspring
00234 
00235           if (_eo.fitness() > oldFitness)
00236             nbSuccess[genIndex]++;          // update counter
00237         }
00238       return false;                // because eval has reset the validity flag
00239     }
00240 
00244   void update()
00245   {
00246     unsigned totalMut = 0;
00247     unsigned totalSuccess = 0;
00248     // compute the average stats over the time window
00249     for ( unsigned i=0; i<nbMut.size(); i++)
00250       {
00251         totalMut += nbMut[i];
00252         totalSuccess += nbSuccess[i];
00253       }
00254 
00255     // update sigma accordingly
00256     double prop = double(totalSuccess) / totalMut;
00257     if (prop > threshold) {
00258       Sigma() /= updateFactor;     // increase sigma
00259     }
00260     else
00261       {
00262         Sigma() *= updateFactor;           // decrease sigma
00263       }
00264     genIndex = (genIndex+1) % nbMut.size() ;
00265     nbMut[genIndex] = nbSuccess[genIndex] = 0;
00266 
00267   }
00268 
00269 private:
00270   eoEvalFunc<EOT> & eval;
00271   double threshold;                // 1/5 !
00272   double updateFactor ;            // the multiplicative factor
00273   std::vector<unsigned> nbMut;     // total number of mutations per gen
00274   std::vector<unsigned> nbSuccess;         // number of successful mutations per gen
00275   unsigned genIndex ;              // current index in std::vectors (circular)
00276 };
00277 
00278 
00279 //-----------------------------------------------------------------------------
00281 #endif
 All Classes Namespaces Files Functions Variables Typedefs Friends