From df4db4d623b0ca63da20e30097b2ce8c5e42630f Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Tue, 11 Jun 2013 13:29:57 +0200 Subject: [PATCH] Add hyper volume continuators & metrics handling feasibility constraint on objectives --- moeo/src/continue/moeoHypContinue.h | 119 +++++++++++++- ...inaryIndicatorBasedDualFitnessAssignment.h | 27 +++- ...ExpBinaryIndicatorBasedFitnessAssignment.h | 2 +- .../metric/moeoHyperVolumeDifferenceMetric.h | 153 ++++++++++++++---- 4 files changed, 258 insertions(+), 43 deletions(-) diff --git a/moeo/src/continue/moeoHypContinue.h b/moeo/src/continue/moeoHypContinue.h index 85be8281e..f6fbac34a 100644 --- a/moeo/src/continue/moeoHypContinue.h +++ b/moeo/src/continue/moeoHypContinue.h @@ -46,11 +46,11 @@ #include /** - Continues until the optimum ParetoSet level is reached. + Continues until the given ParetoSet level is reached. @ingroup Continuators */ -template< class MOEOT> +template< class MOEOT, class MetricT = moeoHyperVolumeDifferenceMetric > class moeoHypContinue: public eoContinue { public: @@ -71,8 +71,20 @@ public: vectorToParetoSet(_OptimVec); } + /** Returns false when a ParetoSet is reached. */ virtual bool operator() ( const eoPop& _pop ) + { + std::vector bestCurrentParetoSet = pareto( arch ); + + return is_null_hypervolume( bestCurrentParetoSet ); + } + + virtual std::string className(void) const { return "moeoHypContinue"; } + +protected: + + std::vector pareto( moeoArchive & _archive ) { std::vector < ObjectiveVector > bestCurrentParetoSet; @@ -80,7 +92,12 @@ public: bestCurrentParetoSet.push_back(arch[i].objectiveVector()); } - double hypervolume= metric(bestCurrentParetoSet,OptimSet ); + return bestCurrentParetoSet; + } + + bool is_null_hypervolume( std::vector& bestCurrentParetoSet ) + { + double hypervolume= metric( bestCurrentParetoSet, OptimSet ); if (hypervolume==0) { eo::log << eo::logging << "STOP in moeoHypContinue: Best ParetoSet has been reached " @@ -91,7 +108,7 @@ public: } /** Translate a vector given as param to the ParetoSet that should be reached. */ - void vectorToParetoSet(const std::vector & _OptimVec) + virtual void vectorToParetoSet(const std::vector & _OptimVec) { unsigned dim = (unsigned)(_OptimVec.size()/ObjectiveVector::Traits::nObjectives()); OptimSet.resize(dim); @@ -104,12 +121,98 @@ public: } } - virtual std::string className(void) const { return "moeoHypContinue"; } - -private: +protected: moeoArchive & arch; - moeoHyperVolumeDifferenceMetric metric; + MetricT metric; std::vector OptimSet; }; + +/** + Continues until the (feasible or unfeasible) given Pareto set is reached. + + + @ingroup Continuators + */ +template< class MOEOT, class MetricT = moeoDualHyperVolumeDifferenceMetric > +class moeoDualHypContinue: public moeoHypContinue +{ +protected: + bool is_feasible; + + using moeoHypContinue::arch; + using moeoHypContinue::OptimSet; + +public: + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename ObjectiveVector::Type AtomType; + + /** A continuator that stops once a given Pareto front has been reached + * + * You should specify the feasibility of the targeted front. + * NOTE: the MOEOT::ObjectiveVector is supposed to implement the moeoDualRealObjectiveVector interface. + * + */ + moeoDualHypContinue( const std::vector & _OptimVec, bool _is_feasible, moeoArchive < MOEOT > & _archive, bool _normalize=true, double _rho=1.1 ) + : moeoHypContinue( _OptimVec, _archive, _normalize, _rho ), is_feasible(_is_feasible) + { + assert( _OptimVec.size() > 0); + vectorToParetoSet(_OptimVec); + } + + /** A continuator that stops once a given Pareto front has been reached + * + * You should specify the feasibility of the targeted front. + * NOTE: the MOEOT::ObjectiveVector is supposed to implement the moeoDualRealObjectiveVector interface. + * + */ + moeoDualHypContinue( const std::vector & _OptimVec, bool _is_feasible, moeoArchive < MOEOT > & _archive, bool _normalize=true, ObjectiveVector& _ref_point=NULL ) + : moeoHypContinue( _OptimVec, _archive, _normalize, _ref_point ), is_feasible(_is_feasible) + { + assert( _OptimVec.size() > 0); + vectorToParetoSet(_OptimVec); + } + + /** Returns false when a ParetoSet is reached. */ + virtual bool operator() ( const eoPop& _pop ) + { + std::vector bestCurrentParetoSet = pareto( arch ); + +#ifndef NDEBUG + assert( bestCurrentParetoSet.size() > 0 ); + for( unsigned int i=1; i::pareto; + using moeoHypContinue::is_null_hypervolume; + + /** Translate a vector given as param to the ParetoSet that should be reached. */ + virtual void vectorToParetoSet(const std::vector & _OptimVec) + { + unsigned dim = (unsigned)(_OptimVec.size()/ObjectiveVector::Traits::nObjectives()); + OptimSet.resize(dim); + + unsigned k=0; + for(size_t i=0; i < dim; i++) { + for (size_t j=0; j < ObjectiveVector::Traits::nObjectives(); j++) { + // Use the feasibility declaration of an eoDualFitness + OptimSet[i][j] = AtomType(_OptimVec[k++], is_feasible); + } + } + } +}; + #endif diff --git a/moeo/src/fitness/moeoExpBinaryIndicatorBasedDualFitnessAssignment.h b/moeo/src/fitness/moeoExpBinaryIndicatorBasedDualFitnessAssignment.h index d0a0e1317..bff35769c 100644 --- a/moeo/src/fitness/moeoExpBinaryIndicatorBasedDualFitnessAssignment.h +++ b/moeo/src/fitness/moeoExpBinaryIndicatorBasedDualFitnessAssignment.h @@ -10,6 +10,9 @@ protected: public: typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename ObjectiveVector::Type Type; + + using moeoExpBinaryIndicatorBasedFitnessAssignment::values; moeoExpBinaryIndicatorBasedDualFitnessAssignment( moeoNormalizedSolutionVsSolutionBinaryMetric & metric, @@ -54,11 +57,33 @@ public: this->setFitnesses(*ppop); } + /** + * Compute every indicator value in values (values[i] = I(_v[i], _o)) + * @param _pop the population + */ + void computeValues(const eoPop < MOEOT > & _pop) + { + values.clear(); + values.resize(_pop.size()); + for (unsigned int i=0; i<_pop.size(); i++) + { + values[i].resize(_pop.size()); + // the metric may not be symetric, thus neither is the matrix + for (unsigned int j=0; j<_pop.size(); j++) + { + if (i != j) + { + values[i][j] = Type( metric(_pop[i].objectiveVector(), _pop[j].objectiveVector()), _pop[i].objectiveVector().is_feasible() ); + } + } + } + } + virtual void setFitnesses(eoPop < MOEOT > & pop) { for (unsigned int i=0; icomputeFitness(i), pop[i].is_feasible() ); + pop[i].fitness( this->computeFitness(i), pop[i].fitness().is_feasible() ); } } diff --git a/moeo/src/fitness/moeoExpBinaryIndicatorBasedFitnessAssignment.h b/moeo/src/fitness/moeoExpBinaryIndicatorBasedFitnessAssignment.h index 7d8bb63b8..d84b052e9 100644 --- a/moeo/src/fitness/moeoExpBinaryIndicatorBasedFitnessAssignment.h +++ b/moeo/src/fitness/moeoExpBinaryIndicatorBasedFitnessAssignment.h @@ -187,7 +187,7 @@ class moeoExpBinaryIndicatorBasedFitnessAssignment : public moeoBinaryIndicatorB { if (i != j) { - values[i][j] = metric(_pop[i].objectiveVector(), _pop[j].objectiveVector()); + values[i][j] = Type( metric(_pop[i].objectiveVector(), _pop[j].objectiveVector()) ); } } } diff --git a/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h b/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h index 9d3a1c4b9..aaa899827 100644 --- a/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h +++ b/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h @@ -86,41 +86,42 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < */ double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) { - double hypervolume_set1; - double hypervolume_set2; - if(rho >= 1.0){ - //determine bounds - setup(_set1, _set2); - //determine reference point - for (unsigned int i=0; i= 1.0){ + //determine bounds + setup(_set1, _set2); + //determine reference point + for (unsigned int i=0; i unaryMetric(ref_point, bounds); - hypervolume_set1 = unaryMetric(_set1); - hypervolume_set2 = unaryMetric(_set2); + } + else if(normalize) + setup(_set1, _set2); - return hypervolume_set1 - hypervolume_set2; + moeoHyperVolumeMetric unaryMetric(ref_point, bounds); + hypervolume_set1 = unaryMetric(_set1); + hypervolume_set2 = unaryMetric(_set2); + + return hypervolume_set1 - hypervolume_set2; } /** @@ -132,7 +133,7 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < } /** - * method caclulate bounds for the normalization + * method calculate bounds for the normalization * @param _set1 the vector contains all objective Vector of the first pareto front * @param _set2 the vector contains all objective Vector of the second pareto front */ @@ -182,7 +183,7 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < return 1e-6; } - private: + protected: /*boolean indicates if data must be normalized or not*/ bool normalize; @@ -196,4 +197,90 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < }; + +template +class moeoDualHyperVolumeDifferenceMetric : public moeoHyperVolumeDifferenceMetric +{ +protected: + using moeoHyperVolumeDifferenceMetric::rho; + using moeoHyperVolumeDifferenceMetric::normalize; + using moeoHyperVolumeDifferenceMetric::ref_point; + using moeoHyperVolumeDifferenceMetric::bounds; + +public: + + typedef typename ObjectiveVector::Type Type; + + moeoDualHyperVolumeDifferenceMetric( bool _normalize=true, double _rho=1.1) + : moeoHyperVolumeDifferenceMetric(_normalize, _rho) + { + + } + + moeoDualHyperVolumeDifferenceMetric( bool _normalize/*=true*/, ObjectiveVector& _ref_point/*=NULL*/ ) + : moeoHyperVolumeDifferenceMetric( _normalize, _ref_point ) + { + + } + + /** + * calculates and returns the HyperVolume value of a pareto front + * @param _set1 the vector contains all objective Vector of the first pareto front + * @param _set2 the vector contains all objective Vector of the second pareto front + */ + double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) + { +#ifndef NDEBUG + // the two sets must be homogeneous in feasibility + assert( _set1.size() > 0 ); + for( unsigned int i=1; i<_set1.size(); ++i ) { + assert( _set1[i].is_feasible() == _set1[0].is_feasible() ); + } + assert( _set2.size() > 0 ); + for( unsigned int i=1; i<_set2.size(); ++i ) { + assert( _set2[i].is_feasible() == _set2[0].is_feasible() ); + } + // and they must have the same feasibility + assert( _set1[0].is_feasible() == _set2[0].is_feasible() ); +#endif + bool feasible = _set1[0].is_feasible(); + + double hypervolume_set1; + double hypervolume_set2; + + if(rho >= 1.0){ + //determine bounds + setup(_set1, _set2); + //determine reference point + for (unsigned int i=0; i unaryMetric(ref_point, bounds); + hypervolume_set1 = unaryMetric(_set1); + hypervolume_set2 = unaryMetric(_set2); + + return hypervolume_set1 - hypervolume_set2; + } +}; + #endif /*MOEOHYPERVOLUMEMETRIC_H_*/