00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef MOEOHYPERVOLUMEBINARYMETRIC_H_
00014 #define MOEOHYPERVOLUMEBINARYMETRIC_H_
00015
00016 #include <stdexcept>
00017 #include <comparator/moeoParetoObjectiveVectorComparator.h>
00018 #include <metric/moeoNormalizedSolutionVsSolutionBinaryMetric.h>
00019
00028 template < class ObjectiveVector >
00029 class moeoHypervolumeBinaryMetric : public moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double >
00030 {
00031 public:
00032
00037 moeoHypervolumeBinaryMetric(double _rho = 1.1) : rho(_rho)
00038 {
00039
00040 for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++)
00041 {
00042 if (ObjectiveVector::Traits::maximizing(i))
00043 {
00044 throw std::runtime_error("Hypervolume binary metric not yet implemented for a maximization problem in moeoHypervolumeBinaryMetric");
00045 }
00046 }
00047
00048 if (rho < 1)
00049 {
00050 std::cout << "Warning, value used to compute the reference point rho for the hypervolume calculation must not be smaller than 1" << std::endl;
00051 std::cout << "Adjusted to 1" << std::endl;
00052 rho = 1;
00053 }
00054 }
00055
00056
00063 double operator()(const ObjectiveVector & _o1, const ObjectiveVector & _o2)
00064 {
00065 double result;
00066
00067 if ( paretoComparator(_o2,_o1) )
00068 {
00069 result = - hypervolume(_o1, _o2, ObjectiveVector::Traits::nObjectives()-1);
00070 }
00071 else
00072 {
00073 result = hypervolume(_o2, _o1, ObjectiveVector::Traits::nObjectives()-1);
00074 }
00075 return result;
00076 }
00077
00078
00079 private:
00080
00082 double rho;
00084 using moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > :: bounds;
00086 moeoParetoObjectiveVectorComparator < ObjectiveVector > paretoComparator;
00087
00088
00096 double hypervolume(const ObjectiveVector & _o1, const ObjectiveVector & _o2, const unsigned int _obj, const bool _flag = false)
00097 {
00098 double result;
00099 double range = rho * bounds[_obj].range();
00100 double max = bounds[_obj].minimum() + range;
00101
00102 double v1 = _o1[_obj];
00103
00104 double v2;
00105 if (_flag)
00106 {
00107 v2 = max;
00108 }
00109 else
00110 {
00111 v2 = _o2[_obj];
00112 }
00113
00114 if (_obj == 0)
00115 {
00116 if (v1 < v2)
00117 {
00118 result = (v2 - v1) / range;
00119 }
00120 else
00121 {
00122 result = 0;
00123 }
00124 }
00125 else
00126 {
00127 if (v1 < v2)
00128 {
00129 result = ( hypervolume(_o1, _o2, _obj-1, true) * (v2 - v1) / range ) + ( hypervolume(_o1, _o2, _obj-1) * (max - v2) / range );
00130 }
00131 else
00132 {
00133 result = hypervolume(_o1, _o2, _obj-1) * (max - v2) / range;
00134 }
00135 }
00136 return result;
00137 }
00138
00139 };
00140
00141 #endif