00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef MOEONORMALIZEDSOLUTIONVSSOLUTIONBINARYMETRIC_H_
00014 #define MOEONORMALIZEDSOLUTIONVSSOLUTIONBINARYMETRIC_H_
00015
00016 #include <stdexcept>
00017 #include <metric/moeoMetric.h>
00018
00019
00025 template < class ObjectiveVector, class R >
00026 class moeoNormalizedSolutionVsSolutionBinaryMetric : public moeoSolutionVsSolutionBinaryMetric < ObjectiveVector, R >
00027 {
00028 public:
00029
00033 moeoNormalizedSolutionVsSolutionBinaryMetric()
00034 {
00035 bounds.resize(ObjectiveVector::Traits::nObjectives());
00036 }
00037
00038
00045 void setup(double _min, double _max, unsigned _obj)
00046 {
00047 if (_min == _max)
00048 {
00049 _min -= tiny();
00050 _max += tiny();
00051 }
00052 bounds[_obj] = eoRealInterval(_min, _max);
00053 }
00054
00060 virtual void setup(eoRealInterval _realInterval, unsigned _obj)
00061 {
00062 bounds[_obj] = _realInterval;
00063 }
00064
00065
00069 static double tiny()
00070 {
00071 return 1e-6;
00072 }
00073
00074
00075 protected:
00076
00078 std::vector < eoRealInterval > bounds;
00079
00080 };
00081
00082
00088 template < class ObjectiveVector >
00089 class moeoAdditiveEpsilonBinaryMetric : public moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double >
00090 {
00091 public:
00092
00100 double operator()(const ObjectiveVector & _o1, const ObjectiveVector & _o2)
00101 {
00102
00103 double result = epsilon(_o1, _o2, 0);
00104
00105 double tmp;
00106 for (unsigned i=1; i<ObjectiveVector::Traits::nObjectives(); i++)
00107 {
00108 tmp = epsilon(_o1, _o2, i);
00109 result = std::max(result, tmp);
00110 }
00111
00112 return result;
00113 }
00114
00115
00116 private:
00117
00119 using moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > :: bounds;
00120
00121
00129 double epsilon(const ObjectiveVector & _o1, const ObjectiveVector & _o2, const unsigned _obj)
00130 {
00131 double result;
00132
00133 if (ObjectiveVector::Traits::minimizing(_obj))
00134 {
00135
00136 result = ( (_o1[_obj] - bounds[_obj].minimum()) / bounds[_obj].range() ) - ( (_o2[_obj] - bounds[_obj].minimum()) / bounds[_obj].range() );
00137 }
00138
00139 else
00140 {
00141
00142 result = ( (_o2[_obj] - bounds[_obj].minimum()) / bounds[_obj].range() ) - ( (_o1[_obj] - bounds[_obj].minimum()) / bounds[_obj].range() );
00143 }
00144 return result;
00145 }
00146
00147 };
00148
00149
00158 template < class ObjectiveVector >
00159 class moeoHypervolumeBinaryMetric : public moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double >
00160 {
00161 public:
00162
00167 moeoHypervolumeBinaryMetric(double _rho = 1.1) : rho(_rho)
00168 {
00169
00170 for (unsigned i=0; i<ObjectiveVector::Traits::nObjectives(); i++)
00171 {
00172 if (ObjectiveVector::Traits::maximizing(i))
00173 {
00174 throw std::runtime_error("Hypervolume binary metric not yet implemented for a maximization problem in moeoHypervolumeBinaryMetric");
00175 }
00176 }
00177
00178 if (rho < 1)
00179 {
00180 cout << "Warning, value used to compute the reference point rho for the hypervolume calculation must not be smaller than 1" << endl;
00181 cout << "Adjusted to 1" << endl;
00182 rho = 1;
00183 }
00184 }
00185
00186
00193 double operator()(const ObjectiveVector & _o1, const ObjectiveVector & _o2)
00194 {
00195 double result;
00196
00197 if ( paretoComparator(_o1,_o2) )
00198 {
00199 result = - hypervolume(_o1, _o2, ObjectiveVector::Traits::nObjectives()-1);
00200 }
00201 else
00202 {
00203 result = hypervolume(_o2, _o1, ObjectiveVector::Traits::nObjectives()-1);
00204 }
00205 return result;
00206 }
00207
00208
00209 private:
00210
00212 double rho;
00214 using moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > :: bounds;
00216 moeoParetoObjectiveVectorComparator < ObjectiveVector > paretoComparator;
00217
00225 double hypervolume(const ObjectiveVector & _o1, const ObjectiveVector & _o2, const unsigned _obj, const bool _flag = false)
00226 {
00227 double result;
00228 double range = rho * bounds[_obj].range();
00229 double max = bounds[_obj].minimum() + range;
00230
00231 double v1 = _o1[_obj];
00232
00233 double v2;
00234 if (_flag)
00235 {
00236 v2 = max;
00237 }
00238 else
00239 {
00240 v2 = _o2[_obj];
00241 }
00242
00243 if (_obj == 0)
00244 {
00245 if (v1 < v2)
00246 {
00247 result = (v2 - v1) / range;
00248 }
00249 else
00250 {
00251 result = 0;
00252 }
00253 }
00254 else
00255 {
00256 if (v1 < v2)
00257 {
00258 result = ( hypervolume(_o1, _o2, _obj-1, true) * (v2 - v1) / range ) + ( hypervolume(_o1, _o2, _obj-1) * (max - v2) / range );
00259 }
00260 else
00261 {
00262 result = hypervolume(_o1, _o2, _obj-1) * (max - v2) / range;
00263 }
00264 }
00265 return result;
00266 }
00267
00268 };
00269
00270
00271 #endif