26 #include <boost/numeric/conversion/cast.hpp>
29 #include <gsl/gsl_deriv.h>
30 #include <gsl/gsl_multimin.h>
31 #include <gsl/gsl_vector.h>
37 #include "../exceptions.h"
38 #include "../population.h"
39 #include "../problem/base.h"
42 #include "gsl_gradient.h"
44 namespace pagmo {
namespace algorithm {
57 gsl_gradient::gsl_gradient(
int max_iter,
const double &grad_tol,
const double &numdiff_step_size,
const double &step_size,
const double &tol):
59 m_max_iter(
boost::numeric_cast<
std::size_t>(max_iter)),m_grad_tol(grad_tol),m_numdiff_step_size(numdiff_step_size),
60 m_step_size(step_size),m_tol(tol)
63 pagmo_throw(value_error,
"step size must be positive");
66 pagmo_throw(value_error,
"tolerance must be positive");
68 if (numdiff_step_size <= 0) {
69 pagmo_throw(value_error,
"step size for numerical differentiation must be positive");
72 pagmo_throw(value_error,
"gradient tolerance must be positive");
77 double gsl_gradient::objfun_numdiff_wrapper(
double x,
void *params)
79 objfun_numdiff_wrapper_params *pars = (objfun_numdiff_wrapper_params *)params;
80 pars->x[pars->coord] = x;
81 pars->prob->objfun(pars->f,pars->x);
86 void gsl_gradient::objfun_numdiff_central(gsl_vector *retval,
const problem::base &prob,
const decision_vector &input,
const double &step_size)
89 pagmo_throw(value_error,
"invalid input vector dimension in numerical differentiation of the objective function");
92 pagmo_throw(value_error,
"numerical differentiation of the objective function cannot work on multi-objective problems");
97 objfun_numdiff_wrapper_params pars;
103 F.function = &objfun_numdiff_wrapper;
104 F.params = (
void *)&pars;
105 double result, abserr;
109 gsl_deriv_central(&F,input[i],step_size,&result,&abserr);
110 gsl_vector_set(retval,i,result);
115 void gsl_gradient::d_objfun_wrapper(
const gsl_vector *v,
void *params, gsl_vector *df)
117 objfun_wrapper_params *par = (objfun_wrapper_params *)params;
122 par->x[i] = gsl_vector_get(v,i);
125 objfun_numdiff_central(df,*par->p,par->x,par->step_size);
129 void gsl_gradient::fd_objfun_wrapper(
const gsl_vector *v,
void *params,
double *retval, gsl_vector *df)
132 d_objfun_wrapper(v,params,df);
154 pagmo_throw(value_error,
"this algorithm does not support multi-objective optimisation");
157 pagmo_throw(value_error,
"this algorithm does not support constrained optimisation");
161 pagmo_throw(value_error,
"the problem has no continuous part");
172 std::copy(best_ind.
cur_x.begin() + cont_size, best_ind.
cur_x.end(), params.
x.begin() + cont_size);
176 gsl_multimin_function_fdf gsl_func;
177 gsl_func.n = boost::numeric_cast<std::size_t>(cont_size);
179 gsl_func.df = &d_objfun_wrapper;
180 gsl_func.fdf = &fd_objfun_wrapper;
181 gsl_func.params = (
void *)¶ms;
183 gsl_multimin_fdfminimizer *s = 0;
188 const std::size_t s_cont_size = boost::numeric_cast<std::size_t>(cont_size);
190 x = gsl_vector_alloc(s_cont_size);
192 pagmo_assert(minimiser);
193 s = gsl_multimin_fdfminimizer_alloc(minimiser,s_cont_size);
197 for (std::size_t i = 0; i < s_cont_size; ++i) {
198 gsl_vector_set(x,i,best_ind.
cur_x[i]);
201 gsl_multimin_fdfminimizer_set(s,&gsl_func,x,m_step_size,m_tol);
203 std::size_t iter = 0;
209 status = gsl_multimin_fdfminimizer_iterate(s);
213 status = gsl_multimin_test_gradient(s->gradient,m_grad_tol);
214 }
while (status == GSL_CONTINUE && iter < m_max_iter);
215 }
catch (
const std::exception &e) {
222 pagmo_throw(std::runtime_error,
"unknown exception caught in gsl_gradient::evolve");
228 if (params.
x[i] < problem.
get_lb()[i]) {
229 params.
x[i] = problem.
get_lb()[i];
231 if (params.
x[i] > problem.
get_ub()[i]) {
232 params.
x[i] = problem.
get_ub()[i];
236 pop.set_x(best_ind_idx,params.
x);
240 void gsl_gradient::check_allocs(gsl_vector *x, gsl_multimin_fdfminimizer *s)
245 throw std::bad_alloc();
250 void gsl_gradient::cleanup(gsl_vector *x, gsl_multimin_fdfminimizer *s)
256 gsl_multimin_fdfminimizer_free(s);
266 std::ostringstream oss;
267 oss <<
"max_iter: " << m_max_iter <<
' ';
268 oss <<
"step_size: " << m_step_size <<
' ';
269 oss <<
"tol: " << m_tol <<
' ';
270 oss <<
"grad_step_size: " << m_numdiff_step_size <<
' ';
271 oss <<
"grad_tol: " << m_grad_tol <<
' ';
std::vector< double > decision_vector
Decision vector type.
virtual const gsl_multimin_fdfminimizer_type * get_gsl_minimiser_ptr() const =0
Selected minimiser.
double step_size
Initial step size for the computation of the gradient.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
Individuals stored in the population.
void evolve(population &) const
Evolve method.
size_type get_dimension() const
Return global dimension.
Base class for GSL algorithms.
gsl_gradient(int, const double &, const double &, const double &, const double &)
Constructor.
std::string human_readable_extra() const
Extra information in human-readable format.
fitness_vector f
Fitness vector.
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.
static double objfun_wrapper(const gsl_vector *, void *)
Objective function wrapper.
decision_vector cur_x
Current decision vector.
Structure to feed parameters to the wrappers for the objective function and its derivative.
f_size_type get_f_dimension() const
Return fitness dimension.
decision_vector x
Decision vector.
problem::base const * p
Pointer to the problem.
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.