PaGMO  1.1.5
gsl_derivative_free.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 <algorithm>
26 #include <boost/numeric/conversion/cast.hpp>
27 #include <cstddef>
28 #include <exception>
29 #include <gsl/gsl_multimin.h>
30 #include <gsl/gsl_vector.h>
31 #include <new>
32 #include <sstream>
33 #include <stdexcept>
34 #include <string>
35 
36 #include "../exceptions.h"
37 #include "../population.h"
38 #include "../problem/base.h"
39 #include "../types.h"
40 #include "base_gsl.h"
41 #include "gsl_derivative_free.h"
42 
43 namespace pagmo { namespace algorithm {
44 
46 
54 gsl_derivative_free::gsl_derivative_free(int max_iter, const double &tol, const double &step_size):
55  base_gsl(),m_max_iter(boost::numeric_cast<std::size_t>(max_iter)),m_tol(tol),m_step_size(step_size)
56 {
57  if (step_size <= 0) {
58  pagmo_throw(value_error,"step size must be positive");
59  }
60  if (tol <= 0) {
61  pagmo_throw(value_error,"tolerance must be positive");
62  }
63 }
64 
66 
70 {
71  std::ostringstream oss;
72  oss << "max_iter:" << m_max_iter << ' ';
73  oss << "tol:" << m_tol << ' ';
74  oss << "step_size:" << m_step_size << ' ';
75  return oss.str();
76 }
77 
79 
89 {
90  // Do nothing if the population is empty.
91  if (!pop.size()) {
92  return;
93  }
94  // Useful variables.
95  const problem::base &problem = pop.problem();
96  if (problem.get_f_dimension() != 1) {
97  pagmo_throw(value_error,"this algorithm does not support multi-objective optimisation");
98  }
99  if (problem.get_c_dimension()) {
100  pagmo_throw(value_error,"this algorithm does not support constrained optimisation");
101  }
102  const problem::base::size_type cont_size = problem.get_dimension() - problem.get_i_dimension();
103  if (!cont_size) {
104  pagmo_throw(value_error,"the problem has no continuous part");
105  }
106  // Extract the best individual.
107  const population::size_type best_ind_idx = pop.get_best_idx();
108  const population::individual_type &best_ind = pop.get_individual(best_ind_idx);
109  // GSL wrapper parameters structure.
110  objfun_wrapper_params params;
111  params.p = &problem;
112  // Integer part of the temporay decision vector must be filled with the integer part of the best individual,
113  // which will not be optimised.
114  params.x.resize(problem.get_dimension());
115  std::copy(best_ind.cur_x.begin() + cont_size, best_ind.cur_x.end(), params.x.begin() + cont_size);
116  params.f.resize(1);
117  // GSL function structure.
118  gsl_multimin_function gsl_func;
119  // Number of function components.
120  gsl_func.n = boost::numeric_cast<std::size_t>(cont_size);
121  gsl_func.f = &objfun_wrapper;
122  gsl_func.params = (void *)&params;
123  // Mimimizer.
124  gsl_multimin_fminimizer *s = 0;
125  // Starting point and step sizes.
126  gsl_vector *x = 0, *ss = 0;
127  // Here we start the allocations.
128  // Recast as size_t here, in order to avoid potential overflows later.
129  const std::size_t s_cont_size = boost::numeric_cast<std::size_t>(cont_size);
130  // Allocate and check the allocation results.
131  x = gsl_vector_alloc(s_cont_size);
132  ss = gsl_vector_alloc(s_cont_size);
133  const gsl_multimin_fminimizer_type *minimiser = get_gsl_minimiser_ptr();
134  pagmo_assert(minimiser);
135  s = gsl_multimin_fminimizer_alloc(minimiser,s_cont_size);
136  // Check the allocations.
137  check_allocs(x,ss,s);
138  // Starting point comes from the best individual.
139  for (std::size_t i = 0; i < s_cont_size; ++i) {
140  gsl_vector_set(x,i,best_ind.cur_x[i]);
141  }
142  // Set initial step sizes.
143  gsl_vector_set_all(ss,m_step_size);
144  // Init the solver.
145  gsl_multimin_fminimizer_set(s,&gsl_func,x,ss);
146  // Iterate.
147  std::size_t iter = 0;
148  int status;
149  double size;
150  try {
151  do
152  {
153  status = gsl_multimin_fminimizer_iterate(s);
154  ++iter;
155  if (status) {
156  break;
157  }
158  size = gsl_multimin_fminimizer_size(s);
159  status = gsl_multimin_test_size(size, m_tol);
160  if (m_screen_output) {
161  if (!((iter-1)%20)) {
162  std::cout << std::endl << std::left << std::setw(20) <<
163  "Iter." << std::setw(20) <<
164  "Best " << std::setw(20) <<
165  "Size "<< std::endl;
166  }
167  std::cout << std::left << std::setprecision(14) << std::setw(20) <<
168  iter << std::setw(20) <<
169  gsl_multimin_fminimizer_minimum(s) << std::setw(20) <<
170  size << std::endl;
171  }
172  } while (status == GSL_CONTINUE && iter < m_max_iter);
173  } catch (const std::exception &e) {
174  // Cleanup and re-throw.
175  cleanup(x,ss,s);
176  throw e;
177  } catch (...) {
178  // Cleanup and throw.
179  cleanup(x,ss,s);
180  pagmo_throw(std::runtime_error,"unknown exception caught in gsl_derivative_free::evolve");
181  }
182  // Free up resources.
183  cleanup(x,ss,s);
184  // Check the generated individual and change it to respect the bounds as necessary.
185  for (problem::base::size_type i = 0; i < cont_size; ++i) {
186  if (params.x[i] < problem.get_lb()[i]) {
187  params.x[i] = problem.get_lb()[i];
188  }
189  if (params.x[i] > problem.get_ub()[i]) {
190  params.x[i] = problem.get_ub()[i];
191  }
192  }
193  // Replace the best individual.
194  pop.set_x(best_ind_idx,params.x);
195 }
196 
197 // Check GSL allocations done during evolve().
198 void gsl_derivative_free::check_allocs(gsl_vector *x, gsl_vector *ss, gsl_multimin_fminimizer *s)
199 {
200  // If at least one allocation failed, cleanup and throw a memory error.
201  if (!x || !ss || !s) {
202  cleanup(x,ss,s);
203  throw std::bad_alloc();
204  }
205 }
206 
207 // Cleanup allocations done during evolve.
208 void gsl_derivative_free::cleanup(gsl_vector *x, gsl_vector *ss, gsl_multimin_fminimizer *s)
209 {
210  if (x) {
211  gsl_vector_free(x);
212  }
213  if (ss) {
214  gsl_vector_free(ss);
215  }
216  if (s) {
217  gsl_multimin_fminimizer_free(s);
218  }
219 }
220 
221 }}
Root PaGMO namespace.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
Definition: population.cpp:277
Individuals stored in the population.
Definition: population.h:80
STL namespace.
Base problem class.
Definition: problem/base.h:148
Population class.
Definition: population.h:70
size_type get_dimension() const
Return global dimension.
Base class for GSL algorithms.
Definition: base_gsl.h:56
std::string human_readable_extra() const
Extra information in human-readable format.
virtual const gsl_multimin_fminimizer_type * get_gsl_minimiser_ptr() const =0
Selected minimiser.
fitness_vector f
Fitness vector.
Definition: base_gsl.h:69
bool m_screen_output
Indicates to the derived class whether to print stuff on screen.
void evolve(population &) const
Evolve method.
size_type get_i_dimension() const
Return integer dimension.
c_size_type get_c_dimension() const
Return global constraints dimension.
const decision_vector & get_ub() const
Upper bounds getter.
container_type::size_type size_type
Population size type.
Definition: population.h:192
static double objfun_wrapper(const gsl_vector *, void *)
Objective function wrapper.
Definition: base_gsl.cpp:67
decision_vector cur_x
Current decision vector.
Definition: population.h:83
Structure to feed parameters to the wrappers for the objective function and its derivative.
Definition: base_gsl.h:62
f_size_type get_f_dimension() const
Return fitness dimension.
gsl_derivative_free(int, const double &, const double &)
Constructor.
decision_vector x
Decision vector.
Definition: base_gsl.h:67
problem::base const * p
Pointer to the problem.
Definition: base_gsl.h:65
const decision_vector & get_lb() const
Lower bounds getter.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160