diff --git a/trunk/paradiseo-moeo/src/metric/moeoHyperVolumeUnaryMetric.h b/trunk/paradiseo-moeo/src/metric/moeoHyperVolumeUnaryMetric.h new file mode 100644 index 000000000..74e43a50c --- /dev/null +++ b/trunk/paradiseo-moeo/src/metric/moeoHyperVolumeUnaryMetric.h @@ -0,0 +1,286 @@ +/* +* +* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2007 +* (C) OPAC Team, LIFL, 2002-2007 +* +* Jeremie Humeau +* Arnaud Liefooghe +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +* +* ParadisEO WebSite : http://paradiseo.gforge.inria.fr +* Contact: paradiseo-help@lists.gforge.inria.fr +* +*/ +//----------------------------------------------------------------------------- + +#ifndef MOEOHYPERVOLUMEUNARYMETRIC_H_ +#define MOEOHYPERVOLUMEUNARYMETRIC_H_ + +#include + +/** + * The contribution metric evaluates the proportion of non-dominated solutions given by a Pareto set relatively to another Pareto set + * (Meunier, Talbi, Reininger: 'A multiobjective genetic algorithm for radio network optimization', in Proc. of the 2000 Congress on Evolutionary Computation, IEEE Press, pp. 317-324) + */ +template < class ObjectiveVector > +class moeoHyperVolumeUnaryMetric : public moeoVectorUnaryMetric < ObjectiveVector , double > + { + public: + + /** + * Default Construtcor + * @param _normalize allow to normalize data (default true) + */ + moeoHyperVolumeUnaryMetric(bool _normalize=true, double _rho=1.1): normalize(_normalize), rho(_rho){ + bounds.resize(ObjectiveVector::Traits::nObjectives()); + // initialize bounds in case someone does not want to use them + for (unsigned int i=0; i & _set) + { + return 0.0; + } + + std::vector < eoRealInterval > getBounds(){ + return bounds; + } + + /** + * method caclulate bounds for the normalization + * @param _set the vector of objective vectors + */ + void setup(const std::vector < ObjectiveVector > & _set){ + if(_set.size() < 1) + throw("Error in moeoHyperVolumeUnaryMetric::setup -> argument1: vector size must be greater than 0"); + else{ + double min, max; + unsigned int nbObj=ObjectiveVector::Traits::nObjectives(); + bounds.resize(nbObj); + for (unsigned int i=0; i& _point1, std::vector& _point2, unsigned int _no_objectives){ + unsigned int i; + bool better_in_any_objective = false; + bool worse_in_any_objective = false; + + for(i=0; i < _no_objectives && !worse_in_any_objective; i++){ + if(_point1[i] > _point2[i]) + better_in_any_objective = true; + else if(_point1[i] < _point2[i]) + worse_in_any_objective = true; + } + //_point1 dominates _point2 if it is better than _point2 on a objective and if it is never worse in any other objectives + return(!worse_in_any_objective && better_in_any_objective); + + } + + /** + * swap two elements of a vector + * @param _front the vector + * @param _i index of the first element to swap + * @param _j index of the second element to swap + */ + void swap(std::vector< std::vector >& _front, unsigned int _i, unsigned int _j){ + _front.push_back(_front[_i]); + _front[_i]= _front[_j]; + _front[_j]=_front.back(); + _front.pop_back(); + } + + + /** + * collect all nondominated points regarding the first '_no_objectives' objectives (dominated points are stored at the end of _front) + * @param _front the front + * @param _no_points the number of points of the front to consider (index 0 to _no_points are considered) + * @param _no_objectives the number of objective to consider + * @return the index of the last nondominated point + */ + unsigned int filter_nondominated_set( std::vector < std::vector< double > >& _front, unsigned int _no_points, unsigned int _no_objectives){ + unsigned int i,j,n; + + n=_no_points; + i=0; + while(i < n){ + j=i+1; + while(j < n){ + //if a point 'A' (index i) dominates another one 'B' (index j), swap 'B' with the point of index n-1 + if( dominates(_front[i], _front[j], _no_objectives)){ + n--; + swap(_front, j, n); + } + //if a point 'B'(index j) dominates another one 'A' (index i), swap 'A' with the point of index n-1 + else if( dominates(_front[j], _front[i], _no_objectives)){ + n--; + swap(_front, i, n); + i--; + break; + } + else + j++; + } + i++; + } + return n; + } + + /** + * @param _front the front + * @param _no_points the number of points of the front to consider (index 0 to _no_points are considered) + * @param _objective the objective to consider + * @return the minimum value regarding dimension '_objective' consider points O to _no_points in '_front' + */ + double surface_unchanged_to(std::vector < std::vector< double > >& _front, unsigned int _no_points, unsigned int _objective){ + unsigned int i; + double min, value; + + if(_no_points < 1) + throw("Error in moeoHyperVolumeUnaryMetric::surface_unchanged_to -> argument2: _no_points must be greater than 0"); + min = _front[0][_objective]; + + for(i=1; i < _no_points; i++){ + value = _front[i][_objective]; + if(value < min) + min = value; + } + return min; + } + + + /** + * remove all points having a value <= 'threshold' regarding the dimension 'objective', only points of index 0 to _no_points are considered. + * points removed are swap at the end of the front. + * @param _front the front + * @param _no_points the number of points of the front to consider (index 0 to _no_points are considered) + * @param _objective the objective to consider + * @param _threshold the threshold + * @return index of the last points of '_front' greater than the threshold + */ + unsigned int reduce_nondominated_set(std::vector < std::vector< double > >& _front, unsigned int _no_points, unsigned int _objective, double _threshold){ + unsigned int i,n ; + + n=_no_points; + for(i=0; i < n ; i++) + if(_front[i][_objective] <= _threshold){ + n--; + swap(_front, i, n); + i--; //ATTENTION I had this to reconsider the point copied to index i (it can be useless verify algorythimic in calc_hypervolume) + } + + return n; + } + + + /** + * calculate hypervolume of the front (data are redrafted before) + * @param _front the front + * @param _no_points the number of points of the front to consider (index 0 to _no_points are considered) + * @param _no_objectives the number of objective to consider + * @return the hypervolume of the front + */ + double calc_hypervolume(std::vector < std::vector< double > >& _front, unsigned int _no_points, unsigned int _no_objectives){ + unsigned int n; + double volume, distance; + + volume=0; + distance=0; + n=_no_points; + while(n > 0){ + unsigned int no_nondominated_points; + double temp_vol, temp_dist; + + //get back the index of non dominated points of the front regarding the first "_nb_objectives - 1" objectives + //So one dimension is not determinante for the dominance + no_nondominated_points = filter_nondominated_set(_front, n, _no_objectives - 1); + + temp_vol=0; + + //if there are less than 3 objectifs take the fisrt objectif of the first point of front to begin computation of hypervolume + if(_no_objectives < 3){ + if(_no_objectives < 1) + throw("Error in moeoHyperVolumeUnaryMetric::calc_hypervolume -> argument3: _no_objectives must be greater than 0"); + temp_vol=_front[0][0]; + } + //else if there at least 3 objectives, a recursive computation of hypervolume starts with _no_objectives -1 on the filter_nondominated_set calculating previously. + else + temp_vol= calc_hypervolume(_front, no_nondominated_points, _no_objectives - 1); + + //search the next minimum distance on the dimension _no_objectives -1 + temp_dist = surface_unchanged_to(_front, n, _no_objectives - 1); + //calculate the area + volume+= temp_vol * (temp_dist - distance); + //change distance to have the good lenght on next step + distance= temp_dist; + //remove all points <= distance on dimension _no_objectives + n=reduce_nondominated_set(_front, n , _no_objectives - 1, distance); + } + return volume; + } + + + + private: + + /*boolean indicates if data must be normalized or not*/ + bool normalize; + + double rho; + + /*vectors contains bounds for normalization*/ + std::vector < eoRealInterval > bounds; + + + + + + }; + +#endif /*MOEOHYPERVOLUMEUNARYMETRIC_H_*/