DiFfRG
Loading...
Searching...
No Matches
minimization.hh
Go to the documentation of this file.
1#pragma once
2
3// standard library
4#include <array>
5#include <functional>
6#include <stdexcept>
7
8// external libraries
9#include <gsl/gsl_errno.h>
10#include <gsl/gsl_math.h>
11#include <gsl/gsl_multimin.h>
12
13namespace DiFfRG
14{
20 template <int dim> class AbstractMinimizer
21 {
22 protected:
23 using FUN = std::function<double(const std::array<double, dim> &)>;
24
25 public:
33 AbstractMinimizer(const FUN &f, const double abs_tol = 1e-4, const int max_iter = 1000)
35 {
36 }
37
43 void set_abs_tol(const double abs_tol) { this->abs_tol = abs_tol; }
44
50 void set_max_iter(const uint max_iter) { this->max_iter = max_iter; }
51
57 uint get_iter() const { return iter; }
58
64 std::array<double, dim> minimize() { return this->minimize_impl(); }
65
66 protected:
68
69 double abs_tol;
72
73 virtual std::array<double, dim> minimize_impl() = 0;
74 };
75
76 // explicit specialization for 1D minimization
77 template <> class AbstractMinimizer<1>
78 {
79 protected:
80 using FUN = std::function<double(const double)>;
81 using FUN_ARR = std::function<double(const std::array<double, 1> &)>;
82
83 public:
91 AbstractMinimizer(const FUN &f, const double abs_tol = 1e-4, const int max_iter = 1000)
92 : f([f](const std::array<double, 1> &x) { return f(x[0]); }), abs_tol(abs_tol), max_iter(max_iter), iter(0)
93 {
94 }
95
103 AbstractMinimizer(const FUN_ARR &f, const double abs_tol = 1e-4, const int max_iter = 1000)
105 {
106 }
107
113 void set_abs_tol(const double abs_tol) { this->abs_tol = abs_tol; }
114
120 void set_max_iter(const uint max_iter) { this->max_iter = max_iter; }
121
127 uint get_iter() const { return iter; }
128
134 double minimize() { return this->minimize_impl()[0]; }
135
136 protected:
138
139 double abs_tol;
142
143 virtual std::array<double, 1> minimize_impl() = 0;
144 };
145
151 template <int dim> class GSLSimplexMinimizer : public AbstractMinimizer<dim>
152 {
154
155 public:
163 GSLSimplexMinimizer(const FUN &f, const double abs_tol = 1e-4, const int max_iter = 1000)
165 {
166 gsl_set_error_handler_off();
167 }
168
174 void set_step_size(const double step_size) { this->step_size = step_size; }
175
181 void set_x0(const std::array<double, dim> &x0) { this->x0 = x0; }
182
183 static double gsl_wrap(const gsl_vector *v, void *params)
184 {
186 std::array<double, dim> x;
187 for (int i = 0; i < dim; ++i)
188 x[i] = gsl_vector_get(v, i);
189 return self->f(x);
190 }
191
192 protected:
193 virtual std::array<double, dim> minimize_impl() override
194 {
195 gsl_multimin_function gsl_f;
196 gsl_f.n = dim;
198 gsl_f.params = this;
199
200 gsl_vector *x = gsl_vector_alloc(dim);
201 for (int i = 0; i < dim; ++i)
202 gsl_vector_set(x, i, x0[i]);
203
204 gsl_vector *init_step = gsl_vector_alloc(dim);
205 gsl_vector_set_all(init_step, step_size);
206
207 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2;
208 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, dim);
209
210 gsl_multimin_fminimizer_set(s, &gsl_f, x, init_step);
211
212 int status;
213 this->iter = 0;
214 do {
215 this->iter++;
216 status = gsl_multimin_fminimizer_iterate(s);
217 if (status) break;
218
219 double size = gsl_multimin_fminimizer_size(s);
220 status = gsl_multimin_test_size(size, this->abs_tol);
221
222 if (status == GSL_SUCCESS) break;
223
224 } while (status == GSL_CONTINUE && this->iter < this->max_iter);
225
226 if (status != GSL_SUCCESS) throw std::runtime_error("Minimization failed.");
227
228 std::array<double, dim> result;
229 for (int i = 0; i < dim; ++i)
230 result[i] = gsl_vector_get(s->x, i);
231
232 gsl_multimin_fminimizer_free(s);
233 gsl_vector_free(x);
234
235 return result;
236 }
237
238 std::array<double, dim> x0;
239 double step_size;
240 };
241
246 {
248
249 public:
257 GSLMinimizer1D(const FUN &f, const double abs_tol = 1e-4, const int max_iter = 1000)
258 : AbstractMinimizer<1>(f, abs_tol, max_iter), x0(0.), min_x(-1.), max_x(1.), rel_tol(0.), m(method::brent)
259 {
260 gsl_set_error_handler_off();
261 }
262
267
273 void set_x0(const double x0) { this->x0 = x0; }
274
281 void set_bounds(const double min_x, const double max_x)
282 {
283 this->min_x = min_x;
284 this->max_x = max_x;
285 }
286
292 void set_method(const method m) { this->m = m; }
293
299 void set_rel_tol(const double rel_tol) { this->rel_tol = rel_tol; }
300
301 protected:
302 virtual std::array<double, 1> minimize_impl() override
303 {
304 gsl_function gsl_f;
305 gsl_f.function = &GSLMinimizer1D::gsl_wrap;
306 gsl_f.params = this;
307
308 const gsl_min_fminimizer_type *T;
309 switch (this->m) {
310 case golden_section:
311 T = gsl_min_fminimizer_goldensection;
312 break;
313 case brent:
314 T = gsl_min_fminimizer_brent;
315 break;
316 case quadratic:
317 T = gsl_min_fminimizer_quad_golden;
318 break;
319 default:
320 throw std::runtime_error("Unknown minimization method.");
321 }
322
323 gsl_min_fminimizer *s = gsl_min_fminimizer_alloc(T);
324
325 double x = this->x0 < this->min_x || this->x0 > this->max_x ? 0.5 * (this->min_x + this->max_x) : this->x0;
326 double x_lo = this->min_x;
327 double x_hi = this->max_x;
328
329 gsl_min_fminimizer_set(s, &gsl_f, x, x_lo, x_hi);
330
331 double prev_x = -x;
332 int status;
333 this->iter = 0;
334 int stuck = 0;
335 do {
336 this->iter++;
337 status = gsl_min_fminimizer_iterate(s);
338
339 x = gsl_min_fminimizer_x_minimum(s);
340 x_lo = gsl_min_fminimizer_x_lower(s);
341 x_hi = gsl_min_fminimizer_x_upper(s);
342
343 status = gsl_min_test_interval(x_lo, x_hi, this->abs_tol, this->rel_tol);
344
345 if (is_close(x, prev_x)) stuck++;
346 if (stuck > 3) std::runtime_error("Minimization got stuck at x = " + std::to_string(x));
347 prev_x = x;
348
349 } while (status == GSL_CONTINUE && this->iter < this->max_iter);
350
351 if (status != GSL_SUCCESS) throw std::runtime_error("Minimization failed.");
352
353 gsl_min_fminimizer_free(s);
354
355 return {x};
356 }
357
358 static double gsl_wrap(double x, void *params)
359 {
360 GSLMinimizer1D *self = (GSLMinimizer1D *)params;
361 return self->f({{x}});
362 }
363
364 double x0;
365 double min_x, max_x;
366 double rel_tol;
368 };
369} // namespace DiFfRG
double minimize()
Perform the minimization.
Definition minimization.hh:134
uint iter
Definition minimization.hh:141
std::function< double(const std::array< double, 1 > &)> FUN_ARR
Definition minimization.hh:81
virtual std::array< double, 1 > minimize_impl()=0
void set_abs_tol(const double abs_tol)
Set the absolute tolerance for the minimization.
Definition minimization.hh:113
uint get_iter() const
Get the number of iterations used in the last minimization.
Definition minimization.hh:127
AbstractMinimizer(const FUN &f, const double abs_tol=1e-4, const int max_iter=1000)
Construct a new AbstractMinimizer object.
Definition minimization.hh:91
void set_max_iter(const uint max_iter)
Set the maximum number of iterations.
Definition minimization.hh:120
double abs_tol
Definition minimization.hh:139
AbstractMinimizer(const FUN_ARR &f, const double abs_tol=1e-4, const int max_iter=1000)
Construct a new AbstractMinimizer object.
Definition minimization.hh:103
FUN_ARR f
Definition minimization.hh:137
std::function< double(const double)> FUN
Definition minimization.hh:80
uint max_iter
Definition minimization.hh:140
Abstract class for minimization in arbitrary dimensions.
Definition minimization.hh:21
uint iter
Definition minimization.hh:71
void set_max_iter(const uint max_iter)
Set the maximum number of iterations.
Definition minimization.hh:50
uint max_iter
Definition minimization.hh:70
std::function< double(const std::array< double, dim > &)> FUN
Definition minimization.hh:23
FUN f
Definition minimization.hh:67
AbstractMinimizer(const FUN &f, const double abs_tol=1e-4, const int max_iter=1000)
Construct a new AbstractMinimizer object.
Definition minimization.hh:33
double abs_tol
Definition minimization.hh:69
uint get_iter() const
Get the number of iterations used in the last minimization.
Definition minimization.hh:57
void set_abs_tol(const double abs_tol)
Set the absolute tolerance for the minimization.
Definition minimization.hh:43
std::array< double, dim > minimize()
Perform the minimization.
Definition minimization.hh:64
virtual std::array< double, dim > minimize_impl()=0
Minimizer in 1D using either the golden section, Brent or quadratic method from GSL.
Definition minimization.hh:246
static double gsl_wrap(double x, void *params)
Definition minimization.hh:358
method
List of available minimization methods.
Definition minimization.hh:266
@ quadratic
Definition minimization.hh:266
@ brent
Definition minimization.hh:266
@ golden_section
Definition minimization.hh:266
void set_bounds(const double min_x, const double max_x)
Set the bounds for the minimization.
Definition minimization.hh:281
AbstractMinimizer< 1 >::FUN FUN
Definition minimization.hh:247
void set_x0(const double x0)
Set the initial guess for the minimization.
Definition minimization.hh:273
void set_rel_tol(const double rel_tol)
Set the relative tolerance for the minimization. Default is 0.
Definition minimization.hh:299
double max_x
Definition minimization.hh:365
GSLMinimizer1D(const FUN &f, const double abs_tol=1e-4, const int max_iter=1000)
Construct a new GSLMinimizer1D object.
Definition minimization.hh:257
method m
Definition minimization.hh:367
double x0
Definition minimization.hh:364
double min_x
Definition minimization.hh:365
virtual std::array< double, 1 > minimize_impl() override
Definition minimization.hh:302
void set_method(const method m)
Set the minimization method. Default is Brent.
Definition minimization.hh:292
double rel_tol
Definition minimization.hh:366
Minimizer using the Nelder-Mead simplex algorithm from GSL.
Definition minimization.hh:152
virtual std::array< double, dim > minimize_impl() override
Definition minimization.hh:193
AbstractMinimizer< dim >::FUN FUN
Definition minimization.hh:153
static double gsl_wrap(const gsl_vector *v, void *params)
Definition minimization.hh:183
void set_x0(const std::array< double, dim > &x0)
Set the initial guess for the minimization.
Definition minimization.hh:181
double step_size
Definition minimization.hh:239
std::array< double, dim > x0
Definition minimization.hh:238
GSLSimplexMinimizer(const FUN &f, const double abs_tol=1e-4, const int max_iter=1000)
Construct a new GSLSimplexMinimizer object.
Definition minimization.hh:163
void set_step_size(const double step_size)
Set the initial step size for the minimization.
Definition minimization.hh:174
Definition complex_math.hh:14
bool __forceinline__ __host__ __device__ is_close(T1 a, T2 b, T3 eps_)
Function to evaluate whether two floats are equal to numerical precision. Tests for both relative and...
Definition math.hh:160
unsigned int uint
Definition utils.hh:22
Definition tuples.hh:117