PaGMO  1.1.5
mbh.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 "../types.h"
34 #include "base.h"
35 #include "mbh.h"
36 
37 namespace pagmo { namespace algorithm {
38 
40 
50 mbh::mbh(const base & local, int stop, double perturb):base(),m_stop(stop),m_perturb(1,perturb)
51 {
52  m_local = local.clone();
53  if (stop < 0) {
54  pagmo_throw(value_error,"number of consecutive step allowed without any improvement needs to be positive");
55  }
56  if ((perturb < 0) || (perturb > 1)) {
57  pagmo_throw(value_error,"perturb must be positive");
58  }
59 }
60 
62 
72 mbh::mbh(const base & local, int stop, const std::vector<double> &perturb):base(),m_stop(stop),m_perturb(perturb)
73 {
74  m_local = local.clone();
75  if (stop < 0) {
76  pagmo_throw(value_error,"number of consecutive step allowed without any improvement needs to be positive");
77  }
78  for (size_t i=0;i<perturb.size();++i)
79  {
80  if ((perturb[i] < 0 ) || (perturb[i] > 1 )) {
81  pagmo_throw(value_error,"perturb[.] must be in [0,1]");
82  }
83  }
84  if (perturb.size()==0) pagmo_throw(value_error,"perturbation vector appears empty!!");
85 }
86 
88 mbh::mbh(const mbh &algo):base(algo),m_local(algo.m_local->clone()),m_stop(algo.m_stop),m_perturb(algo.m_perturb)
89 {}
90 
93 {
94  return base_ptr(new mbh(*this));
95 }
96 
98 
104 void mbh::evolve(population &pop) const
105 {
106  // Let's store some useful variables.
107  const problem::base &prob = pop.problem();
108  const problem::base::size_type D = prob.get_dimension(), prob_i_dimension = prob.get_i_dimension();
109  const decision_vector &lb = prob.get_lb(), &ub = prob.get_ub();
110  const population::size_type NP = pop.size();
111  const problem::base::size_type Dc = D - prob_i_dimension;
112 
113  //Check if the perturbation vector has size 1, in which case it fills up the whole vector with
114  //the same number
115  if (m_perturb.size()==1)
116  {
117  for (problem::base::size_type i=1;i<D;++i) m_perturb.push_back(m_perturb[0]);
118  }
119 
120  //Check that the perturbation vector size equals the size of the problem
121  if (m_perturb.size()!=D)
122  {
123  pagmo_throw(value_error,"perturbation vector size does not match the problem size");
124  }
125 
126  // Get out if there is nothing to do.
127  if (m_stop == 0 || NP == 0) {
128  return;
129  }
130 
131  // Some dummies and temporary variables
132  decision_vector tmp_x(D), tmp_v(D);
133  double dummy, width;
134 
135  // Init the best fitness and constraint vector
136  population pert_pop(pop);
137 
138  int i = 0;
139 
140  //mbh main loop
141  while (i<m_stop){
142 
143  //1. Perturb the current population
144  pert_pop.clear();
145  for (population::size_type j =0; j < NP; ++j)
146  {
147  for (decision_vector::size_type k=0; k < Dc; ++k)
148  {
149  dummy = pop.get_individual(j).best_x[k];
150  width = m_perturb[k];
151  tmp_x[k] = boost::uniform_real<double>(std::max(dummy-width*(ub[k]-lb[k]),lb[k]),std::min(dummy+width*(ub[k]-lb[k]),ub[k]))(m_drng);
152  dummy = pop.get_individual(j).cur_v[k];
153  tmp_v[k] = boost::uniform_real<double>(dummy-width*(ub[k]-lb[k]),dummy+width*(ub[k]-lb[k]))(m_drng);
154  }
155 
156  for (decision_vector::size_type k=Dc; k < D; ++k)
157  {
158  dummy = pop.get_individual(j).best_x[k];
159  width = m_perturb[k];
160  tmp_x[k] = boost::uniform_int<int>(std::max(dummy-std::floor(width*(ub[k]-lb[k])),lb[k]),std::min(dummy+std::floor(width*(ub[k]-lb[k])),ub[k]))(m_urng);
161  dummy = pop.get_individual(j).cur_v[k];
162  tmp_v[k] = boost::uniform_int<int>(std::max(dummy-std::floor(width*(ub[k]-lb[k])),lb[k]),std::min(dummy+std::floor(width*(ub[k]-lb[k])),ub[k]))(m_urng);
163  }
164  pert_pop.push_back(tmp_x);
165  pop.set_v(j,tmp_v);
166  }
167 
168  //2. Evolve population with selected algorithm
169  m_local->evolve(pert_pop); i++;
170  if (m_screen_output)
171  {
172  std::cout << i << ". " << "\tLocal solution: " << pert_pop.champion().f << "\tGlobal best: " << pop.champion().f;
173  if (!prob.feasibility_x(pop.champion().x)) {
174  std::cout << " i";
175  }
176  std::cout << std::endl;
177  }
178 
179  //3. Reset counter if improved
180  if (pert_pop.problem().compare_fc(pert_pop.champion().f,pert_pop.champion().c,pop.champion().f,pop.champion().c) )
181  {
182  i = 0;
183  if (m_screen_output) {
184  std::cout << "New solution accepted. Constraints vector: " << pert_pop.champion().c << '\n';
185  }
186  //update pop
187  for (population::size_type j=0; j<pop.size();++j)
188  {
189  pop.set_x(j,pert_pop.get_individual(j).best_x);
190  pop.set_v(j,pert_pop.get_individual(j).cur_v);
191  }
192  }
193 
194 
195  }
196 }
197 
199 std::string mbh::get_name() const
200 {
201  return "Generalized Monotonic Basin Hopping";
202 }
203 
205 
209 {
210  return m_local->clone();
211 }
212 
214 
219 void mbh::set_algorithm(const base &algo)
220 {
221  m_local = algo.clone();
222 }
223 
225 
228 std::string mbh::human_readable_extra() const
229 {
230  std::ostringstream s;
231  s << "algorithm: " << m_local->get_name() << ' ';
232  s << "stop:" << m_stop << ' ';
233  s << "perturb:" << m_perturb << ' ';
234  return s.str();
235 }
236 
237 }} //namespaces
238 
239 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::algorithm::mbh)
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
std::string human_readable_extra() const
Extra human readable algorithm info.
Definition: mbh.cpp:228
Root PaGMO namespace.
bool feasibility_x(const decision_vector &) const
Test feasibility of decision vector.
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.
void evolve(population &) const
Evolve implementation.
Definition: mbh.cpp:104
base_ptr clone() const
Clone method.
Definition: mbh.cpp:92
std::string get_name() const
Algorithm name.
Definition: mbh.cpp:199
Base problem class.
Definition: problem/base.h:148
Population class.
Definition: population.h:70
size_type get_dimension() const
Return global dimension.
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.
size_type get_i_dimension() const
Return integer dimension.
decision_vector cur_v
Current velocity vector.
Definition: population.h:85
const decision_vector & get_ub() const
Upper bounds getter.
constraint_vector c
Constraint vector.
Definition: population.h:151
base_ptr get_algorithm() const
Get a copy of the internal local algorithm.
Definition: mbh.cpp:208
container_type::size_type size_type
Population size type.
Definition: population.h:192
rng_uint32 m_urng
Random number generator for unsigned integer values.
Monotonic Basin Hopping (generalized)
Definition: mbh.h:75
bool compare_fc(const fitness_vector &, const constraint_vector &, const fitness_vector &, const constraint_vector &) const
Simultaneous fitness-constraint comparison.
const decision_vector & get_lb() const
Lower bounds getter.
rng_double m_drng
Random number generator for double-precision floating point values.
void set_algorithm(const base &)
Set algorithm.
Definition: mbh.cpp:219
mbh(const base &=cs(), int stop=5, double perturb=5e-2)
Constructor.
Definition: mbh.cpp:50
decision_vector best_x
Best decision vector so far.
Definition: population.h:91
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160