00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _moeoBinaryQualityIndicator_h
00014 #define _moeoBinaryQualityIndicator_h
00015
00016
00017 #include <stdexcept>
00018
00019 #include <eoFunctor.h>
00020
00021
00028 template < class EOFitness > class moeoBinaryQualityIndicator:public eoBF < const EOFitness &, const EOFitness &,
00029 double >
00030 {
00031
00032 public:
00033
00037 moeoBinaryQualityIndicator ():eoBF < const EOFitness &, const EOFitness &,
00038 double >()
00039 {
00040 bounds.reserve (traits::nObjectives ());
00041 bounds.resize (traits::nObjectives ());
00042 }
00043
00044
00051 void setBounds (const unsigned _iObj, const double _min, const double _max)
00052 {
00053 bounds[_iObj] = Range (_min, _max);
00054 }
00055
00056
00057 protected:
00058
00062 class Range
00063 {
00064 public:
00065 Range ()
00066 {
00067 min = 0;
00068 max = 0;
00069 r = 0;
00070 }
00071 Range (const double _min, const double _max)
00072 {
00073 min = _min;
00074 max = _max;
00075 r = max - min;
00076 if (r < 0)
00077 throw std::logic_error ("Negative range in eoBinaryQualityIndicator");
00078 }
00079 double minimum ()
00080 {
00081 return min;
00082 }
00083 double maximum ()
00084 {
00085 return max;
00086 }
00087 double range ()
00088 {
00089 return r;
00090 }
00091 private:
00092 double min, max, r;
00093 };
00094
00095
00097 std::vector < Range > bounds;
00098
00099
00100 private:
00101
00103 typedef typename EOFitness::fitness_traits traits;
00104
00105 };
00106
00107
00108
00109
00110
00115 template < class EOFitness > class moeoAdditiveBinaryEpsilonIndicator:public moeoBinaryQualityIndicator <
00116 EOFitness
00117 >
00118 {
00119
00120 public:
00121
00125 moeoAdditiveBinaryEpsilonIndicator ():moeoBinaryQualityIndicator < EOFitness >
00126 ()
00127 {
00128 }
00129
00130
00138 double operator () (const EOFitness & _fitness_eo1,
00139 const EOFitness & _fitness_eo2)
00140 {
00141 double epsilon, tmp;
00142
00143 epsilon = epsilonValue (_fitness_eo1, _fitness_eo2, 0);
00144
00145 for (unsigned i = 1; i < traits::nObjectives (); i++)
00146 {
00147 tmp = epsilonValue (_fitness_eo1, _fitness_eo2, i);
00148 epsilon = std::max (epsilon, tmp);
00149 }
00150
00151 return epsilon;
00152 }
00153
00154
00155 private:
00156
00158 typedef typename EOFitness::fitness_traits traits;
00160 using moeoBinaryQualityIndicator < EOFitness >::bounds;
00161
00162
00170 double epsilonValue (const EOFitness & _fitness_eo1,
00171 const EOFitness & _fitness_eo2, const unsigned _iObj)
00172 {
00173 double result;
00174 if (bounds[_iObj].range () == 0)
00175 {
00176
00177 result = 0;
00178 }
00179 else
00180 {
00181
00182 result =
00183 (_fitness_eo1[_iObj] -
00184 bounds[_iObj].minimum ()) / bounds[_iObj].range ();
00185 result -=
00186 (_fitness_eo2[_iObj] -
00187 bounds[_iObj].minimum ()) / bounds[_iObj].range ();
00188
00189 if (traits::maximizing (_iObj))
00190 result = -result;
00191 }
00192
00193 return result;
00194 }
00195
00196 };
00197
00198
00199
00200
00201
00206 template < class EOFitness > class moeoBinaryHypervolumeIndicator:public moeoBinaryQualityIndicator <
00207 EOFitness >
00208 {
00209
00210 public:
00211
00216 moeoBinaryHypervolumeIndicator (double _rho):moeoBinaryQualityIndicator < EOFitness >
00217 ()
00218 {
00219 rho = _rho;
00220
00221 if (rho < 1)
00222 {
00223 cout <<
00224 "Warning, reference point rho for the hypervolume calculation must not be smaller than 1"
00225 << endl;
00226 cout << "Adjusted to 1" << endl;
00227 rho = 1;
00228 }
00229 }
00230
00231
00239 double operator () (const EOFitness & _fitness_eo1,
00240 const EOFitness & _fitness_eo2)
00241 {
00242 double result;
00243 if (_fitness_eo1.dominates (_fitness_eo2))
00244 result =
00245 -hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00246 traits::nObjectives ());
00247 else
00248 result =
00249 hypervolumeIndicatorValue (_fitness_eo2, _fitness_eo1,
00250 traits::nObjectives ());
00251 return result;
00252 }
00253
00254
00255 private:
00256
00258 typedef typename EOFitness::fitness_traits traits;
00260 using moeoBinaryQualityIndicator < EOFitness >::bounds;
00261
00263 double rho;
00264
00265
00274 double hypervolumeIndicatorValue (const EOFitness & _fitness_eo1,
00275 const EOFitness & _fitness_eo2,
00276 const unsigned _iObj, const bool _flag =
00277 false)
00278 {
00279 double result;
00280 if (bounds[_iObj - 1].range () == 0)
00281 {
00282
00283 result = 0;
00284 }
00285 else
00286 {
00287 if (traits::maximizing (_iObj - 1))
00288 result =
00289 hypervolumeIndicatorValueMax (_fitness_eo1, _fitness_eo2, _iObj,
00290 _flag);
00291 else
00292 result =
00293 hypervolumeIndicatorValueMin (_fitness_eo1, _fitness_eo2, _iObj,
00294 _flag);
00295 }
00296 return result;
00297 }
00298
00299
00309 double hypervolumeIndicatorValueMin (const EOFitness & _fitness_eo1,
00310 const EOFitness & _fitness_eo2,
00311 const unsigned _iObj, const bool _flag)
00312 {
00313 double result;
00314 double r = rho * bounds[_iObj - 1].range ();
00315 double max = bounds[_iObj - 1].minimum () + r;
00316
00317 double fitness_eo1 = _fitness_eo1[_iObj - 1];
00318 double fitness_eo2;
00319 if (_flag)
00320 fitness_eo2 = max;
00321 else
00322 fitness_eo2 = _fitness_eo2[_iObj - 1];
00323
00324 if (_iObj == 1)
00325 {
00326 if (fitness_eo1 < fitness_eo2)
00327 result = (fitness_eo2 - fitness_eo1) / r;
00328 else
00329 result = 0;
00330 }
00331 else
00332 {
00333 if (fitness_eo1 < fitness_eo2)
00334 {
00335 result =
00336 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00337 _iObj - 1) * (max - fitness_eo2) / r;
00338 result +=
00339 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00340 _iObj - 1,
00341 true) * (fitness_eo2 -
00342 fitness_eo1) / r;
00343 }
00344 else
00345 result =
00346 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00347 _iObj - 1) * (max - fitness_eo2) / r;
00348 }
00349
00350 return result;
00351 }
00352
00353
00363 double hypervolumeIndicatorValueMax (const EOFitness & _fitness_eo1,
00364 const EOFitness & _fitness_eo2,
00365 const unsigned _iObj, const bool _flag)
00366 {
00367 double result;
00368 double r = rho * bounds[_iObj - 1].range ();
00369 double min = bounds[_iObj - 1].maximum () - r;
00370
00371 double fitness_eo1 = _fitness_eo1[_iObj - 1];
00372 double fitness_eo2;
00373 if (_flag)
00374 fitness_eo2 = min;
00375 else
00376 fitness_eo2 = _fitness_eo2[_iObj - 1];
00377
00378 if (_iObj == 1)
00379 {
00380 if (fitness_eo1 > fitness_eo2)
00381 result = (fitness_eo1 - fitness_eo2) / r;
00382 else
00383 result = 0;
00384 }
00385 else
00386 {
00387 if (fitness_eo1 > fitness_eo2)
00388 {
00389 result =
00390 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00391 _iObj - 1) * (fitness_eo2 - min) / r;
00392 result +=
00393 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00394 _iObj - 1,
00395 true) * (fitness_eo1 -
00396 fitness_eo2) / r;
00397 }
00398 else
00399 result =
00400 hypervolumeIndicatorValue (_fitness_eo1, _fitness_eo2,
00401 _iObj - 1) * (fitness_eo2 - min) / r;
00402 }
00403
00404 return result;
00405 }
00406
00407 };
00408
00409 #endif