PaGMO  1.1.5
dtlz.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 <cmath>
26 #include <boost/math/constants/constants.hpp>
27 
28 #include "../exceptions.h"
29 #include "../types.h"
30 #include "../population.h"
31 #include "dtlz.h"
32 
33 static int __check__(int N)
34 {
35  if (N > 7 || N < 1) {
36  pagmo_throw(value_error, "the problem id needs to be one of [1..7]");
37  }
38  return N;
39 }
40 
41 namespace pagmo { namespace problem {
42 
43 static const double PI_HALF = boost::math::constants::pi<double>() / 2.0;
44 
54 dtlz::dtlz(size_type id, size_type k, size_type fdim, const size_t alpha)
55  :base_dtlz(k + fdim - 1, fdim),
56  m_problem_number(__check__(id)),
57  m_alpha(alpha)
58 {
59  // Set bounds.
60  set_lb(0.0);
61  set_ub(1.0);
62 }
63 
66 {
67  return base_ptr(new dtlz(*this));
68 }
69 
71 double dtlz::g_func(const decision_vector &x) const
72 {
73  switch(m_problem_number)
74  { // We start with the 6-7 cases as for absurd reasons behind my comprehension this is way more efficient
75  case 6:
76  return g6_func(x);
77  case 7:
78  return g7_func(x);
79  case 1:
80  case 3:
81  return g13_func(x);
82  case 2:
83  case 4:
84  case 5:
85  return g245_func(x);
86  default:
87  pagmo_throw(value_error, "Error: There are only 7 test functions in this test suite!");
88  }
89  return -1.0;
90 }
91 
94 {
95 
96  pagmo_assert(f.size() == get_f_dimension());
97  pagmo_assert(x.size() == get_dimension());
98 
99  switch(m_problem_number)
100  {
101  case 1:
102  f1_objfun_impl(f,x);
103  break;
104  case 2:
105  case 3:
106  f23_objfun_impl(f,x);
107  break;
108  case 4:
109  f4_objfun_impl(f,x);
110  break;
111  case 5:
112  case 6:
113  f56_objfun_impl(f,x);
114  break;
115  case 7:
116  f7_objfun_impl(f,x);
117  break;
118  default:
119  pagmo_throw(value_error, "Error: There are only 7 test functions in this test suite!");
120  break;
121  }
122 }
123 
125 double dtlz::g13_func(const decision_vector &x) const
126 {
127  double y = 0.0;
128  for(decision_vector::size_type i = 0; i < x.size(); ++i) {
129  y += pow(x[i] - 0.5, 2) - cos(20 * boost::math::constants::pi<double>() * (x[i] - 0.5));
130  }
131  return 100.0 * (y + x.size());
132 }
133 
134 double dtlz::g245_func(const decision_vector &x) const
135 {
136  double y = 0.0;
137  for(decision_vector::size_type i = 0; i < x.size(); ++i) {
138  y += pow(x[i] - 0.5, 2);
139  }
140  return y;
141 }
142 
143 double dtlz::g6_func(const decision_vector &x) const
144 {
145  double y = 0.0;
146  for(decision_vector::size_type i = 0; i < x.size(); ++i) {
147  y += pow(x[i], 0.1);
148  }
149  return y;
150 }
151 
152 double dtlz::g7_func(const decision_vector &x) const
153 {
154  // NOTE: the original g-function should return 1 + (9.0 / x.size()) * y but we drop the 1
155  // to have the minimum at 0.0 so we can use the p_distance implementation in base_dtlz
156  // to have the p_distance converging towards 0.0 rather then towards 1.0
157  double y = 0.0;
158  for(decision_vector::size_type i = 0; i < x.size(); ++i) {
159  y += x[i];
160  }
161  return (9.0 / x.size()) * y;
162 }
163 
165 double dtlz::h7_func(const fitness_vector &f, const double g) const
166 {
167  // NOTE: we intentionally ignore the last element of the vector to make things easier
168  int fdim = get_f_dimension();
169  double y = 0.0;
170 
171  for(decision_vector::size_type i = 0; i < f.size() - 1; ++i) {
172  y += (f[i] / (1.0 + g)) * (1.0 + sin(3 * boost::math::constants::pi<double>() * f[i]) );
173  }
174  return fdim - y;
175 }
176 
178 /* The chomosome: x_1, x_2, ........, x_M-1, x_M, .........., x_M+k
179  * [------- Vector x_M -------]
180  * x[0], x[1], ... ,x[fdim-2], x[fdim-1], ... , x[fdim+k-1] */
181 void dtlz::f1_objfun_impl(fitness_vector &f, const decision_vector &x) const
182 {
183  // computing distance-function
184  decision_vector x_M;
185  double g;
186 
187  for(problem::base::size_type i = f.size() - 1; i < x.size(); ++i) {
188  x_M.push_back(x[i]);
189  }
190 
191  g = g_func(x_M);
192 
193  // computing shape-functions
194  f[0] = 0.5 * (1.0 + g);
195 
196  for(problem::base::size_type i = 0; i < f.size() - 1; ++i) {
197  f[0] *= x[i];
198  }
199 
200  for(problem::base::size_type i = 1; i < f.size() - 1; ++i) {
201  f[i] = 0.5 * (1.0 + g);
202  for(problem::base::size_type j = 0; j < f.size() - (i+1); ++j) {
203  f[i] *= x[j];
204  }
205  f[i] *= 1 - x[f.size() - (i+1)];
206  }
207 
208  f[f.size()-1] = 0.5 * (1 - x[0]) * (1.0 + g);
209 }
210 
211 void dtlz::f23_objfun_impl(fitness_vector &f, const decision_vector &x) const
212 {
213  // computing distance-function
214  decision_vector x_M;
215  double g;
216 
217  for(problem::base::size_type i = f.size() - 1; i < x.size(); ++i) {
218  x_M.push_back(x[i]);
219  }
220 
221  g = g_func(x_M);
222 
223  // computing shape-functions
224  f[0] = (1.0 + g);
225  for(problem::base::size_type i = 0; i < f.size() - 1; ++i) {
226  f[0] *= cos(x[i] * PI_HALF);
227  }
228 
229  for(problem::base::size_type i = 1; i < f.size() - 1; ++i) {
230  f[i] = (1.0 + g);
231  for(problem::base::size_type j = 0; j < f.size() - (i+1); ++j) {
232  f[i] *= cos(x[j] * PI_HALF);
233  }
234  f[i] *= sin(x[f.size() - (i+1)] * PI_HALF);
235  }
236 
237  f[f.size()-1] = (1.0 + g) * sin(x[0] * PI_HALF);
238 
239 }
240 
241 void dtlz::f4_objfun_impl(fitness_vector &f, const decision_vector &x) const
242 {
243  // computing distance-function
244  decision_vector x_M;
245  double g;
246 
247  for(problem::base::size_type i = f.size() - 1; i < x.size(); ++i) {
248  x_M.push_back(x[i]);
249  }
250 
251  g = g_func(x_M);
252 
253  // computing shape-functions
254  f[0] = (1.0 + g);
255  for(problem::base::size_type i = 0; i < f.size() - 1; ++i) {
256  f[0] *= cos(pow(x[i],m_alpha) * PI_HALF);
257  }
258 
259  for(problem::base::size_type i = 1; i < f.size() - 1; ++i) {
260  f[i] = (1.0 + g);
261  for(problem::base::size_type j = 0; j < f.size() - (i+1); ++j) {
262  f[i] *= cos(pow(x[j], m_alpha) * PI_HALF);
263  }
264  f[i] *= sin(pow(x[f.size() - (i+1)], m_alpha) * PI_HALF);
265  }
266 
267  f[f.size()-1] = (1.0 + g) * sin(pow(x[0],m_alpha) * PI_HALF);
268 
269 }
270 
271 void dtlz::f56_objfun_impl(fitness_vector &f, const decision_vector &x) const
272 {
273  // computing distance-function
274  decision_vector x_M;
275  double g;
276 
277  for(problem::base::size_type i = f.size() - 1; i < x.size(); ++i) {
278  x_M.push_back(x[i]);
279  }
280 
281  g = g_func(x_M);
282 
283  // computing meta-variables
284  decision_vector theta(f.size(), 0.0);
285  double t;
286 
287  theta[0] = x[0]; // * PI_HALF;
288  t = 1.0 / (2.0 * (1.0 + g));
289 
290  for(problem::base::size_type i = 1; i < f.size(); ++i) {
291  theta[i] = t + ((g * x[i]) / (1.0 + g));
292  }
293 
294  // computing shape-functions
295  f[0] = (1.0 + g);
296  for(problem::base::size_type i = 0; i < f.size() - 1; ++i) {
297  f[0] *= cos(theta[i] * PI_HALF);
298  }
299 
300  for(problem::base::size_type i = 1; i < f.size() - 1; ++i) {
301  f[i] = (1.0 + g);
302  for(problem::base::size_type j = 0; j < f.size() - (i+1); ++j) {
303  f[i] *= cos(theta[j] * PI_HALF);
304  }
305  f[i] *= sin(theta[f.size() - (i+1)] * PI_HALF);
306  }
307 
308  f[f.size()-1] = (1.0 + g) * sin(theta[0] * PI_HALF);
309 
310 }
311 
312 void dtlz::f7_objfun_impl(fitness_vector &f, const decision_vector &x) const
313 {
314  // computing distance-function
315  decision_vector x_M;
316  double g;
317 
318  for(problem::base::size_type i = f.size() - 1; i < x.size(); ++i) {
319  x_M.push_back(x[i]);
320  }
321 
322  g = 1.0 + g_func(x_M); // +1.0 according to the original definition of the g-function for DTLZ7
323 
324  // computing shape-functions
325  for(problem::base::size_type i = 0; i < f.size() - 1; ++i) {
326  f[i] = x[i];
327  }
328 
329  f[f.size()-1] = (1.0 + g) * h7_func(f, g);
330 
331 }
332 
333 std::string dtlz::get_name() const
334 {
335  std::string retval("DTLZ");
336  retval.append(boost::lexical_cast<std::string>(m_problem_number));
337 
338  return retval;
339 }
340 
341 }}
342 
343 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::problem::dtlz)
Root PaGMO namespace.
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
Definition: problem/base.h:62
std::vector< double > decision_vector
Decision vector type.
Definition: types.h:40
std::string get_name() const
Get problem's name.
Definition: dtlz.cpp:333
Base DTLZ Multi-objective optimization problem.
Definition: base_dtlz.h:53
dtlz(size_type id=1, size_type k=5, fitness_vector::size_type fdim=3, const size_t alpha=100)
Definition: dtlz.cpp:54
base_ptr clone() const
Clone method.
Definition: dtlz.cpp:65
size_type get_dimension() const
Return global dimension.
void set_lb(const decision_vector &)
Set lower bounds from pagmo::decision_vector.
void set_ub(const decision_vector &)
Set upper bounds from pagmo::decision_vector.
std::vector< double > fitness_vector
Fitness vector type.
Definition: types.h:42
void objfun_impl(fitness_vector &, const decision_vector &) const
Implementation of the objective function.
Definition: dtlz.cpp:93
f_size_type get_f_dimension() const
Return fitness dimension.
DTLZ problem test suite.
Definition: dtlz.h:80
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160