PaGMO  1.1.5
algorithm/cstrs_self_adaptive.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 <boost/random/uniform_int.hpp>
26 #include <boost/random/uniform_real.hpp>
27 #include <string>
28 #include <vector>
29 
30 #include "../exceptions.h"
31 #include "../population.h"
32 #include "../problem/base.h"
33 #include "../problem/cstrs_self_adaptive.h"
34 #include "../types.h"
35 #include "base.h"
36 #include "cstrs_self_adaptive.h"
37 
38 namespace pagmo { namespace algorithm {
39 
41 
50 cstrs_self_adaptive::cstrs_self_adaptive(const base &original_algo, int gen, double ftol, double xtol):base(),
51  m_original_algo(original_algo.clone()),m_gen(gen),m_ftol(ftol),m_xtol(xtol)
52 {
53  if(gen < 0) {
54  pagmo_throw(value_error,"number of generations must be nonnegative");
55  }
56 }
57 
59 cstrs_self_adaptive::cstrs_self_adaptive(const cstrs_self_adaptive &algo):base(algo),m_original_algo(algo.m_original_algo->clone()),m_gen(algo.m_gen),
60  m_ftol(algo.m_ftol),m_xtol(algo.m_xtol) {}
61 
64 {
65  return base_ptr(new cstrs_self_adaptive(*this));
66 }
67 
69 
75 {
76  // Let's store some useful variables.
77  const problem::base &prob = pop.problem();
78  const population::size_type pop_size = pop.size();
79  const problem::base::size_type prob_dimension = prob.get_dimension();
80 
81  // get the constraints dimension
82  problem::base::c_size_type prob_c_dimension = prob.get_c_dimension();
83 
84  //We perform some checks to determine wether the problem/population are suitable for Self-Adaptive
85  if(prob_c_dimension < 1) {
86  pagmo_throw(value_error,"The problem is not constrained and Self-Adaptive is not suitable to solve it");
87  }
88 
89  // Get out if there is nothing to do.
90  if (pop_size == 0) {
91  return;
92  }
93 
94  // Create the new problem;
95  problem::cstrs_self_adaptive prob_new(prob,pop);
96 
97  // Main Self-Adaptive loop
98  for(int k=0; k<m_gen; k++) {
99  //std::cout << "current generation: " << k << std::endl;
100 
101  // at the first iteration the problem is not changed,
102  // for k>0 the problem is gonna change, the cache need to be reset and the population cleared
103  if(k>0){
104  prob_new.reset_caches();
105  prob_new.update_penalty_coeff(pop);
106  }
107 
108  // if the problem has changed it needs to be reassigned to the population
109  population pop_new(prob_new,0);
110 
111  for(population::size_type i=0; i<pop_size; i++) {
112  // Evaluate according to the new fitness;
113  pop_new.push_back(pop.get_individual(i).cur_x);
114  }
115 
116  // this constraints handling technique is initially intended to be
117  // used as a fitness evaluator for ES, I am not convinced this is the easiest
118  // way to implement it. But for DE, PSO in example, there is no fitness evaluator?
119  m_original_algo->evolve(pop_new);
120 
121  // Reinsert best individual from the previous generation if not already present
122  // Uses the constrained problem. If we don't do that, we loose the best individual...
123  // Should we impose a certain percentage of the best ones?
124  bool exists = false;
125  for(population::size_type i=0; i<pop_size; i++) {
126  if(pop_new.get_individual(i).cur_x == pop.champion().x) {
127  exists=true;break;
128  }
129  }
130  if(!exists){
131  int worst=0;
132  for (pagmo::population::size_type i = 1; i<pop_new.size();i++) {
133  if ( prob.compare_x(pop_new.get_individual(worst).cur_x,pop_new.get_individual(i).cur_x) ) worst=i;
134  }
135 
136  decision_vector dummy = pop.champion().x;
137  std::transform(dummy.begin(), dummy.end(), pop.get_individual(worst).cur_x.begin(), dummy.begin(),std::minus<double>());
138  //updates x and v (cache avoids to recompute the objective function)
139  pop_new.set_x(worst,pop.champion().x);
140  pop_new.set_v(worst,dummy);
141  }
142 
143  // update the population pop
144  pop.clear();
145  for(pagmo::population::size_type i=0; i<pop_new.size(); i++) {
146  pop.push_back(pop_new.get_individual(i).cur_x);
147  }
148 
149  // Check the exit conditions (every 40 generations, just as DE)
150  if(k % 40 == 0) {
151  decision_vector tmp(prob_dimension);
152 
153  double dx = 0;
154  for(decision_vector::size_type i=0; i<prob_dimension; i++) {
155  tmp[i] = pop.get_individual(pop.get_worst_idx()).best_x[i] - pop.get_individual(pop.get_best_idx()).best_x[i];
156  dx += std::fabs(tmp[i]);
157  }
158 
159  if(dx < m_xtol ) {
160  if (m_screen_output) {
161  std::cout << "Exit condition -- xtol < " << m_xtol << std::endl;
162  }
163  break;
164  }
165 
166  double mah = std::fabs(pop.get_individual(pop.get_worst_idx()).best_f[0] - pop.get_individual(pop.get_best_idx()).best_f[0]);
167 
168  if(mah < m_ftol) {
169  if(m_screen_output) {
170  std::cout << "Exit condition -- ftol < " << m_ftol << std::endl;
171  }
172  break;
173  }
174 
175  // outputs current values
176  if(m_screen_output) {
177  std::cout << "Generation " << k << " ***" << std::endl;
178  std::cout << " Best global fitness: " << pop.champion().f << std::endl;
179  std::cout << " xtol: " << dx << ", ftol: " << mah << std::endl;
180  std::cout << " xtol: " << dx << ", ftol: " << mah << std::endl;
181  }
182  }
183 
184  }
185 }
186 
188 std::string cstrs_self_adaptive::get_name() const
189 {
190  return m_original_algo->get_name() + "[Self-Adaptive]";
191 }
192 
194 
198 {
199  return m_original_algo->clone();
200 }
201 
203 
209 {
210  m_original_algo = algo.clone();
211 }
212 
214 
218 {
219  std::ostringstream s;
220  s << "algorithm: " << m_original_algo->get_name() << ' ';
221  s << "\n\tConstraints handled with Self-Adaptive algorithm";
222  return s.str();
223 }
224 
225 }} //namespaces
226 
227 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::algorithm::cstrs_self_adaptive)
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
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
Definition: population.cpp:277
Base algorithm class.
Base problem class.
Definition: problem/base.h:148
Population class.
Definition: population.h:70
bool compare_x(const decision_vector &, const decision_vector &) const
Compare decision vectors.
size_type get_dimension() const
Return global dimension.
base_ptr get_algorithm() const
Get a copy of the internal local algorithm.
decision_vector x
Decision vector.
Definition: population.h:149
virtual base_ptr clone() const =0
Clone method.
fitness_vector f
Fitness vector.
Definition: population.h:153
bool m_screen_output
Indicates to the derived class whether to print stuff on screen.
std::string human_readable_extra() const
Extra human readable algorithm info.
c_size_type get_c_dimension() const
Return global constraints dimension.
cstrs_self_adaptive(const base &=jde(), int gen=1, double=1e-15, double=1e-15)
Constructor.
container_type::size_type size_type
Population size type.
Definition: population.h:192
decision_vector cur_x
Current decision vector.
Definition: population.h:83
void evolve(population &) const
Evolve implementation.
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 get_name() const
Algorithm name.
Self-Adaptive Fitness constraints handling meta-algorithm.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160