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 #ifndef _eoMOFitness_h
00027 #define _eoMOFitness_h
00028
00029 #include <math.h>
00030 #include <vector>
00031 #include <stdexcept>
00032 #include <iostream>
00033 #include <limits>
00034
00042 class eoMOFitnessTraits
00043 {
00044 public :
00045
00047 static unsigned nObjectives() { return 2; }
00048
00050 static double direction(unsigned which) { return 1; }
00051
00053 static double tol() { return 1e-6; }
00054
00055 };
00056
00057 namespace dominance {
00058
00059 template <class Traits>
00060 inline double worst_possible_value(unsigned objective) {
00061 double dir = Traits::direction(objective);
00062 if (dir == 0.) return 0.0;
00063 if (dir < 0.) return std::numeric_limits<double>::infinity();
00064 return -std::numeric_limits<double>::infinity();
00065 }
00066
00067 template <class Traits>
00068 inline double best_possible_value(unsigned objective) {
00069 return -worst_possible_value<Traits>(objective);
00070 }
00071
00072 enum dominance_result { non_dominated_equal, first, second, non_dominated };
00073
00074 template <class FitnessDirectionTraits>
00075 inline dominance_result check(const std::vector<double>& p1, const std::vector<double>& p2, double tolerance) {
00076
00077 bool all_equal = true;
00078 bool a_better_in_one = false;
00079 bool b_better_in_one = false;
00080
00081 for (unsigned i = 0; i < p1.size(); ++i) {
00082
00083 double maxim = FitnessDirectionTraits::direction(i);
00084 double aval = maxim * p1[i];
00085 double bval = maxim * p2[i];
00086
00087 if ( fabs(aval-bval) > tolerance ) {
00088 all_equal = false;
00089 if (aval > bval) {
00090 a_better_in_one = true;
00091
00092 } else {
00093 b_better_in_one = true;
00094 }
00095
00096
00097 if (a_better_in_one && b_better_in_one) return non_dominated;
00098 }
00099
00100 }
00101
00102 if (all_equal) return non_dominated_equal;
00103
00104 if (a_better_in_one) return first;
00105
00106 return second;
00107 }
00108
00109 template <class IntType>
00110 inline dominance_result check_discrete(const std::vector<IntType>& a, const std::vector<IntType>& b) {
00111
00112 bool all_equal = true;
00113 bool a_better_in_one = false;
00114 bool b_better_in_one = false;
00115
00116 for (unsigned i = 0; i < a.size(); ++i) {
00117
00118 if ( a[i] != b[i] ) {
00119 all_equal = false;
00120 if (a[i] > b[i]) {
00121 a_better_in_one = true;
00122
00123 } else {
00124 b_better_in_one = true;
00125 }
00126
00127
00128 if (a_better_in_one && b_better_in_one) return non_dominated;
00129 }
00130
00131 }
00132
00133 if (all_equal) return non_dominated_equal;
00134
00135 if (a_better_in_one) return first;
00136
00137 return second;
00138 }
00139
00140 template <class FitnessTraits>
00141 inline dominance_result check(const std::vector<double>& p1, const std::vector<double>& p2) {
00142 return check<FitnessTraits>(p1, p2, FitnessTraits::tol());
00143 }
00144
00145
00146
00147 }
00148
00158 template <class FitnessTraits = eoMOFitnessTraits>
00159 class eoMOFitness : public std::vector<double>
00160 {
00161 double worth;
00162 bool worthValid;
00163 public :
00164
00165 typedef FitnessTraits fitness_traits;
00166
00167 eoMOFitness() : std::vector<double>(FitnessTraits::nObjectives()), worthValid(false) { reset(); }
00168
00169 explicit eoMOFitness(double def) : std::vector<double>(FitnessTraits::nObjectives(),def), worthValid(false) {}
00170
00171
00172 explicit eoMOFitness(std::vector<double> & _v) : std::vector<double>(_v), worthValid(false) {}
00173
00174 virtual ~eoMOFitness() {}
00175 eoMOFitness(const eoMOFitness<FitnessTraits>& org) { operator=(org); }
00176
00177 eoMOFitness<FitnessTraits>& operator=(const eoMOFitness<FitnessTraits>& org) {
00178
00179 std::vector<double>::operator=(org);
00180 worth = org.worth;
00181 worthValid = org.worthValid;
00182
00183 return *this;
00184 }
00185
00186 void reset() {
00187
00188 for (unsigned i = 0; i < size(); ++i) {
00189 this->operator[](i) = dominance::worst_possible_value<FitnessTraits>(i);
00190 }
00191 }
00192
00193
00194 void setFeasible(unsigned objective) { this->operator[](objective) = dominance::best_possible_value<FitnessTraits>(objective); }
00195
00196 void setWorth(double worth_) {
00197 worth = worth_;
00198 worthValid = true;
00199 }
00200
00201 double getWorth() const {
00202 if (!worthValid) {
00203 throw std::runtime_error("invalid worth");
00204 }
00205 return worth;
00206 }
00207
00208 bool validWorth() const { return worthValid; }
00209 void invalidateWorth() { worthValid = false; }
00210
00212 int check_dominance(const eoMOFitness<FitnessTraits>& _other) const
00213 {
00214 dominance::dominance_result dom = dominance::check<FitnessTraits>(*this, _other);
00215
00216 return dom == dominance::first? 1 : (dom == dominance::second? -1 : 0);
00217 }
00218
00220 std::vector<double> normalized() const {
00221 std::vector<double> f;
00222
00223 for (unsigned j = 0; j < FitnessTraits::nObjectives(); ++j) {
00224 if (FitnessTraits::direction(j) != 0) {
00225 f.push_back( FitnessTraits::direction(j) * this->operator[](j));
00226 }
00227 }
00228
00229 return f;
00230 }
00231
00233 bool dominates(const eoMOFitness<FitnessTraits>& _other) const
00234 {
00235 return check_dominance(_other) == 1;
00236 }
00237
00239 bool operator<(const eoMOFitness<FitnessTraits>& _other) const
00240 {
00241 return getWorth() < _other.getWorth();
00242 }
00243
00244 bool operator>(const eoMOFitness<FitnessTraits>& _other) const
00245 {
00246 return _other > *this;
00247 }
00248
00249 bool operator<=(const eoMOFitness<FitnessTraits>& _other) const
00250 {
00251 return getWorth() <= _other.getWorth();
00252 }
00253
00254 bool operator>=(const eoMOFitness<FitnessTraits>& _other) const
00255 {
00256 return _other <= *this;
00257 }
00258
00259 bool operator==(const eoMOFitness<FitnessTraits>& _other) const
00260 {
00261 return getWorth() == _other.getWorth();
00262 }
00263
00264 bool operator!=(const eoMOFitness<FitnessTraits>& _other) const
00265 { return ! operator==(_other); }
00266
00267
00268 friend std::ostream& operator<<(std::ostream& os, const eoMOFitness<FitnessTraits>& fitness)
00269 {
00270 for (unsigned i = 0; i < fitness.size(); ++i)
00271 {
00272 os << fitness[i] << ' ';
00273 }
00274 os << fitness.worthValid << ' ' << fitness.worth;
00275 return os;
00276 }
00277
00278 friend std::istream& operator>>(std::istream& is, eoMOFitness<FitnessTraits>& fitness)
00279 {
00280 fitness = eoMOFitness<FitnessTraits>();
00281 for (unsigned i = 0; i < fitness.size(); ++i)
00282 {
00283 is >> fitness[i];
00284 }
00285 is >> fitness.worthValid >> fitness.worth;
00286 return is;
00287 }
00288
00289 };
00290
00291 namespace dominance {
00292 template <class FitnessTraits>
00293 inline dominance_result check(const eoMOFitness<FitnessTraits>& p1, const eoMOFitness<FitnessTraits>& p2) {
00294 return check<FitnessTraits>(p1, p2, FitnessTraits::tol());
00295 }
00296 }
00297
00298 #endif