PaGMO  1.1.5
util/hv_algorithm/base.cpp
1 /*****************************************************************************
2  * Copyright (C) 2004-2015 The PaGMO development team, *
3  * Advanced Concepts Team (ACT), European Space Agency (ESA) *
4  * *
5  * https://github.com/esa/pagmo *
6  * *
7  * act@esa.int *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the *
21  * Free Software Foundation, Inc., *
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23  *****************************************************************************/
24 
25 #include "base.h"
26 
27 namespace pagmo { namespace util { namespace hv_algorithm {
28 
31 
33 
41 void base::assert_minimisation(const std::vector<fitness_vector> &points, const fitness_vector &r_point) const
42 {
43  for(std::vector<fitness_vector>::size_type idx = 0 ; idx < points.size() ; ++idx) {
44  bool outside_bounds = false;
45  bool all_equal = true;
46 
47  for(fitness_vector::size_type f_idx = 0 ; f_idx < points[idx].size() ; ++f_idx) {
48  outside_bounds |= (r_point[f_idx] < points[idx][f_idx]);
49  all_equal &= (r_point[f_idx] == points[idx][f_idx]);
50  }
51  if (all_equal || outside_bounds) {
52  // Prepare error message.
53  std::stringstream ss;
54  std::string str_p("("), str_r("(");
55  for(fitness_vector::size_type f_idx = 0 ; f_idx < points[idx].size() ; ++f_idx) {
56  str_p += boost::lexical_cast<std::string>(points[idx][f_idx]);
57  str_r += boost::lexical_cast<std::string>(r_point[f_idx]);
58  if (f_idx < points[idx].size() - 1) {
59  str_p += ", ";
60  str_r += ", ";
61  } else {
62  str_p += ")";
63  str_r += ")";
64  }
65  }
66  ss << "Reference point is invalid: another point seems to be outside the reference point boundary, or be equal to it:" << std::endl;
67  ss << " P[" << idx << "]\t= " << str_p << std::endl;
68  ss << " R\t= " << str_r << std::endl;
69  pagmo_throw(value_error, ss.str());
70  }
71  }
72 }
73 
75 
86 double base::exclusive(const unsigned int p_idx, std::vector<fitness_vector> &points, const fitness_vector &r_point) const
87 {
88  if (points.size() == 1) {
89  return compute(points, r_point);
90  }
91  std::vector<fitness_vector> points_less;
92  points_less.reserve(points.size() - 1);
93  copy(points.begin(), points.begin() + p_idx, back_inserter(points_less));
94  copy(points.begin() + p_idx + 1, points.end(), back_inserter(points_less));
95 
96  return compute(points, r_point) - compute(points_less, r_point);
97 }
98 
100 
103 unsigned int base::extreme_contributor(std::vector<fitness_vector> &points, const fitness_vector &r_point, bool (*cmp_func)(double, double)) const
104 {
105  // Trivial case
106  if (points.size() == 1) {
107  return 0;
108  }
109 
110  std::vector<double> c = contributions(points, r_point);
111 
112  unsigned int idx_extreme = 0;
113 
114  // Check the remaining ones using the provided comparison function
115  for(unsigned int idx = 1 ; idx < c.size() ; ++idx) {
116  if (cmp_func(c[idx], c[idx_extreme])) {
117  idx_extreme = idx;
118  }
119  }
120 
121  return idx_extreme;
122 }
123 
125 
134 bool base::cmp_least(const double a, const double b)
135 {
136  return a < b;
137 }
138 
139 
141 
150 bool base::cmp_greatest(const double a, const double b)
151 {
152  return a > b;
153 }
154 
156 
166 unsigned int base::least_contributor(std::vector<fitness_vector> &points, const fitness_vector &r_point) const
167 {
168  return extreme_contributor(points, r_point, base::cmp_least);
169 }
170 
172 
182 unsigned int base::greatest_contributor(std::vector<fitness_vector> &points, const fitness_vector &r_point) const
183 {
184  return extreme_contributor(points, r_point, base::cmp_greatest);
185 }
186 
188 
199 std::vector<double> base::contributions(std::vector<fitness_vector> &points, const fitness_vector &r_point) const
200 {
201  std::vector<double> c;
202  c.reserve(points.size());
203 
204  // Trivial case
205  if (points.size() == 1) {
206  c.push_back(volume_between(points[0], r_point));
207  return c;
208  }
209 
210  // Compute the total hypervolume for the reference
211  std::vector<fitness_vector> points_cpy(points.begin(), points.end());
212  double hv_total = compute(points_cpy, r_point);
213 
214  // Points[0] as a first candidate
215  points_cpy = std::vector<fitness_vector>(points.begin() + 1, points.end());
216  c.push_back(hv_total - compute(points_cpy, r_point));
217 
218  // Check the remaining ones using the provided comparison function
219  for(unsigned int idx = 1 ; idx < points.size() ; ++idx) {
220  std::vector<fitness_vector> points_less;
221  points_less.reserve(points.size() - 1);
222  copy(points.begin(), points.begin() + idx, back_inserter(points_less));
223  copy(points.begin() + idx + 1, points.end(), back_inserter(points_less));
224  double delta = hv_total - compute(points_less, r_point);
225 
226  if (fabs(delta) < 1e-8) {
227  delta = 0.0;
228  }
229  c.push_back(delta);
230  }
231 
232  return c;
233 }
234 
236 
245 double base::volume_between(const fitness_vector &a, const fitness_vector &b, unsigned int dim_bound)
246 {
247  if (dim_bound == 0) {
248  dim_bound = a.size();
249  }
250  double volume = 1.0;
251  for (fitness_vector::size_type idx = 0; idx < dim_bound ; ++idx) {
252  volume *= (a[idx] - b[idx]);
253  }
254  return (volume < 0 ? -volume : volume);
255 }
256 
258 
267 double base::volume_between(double* a, double* b, unsigned int size)
268 {
269  double volume = 1.0;
270  while(size--) {
271  volume *= (b[size] - a[size]);
272  }
273  return (volume < 0 ? -volume : volume);
274 }
275 
277 
285 int base::dom_cmp(const fitness_vector &a, const fitness_vector &b, unsigned int dim_bound)
286 {
287  if (dim_bound == 0) {
288  dim_bound = a.size();
289  }
290  for(fitness_vector::size_type i = 0; i < dim_bound ; ++i) {
291  if (a[i] > b[i]) {
292  for(fitness_vector::size_type j = i + 1; j < dim_bound ; ++j) {
293  if (a[j] < b[j]) {
294  return DOM_CMP_INCOMPARABLE;
295  }
296  }
297  return DOM_CMP_B_DOMINATES_A;
298  }
299  else if (a[i] < b[i]) {
300  for(fitness_vector::size_type j = i + 1 ; j < dim_bound ; ++j) {
301  if (a[j] > b[j]) {
302  return DOM_CMP_INCOMPARABLE;
303  }
304  }
305  return DOM_CMP_A_DOMINATES_B;
306  }
307  }
308  return DOM_CMP_A_B_EQUAL;
309 }
310 
312 
320 int base::dom_cmp(double* a, double* b, unsigned int size)
321 {
322  for(fitness_vector::size_type i = 0; i < size ; ++i) {
323  if (a[i] > b[i]) {
324  for(fitness_vector::size_type j = i + 1; j < size ; ++j) {
325  if (a[j] < b[j]) {
326  return DOM_CMP_INCOMPARABLE;
327  }
328  }
329  return DOM_CMP_B_DOMINATES_A;
330  }
331  else if (a[i] < b[i]) {
332  for(fitness_vector::size_type j = i + 1 ; j < size ; ++j) {
333  if (a[j] > b[j]) {
334  return DOM_CMP_INCOMPARABLE;
335  }
336  }
337  return DOM_CMP_A_DOMINATES_B;
338  }
339  }
340  return DOM_CMP_A_B_EQUAL;
341 }
342 
344 
351 {
352  if (cmp_type == '<') {
353  m_cmp_obj = boost::shared_ptr<cmp_fun>(new cmp_le(dim));
354  }
355  else {
356  m_cmp_obj = boost::shared_ptr<cmp_fun>(new cmp_ge(dim));
357  }
358 }
359 
361 
366 std::string base::get_name() const
367 {
368  return typeid(*this).name();
369 }
370 
371 } } }
Root PaGMO namespace.
virtual ~base()
Destructor required for pure virtual methods.
static bool cmp_least(const double, const double)
Comparison method for the least contributor.
fitness_vector_cmp(int dim, char cmp_type)
Constructor of the comparator object.
static double volume_between(const fitness_vector &, const fitness_vector &, unsigned int=0)
Compute volume between two points.
void assert_minimisation(const std::vector< fitness_vector > &, const fitness_vector &) const
Assert that reference point dominates every other point from the set.
virtual unsigned int greatest_contributor(std::vector< fitness_vector > &, const fitness_vector &) const
Greatest contributor method.
static int dom_cmp(double *, double *, unsigned int)
Dominance comparison method.
static bool cmp_greatest(const double, const double)
Comparison method for the least contributor.
virtual std::string get_name() const
Get algorithm's name.
virtual double compute(std::vector< fitness_vector > &points, const fitness_vector &r_point) const =0
Compute method.
virtual double exclusive(const unsigned int, std::vector< fitness_vector > &, const fitness_vector &) const
Exclusive hypervolume method.
std::vector< double > fitness_vector
Fitness vector type.
Definition: types.h:42
virtual unsigned int least_contributor(std::vector< fitness_vector > &, const fitness_vector &) const
Least contributor method.
virtual std::vector< double > contributions(std::vector< fitness_vector > &, const fitness_vector &) const
Contributions method.
virtual unsigned int extreme_contributor(std::vector< fitness_vector > &, const fitness_vector &, bool(*)(double, double)) const
compute the extreme contributor