EvolvingObjects
|
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