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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef MOEOHYPERVOLUMEBINARYMETRIC_H_
00039 #define MOEOHYPERVOLUMEBINARYMETRIC_H_
00040
00041 #include <stdexcept>
00042 #include <comparator/moeoParetoObjectiveVectorComparator.h>
00043 #include <metric/moeoNormalizedSolutionVsSolutionBinaryMetric.h>
00044
00053 template < class ObjectiveVector >
00054 class moeoHypervolumeBinaryMetric : public moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double >
00055 {
00056 public:
00057
00062 moeoHypervolumeBinaryMetric(double _rho = 1.1) : rho(_rho)
00063 {
00064
00065 for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++)
00066 {
00067 if (ObjectiveVector::Traits::maximizing(i))
00068 {
00069 throw std::runtime_error("Hypervolume binary metric not yet implemented for a maximization problem in moeoHypervolumeBinaryMetric");
00070 }
00071 }
00072
00073 if (rho < 1)
00074 {
00075 std::cout << "Warning, value used to compute the reference point rho for the hypervolume calculation must not be smaller than 1" << std::endl;
00076 std::cout << "Adjusted to 1" << std::endl;
00077 rho = 1;
00078 }
00079 }
00080
00081
00088 double operator()(const ObjectiveVector & _o1, const ObjectiveVector & _o2)
00089 {
00090 double result;
00091
00092 if ( paretoComparator(_o2,_o1) )
00093 {
00094 result = - hypervolume(_o1, _o2, ObjectiveVector::Traits::nObjectives()-1);
00095 }
00096 else
00097 {
00098 result = hypervolume(_o2, _o1, ObjectiveVector::Traits::nObjectives()-1);
00099 }
00100 return result;
00101 }
00102
00103
00104 private:
00105
00107 double rho;
00109 using moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > :: bounds;
00111 moeoParetoObjectiveVectorComparator < ObjectiveVector > paretoComparator;
00112
00113
00121 double hypervolume(const ObjectiveVector & _o1, const ObjectiveVector & _o2, const unsigned int _obj, const bool _flag = false)
00122 {
00123 double result;
00124 double range = rho * bounds[_obj].range();
00125 double max = bounds[_obj].minimum() + range;
00126
00127 double v1 = _o1[_obj];
00128
00129 double v2;
00130 if (_flag)
00131 {
00132 v2 = max;
00133 }
00134 else
00135 {
00136 v2 = _o2[_obj];
00137 }
00138
00139 if (_obj == 0)
00140 {
00141 if (v1 < v2)
00142 {
00143 result = (v2 - v1) / range;
00144 }
00145 else
00146 {
00147 result = 0;
00148 }
00149 }
00150 else
00151 {
00152 if (v1 < v2)
00153 {
00154 result = ( hypervolume(_o1, _o2, _obj-1, true) * (v2 - v1) / range ) + ( hypervolume(_o1, _o2, _obj-1) * (max - v2) / range );
00155 }
00156 else
00157 {
00158 result = hypervolume(_o1, _o2, _obj-1) * (max - v2) / range;
00159 }
00160 }
00161 return result;
00162 }
00163
00164 };
00165
00166 #endif