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 
00048 template<class EOT> class eoNormalVecMutation: public eoMonOp<EOT>
00049 {
00050  public:
00058   eoNormalVecMutation(double _sigma, const double& _p_change = 1.0):
00059     sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
00060 
00069   eoNormalVecMutation(eoRealVectorBounds & _bounds,
00070                     double _sigma, const double& _p_change = 1.0):
00071     sigma(_bounds.size(), _sigma), bounds(_bounds), p_change(_p_change)
00072   {
00073     // scale to the range - if any
00074     for (unsigned i=0; i<bounds.size(); i++)
00075       if (bounds.isBounded(i))
00076           sigma[i] *= _sigma*bounds.range(i);
00077   }
00078 
00080   virtual std::string className() const { return "eoNormalVecMutation"; }
00081 
00086   bool operator()(EOT& _eo)
00087     {
00088       bool hasChanged=false;
00089       for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00090         {
00091           if (rng.flip(p_change))
00092             {
00093               _eo[lieu] += sigma[lieu]*rng.normal();
00094               bounds.foldsInBounds(lieu, _eo[lieu]);
00095               hasChanged = true;
00096             }
00097         }
00098       return hasChanged;
00099     }
00100 
00101 private:
00102   std::vector<double> sigma;
00103   eoRealVectorBounds & bounds;
00104   double p_change;
00105 };
00106 
00116 template<class EOT> class eoNormalMutation
00117     : public eoMonOp<EOT>
00118 {
00119 public:
00127   eoNormalMutation(double & _sigma, const double& _p_change = 1.0):
00128     sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
00129 
00136   eoNormalMutation(eoRealVectorBounds & _bounds,
00137                     double _sigma, const double& _p_change = 1.0):
00138     sigma(_sigma), bounds(_bounds), p_change(_p_change) {}
00139 
00141   virtual std::string className() const { return "eoNormalMutation"; }
00142 
00147   bool operator()(EOT& _eo)
00148     {
00149       bool hasChanged=false;
00150       for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00151         {
00152           if (rng.flip(p_change))
00153             {
00154               _eo[lieu] += sigma*rng.normal();
00155               bounds.foldsInBounds(lieu, _eo[lieu]);
00156               hasChanged = true;
00157             }
00158         }
00159       return hasChanged;
00160     }
00161 
00163   double & Sigma() {return sigma;}
00164 
00165 private:
00166   double & sigma;
00167   eoRealVectorBounds & bounds;
00168   double p_change;
00169 };
00170 
00177 template<class EOT> class eoOneFifthMutation :
00178   public eoNormalMutation<EOT>, public eoUpdatable
00179 {
00180 public:
00181 
00182     using eoNormalMutation< EOT >::Sigma;
00183 
00184     typedef typename EOT::Fitness Fitness;
00185 
00195   eoOneFifthMutation(eoEvalFunc<EOT> & _eval, double & _sigmaInit,
00196                      unsigned _windowSize = 10, double _updateFactor=0.83,
00197                      double _threshold=0.2):
00198     eoNormalMutation<EOT>(_sigmaInit), eval(_eval),
00199     threshold(_threshold), updateFactor(_updateFactor),
00200     nbMut(_windowSize, 0), nbSuccess(_windowSize, 0), genIndex(0)
00201   {
00202     // minimal check
00203     if (updateFactor>=1)
00204       throw std::runtime_error("Update factor must be < 1 in eoOneFifthMutation");
00205   }
00206 
00208   virtual std::string className() const { return "eoOneFifthMutation"; }
00209 
00216   bool operator()(EOT & _eo)
00217     {
00218       if (_eo.invalid())           // due to some crossover???
00219         eval(_eo);
00220       Fitness oldFitness = _eo.fitness(); // save old fitness
00221 
00222       // call standard operator - then count the successes
00223       if (eoNormalMutation<EOT>::operator()(_eo)) // _eo has been modified
00224         {
00225           _eo.invalidate();        // don't forget!!!
00226           nbMut[genIndex]++;
00227           eval(_eo);               // compute fitness of offspring
00228 
00229           if (_eo.fitness() > oldFitness)
00230             nbSuccess[genIndex]++;          // update counter
00231         }
00232       return false;                // because eval has reset the validity flag
00233     }
00234 
00238   void update()
00239   {
00240     unsigned totalMut = 0;
00241     unsigned totalSuccess = 0;
00242     // compute the average stats over the time window
00243     for ( unsigned i=0; i<nbMut.size(); i++)
00244       {
00245         totalMut += nbMut[i];
00246         totalSuccess += nbSuccess[i];
00247       }
00248 
00249     // update sigma accordingly
00250     double prop = double(totalSuccess) / totalMut;
00251     if (prop > threshold) {
00252       Sigma() /= updateFactor;     // increase sigma
00253     }
00254     else
00255       {
00256         Sigma() *= updateFactor;           // decrease sigma
00257       }
00258     genIndex = (genIndex+1) % nbMut.size() ;
00259     nbMut[genIndex] = nbSuccess[genIndex] = 0;
00260 
00261   }
00262 
00263 private:
00264   eoEvalFunc<EOT> & eval;
00265   double threshold;                // 1/5 !
00266   double updateFactor ;            // the multiplicative factor
00267   std::vector<unsigned> nbMut;     // total number of mutations per gen
00268   std::vector<unsigned> nbSuccess;         // number of successful mutations per gen
00269   unsigned genIndex ;              // current index in std::vectors (circular)
00270 };
00271 
00272 
00273 //-----------------------------------------------------------------------------
00275 #endif
00276 

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