00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef eoRealOp_h
00027 #define eoRealOp_h
00028
00029
00030
00031 #include <algorithm>
00032 #include <utils/eoRNG.h>
00033 #include <es/eoReal.h>
00034 #include <utils/eoRealVectorBounds.h>
00035
00036
00037
00045 template<class EOT> class eoUniformMutation: public eoMonOp<EOT>
00046 {
00047 public:
00056 eoUniformMutation(const double& _epsilon, const double& _p_change = 1.0):
00057 homogeneous(true), bounds(eoDummyVectorNoBounds), epsilon(1, _epsilon),
00058 p_change(1, _p_change) {}
00059
00066 eoUniformMutation(eoRealVectorBounds & _bounds,
00067 const double& _epsilon, const double& _p_change = 1.0):
00068 homogeneous(false), bounds(_bounds), epsilon(_bounds.size(), _epsilon),
00069 p_change(_bounds.size(), _p_change)
00070 {
00071
00072 for (unsigned i=0; i<bounds.size(); i++)
00073 if (bounds.isBounded(i))
00074 epsilon[i] *= _epsilon*bounds.range(i);
00075 }
00076
00083 eoUniformMutation(eoRealVectorBounds & _bounds,
00084 const std::vector<double>& _epsilon,
00085 const std::vector<double>& _p_change):
00086 homogeneous(false), bounds(_bounds), epsilon(_epsilon),
00087 p_change(_p_change) {}
00088
00090 virtual std::string className() const { return "eoUniformMutation"; }
00091
00096 bool operator()(EOT& _eo)
00097 {
00098 bool hasChanged=false;
00099 if (homogeneous)
00100 for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00101 {
00102 if (rng.flip(p_change[0]))
00103 {
00104 _eo[lieu] += 2*epsilon[0]*rng.uniform()-epsilon[0];
00105 hasChanged = true;
00106 }
00107 }
00108 else
00109 {
00110
00111 if (_eo.size() != bounds.size())
00112 throw std::runtime_error("Invalid size of indi in eoUniformMutation");
00113
00114 for (unsigned lieu=0; lieu<_eo.size(); lieu++)
00115 if (rng.flip(p_change[lieu]))
00116 {
00117
00118 double emin = _eo[lieu]-epsilon[lieu];
00119 double emax = _eo[lieu]+epsilon[lieu];
00120 if (bounds.isMinBounded(lieu))
00121 emin = std::max(bounds.minimum(lieu), emin);
00122 if (bounds.isMaxBounded(lieu))
00123 emax = std::min(bounds.maximum(lieu), emax);
00124 _eo[lieu] = emin + (emax-emin)*rng.uniform();
00125 hasChanged = true;
00126 }
00127 }
00128 return hasChanged;
00129 }
00130
00131 private:
00132 bool homogeneous;
00133 eoRealVectorBounds & bounds;
00134 std::vector<double> epsilon;
00135 std::vector<double> p_change;
00136 };
00137
00144 template<class EOT> class eoDetUniformMutation: public eoMonOp<EOT>
00145 {
00146 public:
00154 eoDetUniformMutation(const double& _epsilon, const unsigned& _no = 1):
00155 homogeneous(true), bounds(eoDummyVectorNoBounds),
00156 epsilon(1, _epsilon), no(_no) {}
00157
00164 eoDetUniformMutation(eoRealVectorBounds & _bounds,
00165 const double& _epsilon, const unsigned& _no = 1):
00166 homogeneous(false), bounds(_bounds),
00167 epsilon(_bounds.size(), _epsilon), no(_no)
00168 {
00169
00170 for (unsigned i=0; i<bounds.size(); i++)
00171 if (bounds.isBounded(i))
00172 epsilon[i] *= _epsilon*bounds.range(i);
00173 }
00174
00181 eoDetUniformMutation(eoRealVectorBounds & _bounds,
00182 const std::vector<double>& _epsilon,
00183 const unsigned& _no = 1):
00184 homogeneous(false), bounds(_bounds), epsilon(_epsilon), no(_no)
00185 {
00186
00187 for (unsigned i=0; i<bounds.size(); i++)
00188 if (bounds.isBounded(i))
00189 epsilon[i] *= _epsilon[i]*bounds.range(i);
00190 }
00191
00193 virtual std::string className() const { return "eoDetUniformMutation"; }
00194
00199 bool operator()(EOT& _eo)
00200 {
00201 if (homogeneous)
00202 for (unsigned i=0; i<no; i++)
00203 {
00204 unsigned lieu = rng.random(_eo.size());
00205
00206 _eo[lieu] = 2*epsilon[0]*rng.uniform()-epsilon[0];
00207 }
00208 else
00209 {
00210
00211 if (_eo.size() != bounds.size())
00212 throw std::runtime_error("Invalid size of indi in eoDetUniformMutation");
00213 for (unsigned i=0; i<no; i++)
00214 {
00215 unsigned lieu = rng.random(_eo.size());
00216
00217
00218
00219 double emin = _eo[lieu]-epsilon[lieu];
00220 double emax = _eo[lieu]+epsilon[lieu];
00221 if (bounds.isMinBounded(lieu))
00222 emin = std::max(bounds.minimum(lieu), emin);
00223 if (bounds.isMaxBounded(lieu))
00224 emax = std::min(bounds.maximum(lieu), emax);
00225 _eo[lieu] = emin + (emax-emin)*rng.uniform();
00226 }
00227 }
00228 return true;
00229 }
00230
00231 private:
00232 bool homogeneous;
00233 eoRealVectorBounds & bounds;
00234 std::vector<double> epsilon;
00235 unsigned no;
00236 };
00237
00238
00239
00240
00247 template<class EOT> class eoSegmentCrossover: public eoQuadOp<EOT>
00248 {
00249 public:
00259 eoSegmentCrossover(const double& _alpha = 0.0) :
00260 bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha) {}
00261
00270 eoSegmentCrossover(eoRealVectorBounds & _bounds,
00271 const double& _alpha = 0.0) :
00272 bounds(_bounds), alpha(_alpha), range(1+2*_alpha) {}
00273
00275 virtual std::string className() const { return "eoSegmentCrossover"; }
00276
00282 bool operator()(EOT& _eo1, EOT& _eo2)
00283 {
00284 unsigned i;
00285 double r1, r2, fact;
00286 double alphaMin = -alpha;
00287 double alphaMax = 1+alpha;
00288 if (alpha == 0.0)
00289 fact = -alpha + rng.uniform(range);
00290 else
00291 {
00292 for (i=0; i<_eo1.size(); i++)
00293 {
00294 r1=_eo1[i];
00295 r2=_eo2[i];
00296 if (r1 != r2) {
00297 double rmin = std::min(r1, r2);
00298 double rmax = std::max(r1, r2);
00299 double length = rmax - rmin;
00300 if (bounds.isMinBounded(i))
00301 {
00302 alphaMin = std::max(alphaMin, (bounds.minimum(i)-rmin)/length);
00303 alphaMax = std::min(alphaMax, (rmax-bounds.minimum(i))/length);
00304 }
00305 if (bounds.isMaxBounded(i))
00306 {
00307 alphaMax = std::min(alphaMax, (bounds.maximum(i)-rmin)/length);
00308 alphaMin = std::max(alphaMin, (rmax-bounds.maximum(i))/length);
00309 }
00310 }
00311 }
00312 fact = alphaMin + (alphaMax-alphaMin)*rng.uniform();
00313 }
00314
00315 for (i=0; i<_eo1.size(); i++)
00316 {
00317 r1=_eo1[i];
00318 r2=_eo2[i];
00319 _eo1[i] = fact * r1 + (1-fact) * r2;
00320 _eo2[i] = (1-fact) * r1 + fact * r2;
00321 }
00322 return true;
00323 }
00324
00325 protected:
00326 eoRealVectorBounds & bounds;
00327 double alpha;
00328 double range;
00329 };
00330
00337 template<class EOT> class eoHypercubeCrossover: public eoQuadOp<EOT>
00338 {
00339 public:
00349 eoHypercubeCrossover(const double& _alpha = 0.0):
00350 bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha)
00351 {
00352 if (_alpha < 0)
00353 throw std::runtime_error("BLX coefficient should be positive");
00354 }
00355
00364 eoHypercubeCrossover(eoRealVectorBounds & _bounds,
00365 const double& _alpha = 0.0):
00366 bounds(_bounds), alpha(_alpha), range(1+2*_alpha)
00367 {
00368 if (_alpha < 0)
00369 throw std::runtime_error("BLX coefficient should be positive");
00370 }
00371
00373 virtual std::string className() const { return "eoHypercubeCrossover"; }
00374
00380 bool operator()(EOT& _eo1, EOT& _eo2)
00381 {
00382 bool hasChanged = false;
00383 unsigned i;
00384 double r1, r2, fact;
00385 if (alpha == 0.0)
00386 for (i=0; i<_eo1.size(); i++)
00387 {
00388 r1=_eo1[i];
00389 r2=_eo2[i];
00390 if (r1 != r2) {
00391 fact = rng.uniform(range);
00392 _eo1[i] = fact * r1 + (1-fact) * r2;
00393 _eo2[i] = (1-fact) * r1 + fact * r2;
00394 hasChanged = true;
00395 }
00396 }
00397 else
00398
00399
00400 for (i=0; i<_eo1.size(); i++)
00401 {
00402 r1=_eo1[i];
00403 r2=_eo2[i];
00404 if (r1 != r2) {
00405 double rmin = std::min(r1, r2);
00406 double rmax = std::max(r1, r2);
00407
00408
00409 double objMin = -alpha * rmax + (1+alpha) * rmin;
00410 double objMax = -alpha * rmin + (1+alpha) * rmax;
00411
00412
00413 if (bounds.isMinBounded(i))
00414 {
00415 objMin = std::max(objMin, bounds.minimum(i));
00416 }
00417 if (bounds.isMaxBounded(i))
00418 {
00419 objMax = std::min(objMax, bounds.maximum(i));
00420 }
00421
00422 double median = (objMin+objMax)/2.0;
00423
00424 double valMin = objMin + (median-objMin)*rng.uniform();
00425 double valMax = median + (objMax-median)*rng.uniform();
00426
00427 if (rng.flip(0.5))
00428 {
00429 _eo1[i] = valMin;
00430 _eo2[i] = valMax;
00431 }
00432 else
00433 {
00434 _eo1[i] = valMax;
00435 _eo2[i] = valMin;
00436 }
00437
00438 hasChanged = true;
00439 }
00440 }
00441
00442 return hasChanged;
00443 }
00444
00445 protected:
00446 eoRealVectorBounds & bounds;
00447 double alpha;
00448 double range;
00449 };
00450
00451
00457 template<class EOT> class eoRealUXover: public eoQuadOp<EOT>
00458 {
00459 public:
00464 eoRealUXover(const float& _preference = 0.5): preference(_preference)
00465 {
00466 if ( (_preference <= 0.0) || (_preference >= 1.0) )
00467 std::runtime_error("UxOver --> invalid preference");
00468 }
00469
00471 virtual std::string className() const { return "eoRealUXover"; }
00472
00479 bool operator()(EOT& _eo1, EOT& _eo2)
00480 {
00481 if ( _eo1.size() != _eo2.size())
00482 std::runtime_error("UxOver --> chromosomes sizes don't match" );
00483 bool changed = false;
00484 for (unsigned int i=0; i<_eo1.size(); i++)
00485 {
00486 if (rng.flip(preference))
00487 if (_eo1[i] != _eo2[i])
00488 {
00489 double tmp = _eo1[i];
00490 _eo1[i]=_eo2[i];
00491 _eo2[i] = tmp;
00492 changed = true;
00493 }
00494 }
00495 return changed;
00496 }
00497 private:
00498 float preference;
00499 };
00500
00501
00502
00504 #endif