PaGMO  1.1.5
problem/cstrs_co_evolution.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 <algorithm>
27 
28 #include "../exceptions.h"
29 #include "../types.h"
30 #include "../population.h"
31 #include "cstrs_co_evolution.h"
32 
35 
36 namespace pagmo { namespace problem {
37 
57 cstrs_co_evolution::cstrs_co_evolution(const base &problem, const algorithm::cstrs_co_evolution::method_type method):
58  base_meta(
59  problem,
60  problem.get_dimension(),
61  problem.get_i_dimension(),
62  problem.get_f_dimension(),
63  0,
64  0,
65  std::vector<double>()),
66  m_penalty_coeff(),
67  m_method(method),
68  m_map_fitness(),
69  m_map_constraint(),
70  m_decision_vector_hash()
71 {
72  if(m_original_problem->get_c_dimension() <= 0){
73  pagmo_throw(value_error,"The original problem has no constraints.");
74  }
75 
76  // check that the dimension of the problem is 1
77  if (m_original_problem->get_f_dimension() != 1) {
78  pagmo_throw(value_error,"The original fitness dimension of the problem must be one, multi objective problems can't be handled with co-evolution meta problem.");
79  }
80 
81  std::fill(m_penalty_coeff.begin(),m_penalty_coeff.end(),0.);
82 }
83 
84 cstrs_co_evolution::cstrs_co_evolution(const base &problem, const population& pop, const algorithm::cstrs_co_evolution::method_type method):
85  base_meta(
86  problem,
87  problem.get_dimension(),
88  problem.get_i_dimension(),
89  problem.get_f_dimension(),
90  0,
91  0,
92  std::vector<double>()),
93  m_penalty_coeff(),
94  m_method(method),
95  m_map_fitness(),
96  m_map_constraint(),
97  m_decision_vector_hash()
98 {
99  if(m_original_problem->get_c_dimension() <= 0){
100  pagmo_throw(value_error,"The original problem has no constraints.");
101  }
102 
103  // check that the dimension of the problem is 1
104  if (m_original_problem->get_f_dimension() != 1) {
105  pagmo_throw(value_error,"The original fitness dimension of the problem must be one, multi objective problems can't be handled with co-evolution meta problem.");
106  }
107  if(problem != pop.problem()) {
108  pagmo_throw(value_error,"The problem linked to the population is not the same as the problem given in argument.");
109  }
110 
111  std::fill(m_penalty_coeff.begin(),m_penalty_coeff.end(),0.);
112 
113  m_map_fitness.clear();
114  m_map_constraint.clear();
115  // store f and c in maps depending on the the x hash
116  for(population::size_type i=0; i<pop.size(); i++) {
117  const population::individual_type &current_individual = pop.get_individual(i);
118  // m_map_fitness.insert(std::pair<std::size_t, fitness_vector>(m_decision_vector_hash(current_individual.cur_x),current_individual.cur_f));
119  m_map_fitness[m_decision_vector_hash(current_individual.cur_x)]=current_individual.cur_f;
120  m_map_constraint[m_decision_vector_hash(current_individual.cur_x)]=current_individual.cur_c;
121  }
122 
123 }
124 
127 {
128  return base_ptr(new cstrs_co_evolution(*this));
129 }
130 
133 
137 void cstrs_co_evolution::objfun_impl(fitness_vector &f, const decision_vector &x) const
138 {
139  std::map<std::size_t, fitness_vector>::const_iterator it_f;
140 
141  it_f = m_map_fitness.find(m_decision_vector_hash(x));
142  if(it_f != m_map_fitness.end()) {
143  f = it_f->second;
144  } else {
145  m_original_problem->objfun(f, x);
146  }
147 
148  std::vector<double> sum_viol;
149  std::vector<int> num_viol;
150 
151  compute_penalty(sum_viol,num_viol,x);
152 
153  // assuming minimization
154  switch(m_method)
155  {
156  case algorithm::cstrs_co_evolution::SIMPLE:
157  {
158  f[0] += sum_viol.at(0) * m_penalty_coeff.at(0) + double(num_viol.at(0)) * m_penalty_coeff.at(1);
159  break;
160  }
161  case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ:
162  {
163  f[0] += sum_viol.at(0) * m_penalty_coeff.at(0) + double(num_viol.at(0)) * m_penalty_coeff.at(1);
164  f[0] += sum_viol.at(1) * m_penalty_coeff.at(2) + double(num_viol.at(1)) * m_penalty_coeff.at(3);
165  break;
166  }
167  case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS:
168  {
169  int c_dimension = m_original_problem->get_c_dimension();
170  for(int i=0; i<c_dimension; i++) {
171  f[0] += sum_viol.at(i) * m_penalty_coeff.at(i*2) + double(num_viol.at(i)) * m_penalty_coeff.at(1+i*2);
172  }
173  break;
174  }
175  }
176 }
177 
179 
183 {
184  std::ostringstream oss;
185  oss << m_original_problem->human_readable_extra() << std::endl;
186  oss << "\n\tConstraints handled with co-evolution method ";
187  oss << std::endl;
188  return oss.str();
189 }
190 
191 std::string cstrs_co_evolution::get_name() const
192 {
193  return m_original_problem->get_name() + " [cstrs_co_evolution]";
194 }
195 
197 
201 void cstrs_co_evolution::set_penalty_coeff(const std::vector<double> &penalty_coeff)
202 {
203  switch(m_method)
204  {
205  case algorithm::cstrs_co_evolution::SIMPLE:
206  {
207  if(penalty_coeff.size() != 2) {
208  pagmo_throw(value_error,"The size of the penalty coefficient vector is not 2.");
209  }
210  break;
211  }
212  case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ:
213  {
214  if(penalty_coeff.size() != 4) {
215  pagmo_throw(value_error,"The size of the penalty coefficient vector is not 4.");
216  }
217  break;
218  }
219  case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS:
220  if(penalty_coeff.size() != 2*m_original_problem->get_c_dimension()) {
221  pagmo_throw(value_error,"The size of the penalty coefficient vector is not 2*number constraints");
222  }
223  break;
224  default:
225  pagmo_throw(value_error,"The constraints co-evolutionary method is not valid.");
226  break;
227  }
228  m_penalty_coeff = penalty_coeff;
229 }
230 
233 int cstrs_co_evolution::get_penalty_coeff_size() {
234  switch(m_method)
235  {
236  case algorithm::cstrs_co_evolution::SIMPLE:
237  {
238  return 2;
239  break;
240  }
241  case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ:
242  {
243  return 4;
244  break;
245  }
246  case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS:
247  return 2*m_original_problem->get_c_dimension();
248  break;
249  default:
250  pagmo_throw(value_error,"The constraints co-evolutionary method is not valid.");
251  break;
252  }
253 }
254 
256 
262 void cstrs_co_evolution::compute_penalty(std::vector<double> &sum_viol, std::vector<int> &num_viol, const decision_vector &x) const
263 {
264  // get the constraints dimension
265  problem::base::c_size_type prob_c_dimension = m_original_problem->get_c_dimension();
266  constraint_vector c(prob_c_dimension, 0.);
267  constraint_vector c_vio(prob_c_dimension, 0.);
268  problem::base::c_size_type number_of_eq_constraints = prob_c_dimension - m_original_problem->get_ic_dimension();
269 
270  const std::vector<double> &c_tol = m_original_problem->get_c_tol();
271 
272  // updates the current constraint vector
273  std::map<std::size_t, constraint_vector>::const_iterator it_c;
274 
275  it_c = m_map_constraint.find(m_decision_vector_hash(x));
276  if(it_c != m_map_constraint.end()) {
277  c = it_c->second;
278  } else {
279  m_original_problem->compute_constraints(c,x);
280  }
281 
282 
283  // sets the right definition of the constraints violation
284  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
285  if(j<number_of_eq_constraints){
286  c_vio[j] = std::abs(c.at(j)) - c_tol.at(j);
287  }
288  else{
289  c_vio[j] = c.at(j) - c_tol.at(j);
290  }
291  }
292  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
293  c_vio[j] = std::max(0., c_vio.at(j));
294  }
295 
296  // updates the vectors depending on the method
297  switch(m_method)
298  {
299  case algorithm::cstrs_co_evolution::SIMPLE:
300  {
301  sum_viol.resize(1);
302  num_viol.resize(1);
303  std::fill(sum_viol.begin(),sum_viol.end(),0.);
304  std::fill(num_viol.begin(),num_viol.end(),0.);
305 
306  // update sum_num_viol
307  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
308  sum_viol[0] += c_vio.at(j);
309  }
310 
311  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
312  if(!m_original_problem->test_constraint(c, j)) {
313  num_viol[0] += 1;
314  }
315  }
316  break;
317  }
318  case algorithm::cstrs_co_evolution::SPLIT_NEQ_EQ:
319  {
320  sum_viol.resize(2);
321  num_viol.resize(2);
322  std::fill(sum_viol.begin(),sum_viol.end(),0.);
323  std::fill(num_viol.begin(),num_viol.end(),0.);
324 
325  // update sum_num_viol
326  for(problem::base::c_size_type j=0; j<number_of_eq_constraints; j++) {
327  sum_viol[0] += c_vio.at(j);
328  }
329  for(problem::base::c_size_type j=number_of_eq_constraints; j<prob_c_dimension; j++) {
330  sum_viol[1] += c_vio.at(j);
331  }
332  for(problem::base::c_size_type j=0; j<number_of_eq_constraints; j++) {
333  if(!m_original_problem->test_constraint(c, j)) {
334  num_viol[0] += 1;
335  }
336  }
337  for(problem::base::c_size_type j=number_of_eq_constraints; j<prob_c_dimension; j++) {
338  if(!m_original_problem->test_constraint(c, j)) {
339  num_viol[1] += 1;
340  }
341  }
342  break;
343  }
344  case algorithm::cstrs_co_evolution::SPLIT_CONSTRAINTS:
345  {
346  sum_viol.resize(prob_c_dimension);
347  num_viol.resize(prob_c_dimension);
348 
349  std::fill(sum_viol.begin(),sum_viol.end(),0.);
350  std::fill(num_viol.begin(),num_viol.end(),0.);
351 
352  // update sum_num_viol
353  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
354  sum_viol[j] += c_vio.at(j);
355  }
356  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
357  if(!m_original_problem->test_constraint(c, j)) {
358  num_viol[j] += 1;
359  }
360  }
361  break;
362  }
363  }
364 }
365 
376 cstrs_co_evolution_penalty::cstrs_co_evolution_penalty(const base &problem, int dimension, int size):
377  base(dimension,
378  problem.get_i_dimension(),
379  1,
380  0,
381  0,
382  0.),
383  m_original_problem(problem.clone()),
384  m_pop_2_x_vector(size, decision_vector(0)),
385  m_feasible_count_vector(size,0),
386  m_feasible_fitness_sum_vector(size,0.0),
387  m_max_feasible_fitness(0.),
388  m_total_sum_viol(size,0.0),
389  m_total_num_viol(size,0)
390 {
391  if(m_original_problem->get_c_dimension() <= 0){
392  pagmo_throw(value_error,"The original problem has no constraints.");
393  }
394 
395  // check that the dimension of the problem is 1
396  if (m_original_problem->get_f_dimension() != 1) {
397  pagmo_throw(value_error,"The original fitness dimension of the problem must be one, multi objective problems can't be handled with co evolution meta problem.");
398  }
399 
400  set_bounds(0.,10000.);
401 }
402 
404 cstrs_co_evolution_penalty::cstrs_co_evolution_penalty(const cstrs_co_evolution_penalty &prob):
405  base(prob),
406  m_original_problem(prob.m_original_problem->clone()),
407  m_pop_2_x_vector(prob.m_pop_2_x_vector),
408  m_feasible_count_vector(prob.m_feasible_count_vector),
409  m_feasible_fitness_sum_vector(prob.m_feasible_fitness_sum_vector),
410  m_max_feasible_fitness(prob.m_max_feasible_fitness),
411  m_total_sum_viol(prob.m_total_sum_viol),
412  m_total_num_viol(prob.m_total_num_viol)
413 {
414  set_bounds(prob.get_lb(),prob.get_ub());
415 }
416 
418 base_ptr cstrs_co_evolution_penalty::clone() const
419 {
420  return base_ptr(new cstrs_co_evolution_penalty(*this));
421 }
422 
425 
428 void cstrs_co_evolution_penalty::objfun_impl(fitness_vector &f, const decision_vector &x) const
429 {
430  // search where the x vector is located
431  int position=-1;
432  for(std::vector<decision_vector>::size_type i=0; i<m_pop_2_x_vector.size(); i++) {
433  if(m_pop_2_x_vector.at(i) == x) {
434  position = i;
435  break;
436  }
437  }
438 
439  if(position != -1) {
440  // computes the fitness for population 2
441  // case the solution containts at least one feasible individual
442  if(m_feasible_count_vector.at(position) > 0) {
443  f[0] = m_feasible_fitness_sum_vector[position] / double(m_feasible_count_vector[position]) - double(m_feasible_count_vector[position]);
444  } else {
445  f[0] = m_max_feasible_fitness +
446  m_total_sum_viol.at(position)/double(m_total_num_viol.at(position)) -
447  double(m_total_num_viol.at(position));
448  }
449  }
450  else {
451  // what to do?
452  f[0] = m_max_feasible_fitness;
453  }
454 }
455 
457 
461 bool cstrs_co_evolution_penalty::compare_fitness_impl(const fitness_vector &v_f1, const fitness_vector &v_f2) const
462 {
463  return m_original_problem->compare_fitness(v_f1,v_f2);
464 }
465 
467 
470 std::string cstrs_co_evolution_penalty::human_readable_extra() const
471 {
472  std::ostringstream oss;
473  oss << m_original_problem->human_readable_extra() << std::endl;
474  oss << "\n\tConstraints handled with co-evolution method ";
475  oss << std::endl;
476  return oss.str();
477 }
478 
479 std::string cstrs_co_evolution_penalty::get_name() const
480 {
481  return m_original_problem->get_name() + " [cstrs_co_evolution_2]";
482 }
483 
485 
489 void cstrs_co_evolution_penalty::update_penalty_coeff(population::size_type &index, const decision_vector &pop_2_x, const population &pop_1)
490 {
491  m_pop_2_x_vector.at(index) = pop_2_x;
492 
493  population::size_type pop_1_size = pop_1.size();
494 
495  m_max_feasible_fitness = 0.;
496  // computes the total sum_viol, num_viol...
497 
498  m_total_sum_viol[index] = 0.;
499  m_total_num_viol[index] = 0;
500 
501  // computes the number of feasible solutions and their sum for the current population
502  int feasible_count = 0;
503  double feasible_fitness_sum = 0.;
504 
505  double sum_viol_temp = 0.;
506  int num_viol_temp = 0;
507  for(population::size_type i=0; i<pop_1_size; i++) {
508  const fitness_vector &current_f = pop_1.get_individual(i).cur_f;
509  const decision_vector &current_c = pop_1.get_individual(i).cur_c;
510 
511  if(m_original_problem->feasibility_c(current_c)) {
512  feasible_count++;
513  feasible_fitness_sum += current_f[0];
514 
515  // computes max feasible fitness
516  if(i==0) {
517  m_max_feasible_fitness = current_f[0];
518  } else {
519  if(m_max_feasible_fitness < current_f[0]) {
520  m_max_feasible_fitness = current_f[0];
521  }
522  }
523  }
524 
525  compute_penalty(sum_viol_temp,num_viol_temp,current_c);
526  m_total_sum_viol[index] += sum_viol_temp;
527  m_total_num_viol[index] += num_viol_temp;
528  }
529  m_feasible_count_vector[index] = feasible_count;
530  m_feasible_fitness_sum_vector[index] = feasible_fitness_sum;
531 }
532 
534 
540 void cstrs_co_evolution_penalty::compute_penalty(double &sum_viol, int &num_viol, const constraint_vector &c) const
541 {
542  // get the constraints dimension
543  problem::base::c_size_type prob_c_dimension = m_original_problem->get_c_dimension();
544  problem::base::c_size_type number_of_eq_constraints = prob_c_dimension - m_original_problem->get_ic_dimension();
545 
546  const std::vector<double> &c_tol = m_original_problem->get_c_tol();
547 
548  // update sum_num_viol
549  sum_viol = 0.;
550  for(problem::base::c_size_type j=0; j<number_of_eq_constraints; j++) {
551  sum_viol += std::max(0.,std::abs(c.at(j)) - c_tol.at(j));
552  }
553 
554  for(problem::base::c_size_type j=number_of_eq_constraints; j<prob_c_dimension; j++) {
555  sum_viol += std::max(0.,c.at(j));
556  }
557 
558  num_viol = 0;
559  for(problem::base::c_size_type j=0; j<prob_c_dimension; j++) {
560  if(!m_original_problem->test_constraint(c, j)) {
561  num_viol += 1;
562  }
563  }
564 }
565 }}
566 
568 
569 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::problem::cstrs_co_evolution)
570 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::problem::cstrs_co_evolution_penalty)
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
Root PaGMO namespace.
std::vector< double > decision_vector
Decision vector type.
Definition: types.h:40
STL namespace.
std::vector< double > fitness_vector
Fitness vector type.
Definition: types.h:42
std::vector< double > constraint_vector
Constraint vector type.
Definition: types.h:44
container_type::size_type size_type
Population size type.
Definition: population.h:192
constraint_vector::size_type c_size_type
Constraints' size type: the same as pagmo::constraint_vector's size type.
Definition: problem/base.h:164
std::string human_readable_extra() const
Extra human readable algorithm info.
std::string get_name() const
Algorithm name.
cstrs_co_evolution(const base &=jde(), const base &=sga(1), int pop_penalties_size=30, int gen=1, method_type method=SIMPLE, double pen_lower_bound=0., double pen_upper_bound=100000., double=1e-15, double=1e-15)
Constructor.