From d7d11150ee005800936f96d7923367250f87839c Mon Sep 17 00:00:00 2001 From: stevenj Date: Mon, 5 Apr 2010 03:16:50 -0400 Subject: [PATCH] add set_max_objective to automate the sign flip for maximization darcs-hash:20100405071650-c8de0-c7d3b05da048406f5004a4c9c46dccd6d2a41100.gz --- api/nlopt-in.hpp | 7 +++++ api/nlopt-internal.h | 3 ++- api/nlopt.h | 7 +++-- api/optimize.c | 63 +++++++++++++++++++++++++++++++++++++++----- api/options.c | 20 ++++++++++++-- auglag/auglag.c | 1 + mma/mma.c | 1 + 7 files changed, 90 insertions(+), 12 deletions(-) diff --git a/api/nlopt-in.hpp b/api/nlopt-in.hpp index dd76746..a4d9144 100644 --- a/api/nlopt-in.hpp +++ b/api/nlopt-in.hpp @@ -130,6 +130,13 @@ namespace nlopt { void set_min_objective(func *f) { set_min_objective(myfunc, f); } + void set_max_objective(nlopt_func f, void *f_data) { + nlopt_result ret = nlopt_set_max_objective(o, f, f_data); + mythrow(ret); + } + void set_max_objective(func *f) { + set_max_objective(myfunc, f); + } // Nonlinear constraints: diff --git a/api/nlopt-internal.h b/api/nlopt-internal.h index 336f77e..8068911 100644 --- a/api/nlopt-internal.h +++ b/api/nlopt-internal.h @@ -38,6 +38,7 @@ struct nlopt_opt_s { unsigned n; /* the dimension of the problem (immutable) */ nlopt_func f; void *f_data; /* objective function to minimize */ + int maximize; /* nonzero if we are maximizing, not minimizing */ double *lb, *ub; /* lower and upper bounds (length n) */ @@ -50,7 +51,7 @@ struct nlopt_opt_s { nlopt_constraint *h; /* equality constraints, length p_alloc */ /* stopping criteria */ - double minf_max; /* stop when f < minf_max */ + double stopval; /* stop when f reaches stopval or better */ double ftol_rel, ftol_abs; /* relative/absolute f tolerances */ double xtol_rel, *xtol_abs; /* rel/abs x tolerances */ int maxeval; /* max # evaluations */ diff --git a/api/nlopt.h b/api/nlopt.h index 7f34090..8c5819a 100644 --- a/api/nlopt.h +++ b/api/nlopt.h @@ -135,7 +135,7 @@ typedef enum { NLOPT_INVALID_ARGS = -2, NLOPT_OUT_OF_MEMORY = -3, NLOPT_ROUNDOFF_LIMITED = -4, - + NLOPT_STOPVAL_REACHED = 2, NLOPT_SUCCESS = 1, /* generic success code */ NLOPT_MINF_MAX_REACHED = 2, NLOPT_FTOL_REACHED = 3, @@ -144,6 +144,7 @@ typedef enum { NLOPT_MAXTIME_REACHED = 6 } nlopt_result; +#define NLOPT_MINF_MAX_REACHED NLOPT_STOPVAL_REACHED NLOPT_EXTERN void nlopt_srand(unsigned long seed); NLOPT_EXTERN void nlopt_srand_time(void); @@ -173,6 +174,8 @@ NLOPT_EXTERN nlopt_result nlopt_optimize(nlopt_opt opt, double *x, NLOPT_EXTERN nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data); +NLOPT_EXTERN nlopt_result nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, + void *f_data); NLOPT_EXTERN nlopt_algorithm nlopt_get_algorithm(const nlopt_opt opt); NLOPT_EXTERN unsigned nlopt_get_dimension(const nlopt_opt opt); @@ -204,7 +207,7 @@ NLOPT_EXTERN nlopt_result nlopt_add_equality_constraint(nlopt_opt opt, /* stopping criteria: */ -NLOPT_EXTERN nlopt_result nlopt_set_stopval(nlopt_opt opt, double minf_max); +NLOPT_EXTERN nlopt_result nlopt_set_stopval(nlopt_opt opt, double stopval); NLOPT_EXTERN double nlopt_get_stopval(const nlopt_opt opt); NLOPT_EXTERN nlopt_result nlopt_set_ftol_rel(nlopt_opt opt, double tol); diff --git a/api/optimize.c b/api/optimize.c index b1448f2..6c70bd6 100644 --- a/api/optimize.c +++ b/api/optimize.c @@ -69,8 +69,6 @@ typedef struct { const double *lb, *ub; } nlopt_data; -#include "praxis.h" - static double f_bound(int n, const double *x, void *data_) { int i; @@ -142,7 +140,8 @@ static int finite_domain(unsigned n, const double *lb, const double *ub) (nlopt_stochastic_population > 0 ? \ nlopt_stochastic_population : (defaultpop))) -nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *minf) +/* unlike nlopt_optimize() below, only handles minimization case */ +static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) { const double *lb, *ub; nlopt_algorithm algorithm; @@ -152,8 +151,9 @@ nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *minf) nlopt_data d; nlopt_stopping stop; - if (!opt || !x || !minf || !opt->f) return NLOPT_INVALID_ARGS; - + if (!opt || !x || !minf || !opt->f + || opt->maximize) return NLOPT_INVALID_ARGS; + /* copy a few params to local vars for convenience */ n = opt->n; ni = (int) n; /* most of the subroutines take "int" arg */ @@ -162,7 +162,7 @@ nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *minf) f = opt->f; f_data = opt->f_data; if (n == 0) { /* trivial case: no degrees of freedom */ - *minf = f(n, x, NULL, f_data); + *minf = opt->f(n, x, NULL, opt->f_data); return NLOPT_SUCCESS; } @@ -183,7 +183,7 @@ nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *minf) return NLOPT_INVALID_ARGS; stop.n = n; - stop.minf_max = opt->minf_max; + stop.minf_max = opt->stopval; stop.ftol_rel = opt->ftol_rel; stop.ftol_abs = opt->ftol_abs; stop.xtol_rel = opt->xtol_rel; @@ -512,6 +512,55 @@ nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *minf) /*********************************************************************/ +typedef struct { + nlopt_func f; + void *f_data; +} f_max_data; + +/* wrapper for maximizing: just flip the sign of f and grad */ +static double f_max(unsigned n, const double *x, double *grad, void *data) +{ + f_max_data *d = (f_max_data *) data; + double val = d->f(n, x, grad, d->f_data); + if (grad) { + unsigned i; + for (i = 0; i < n; ++i) + grad[i] = -grad[i]; + } + return -val; +} + +nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *opt_f) +{ + nlopt_func f; void *f_data; + f_max_data fmd; + int maximize; + nlopt_result ret; + + if (!opt || !opt_f || !opt->f) return NLOPT_INVALID_ARGS; + f = opt->f; f_data = opt->f_data; + + /* for maximizing, just minimize the f_max wrapper, which + flips the sign of everything */ + if ((maximize = opt->maximize)) { + fmd.f = f; fmd.f_data = f_data; + opt->f = f_max; opt->f_data = &fmd; + opt->stopval = -opt->stopval; + } + + ret = nlopt_optimize_(opt, x, opt_f); + + if (maximize) { /* restore original signs */ + opt->stopval = -opt->stopval; + opt->f = f; opt->f_data = f_data; + *opt_f = -*opt_f; + } + + return ret; +} + +/*********************************************************************/ + nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf, int maxeval, double maxtime) { diff --git a/api/options.c b/api/options.c index af50c4d..038256e 100644 --- a/api/options.c +++ b/api/options.c @@ -56,6 +56,7 @@ nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n) opt->algorithm = algorithm; opt->n = n; opt->f = NULL; opt->f_data = NULL; + opt->maximize = 0; opt->lb = opt->ub = NULL; opt->m = opt->m_alloc = 0; @@ -63,7 +64,7 @@ nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n) opt->p = opt->p_alloc = 0; opt->h = NULL; - opt->minf_max = -HUGE_VAL; + opt->stopval = -HUGE_VAL; opt->ftol_rel = opt->ftol_abs = 0; opt->xtol_rel = 0; opt->xtol_abs = NULL; opt->maxeval = 0; @@ -158,6 +159,21 @@ nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) { if (opt && f) { opt->f = f; opt->f_data = f_data; + opt->maximize = 0; + if (nlopt_isinf(opt->stopval) && opt->stopval > 0) + opt->stopval = -HUGE_VAL; + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +nlopt_result nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data) +{ + if (opt && f) { + opt->f = f; opt->f_data = f_data; + opt->maximize = 1; + if (nlopt_isinf(opt->stopval) && opt->stopval < 0) + opt->stopval = +HUGE_VAL; return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; @@ -323,7 +339,7 @@ nlopt_result nlopt_add_equality_constraint(nlopt_opt opt, #define GETSET(param, T, arg) GET(param, T, arg) SET(param, T, arg) -GETSET(stopval, double, minf_max) +GETSET(stopval, double, stopval) GETSET(ftol_rel, double, ftol_rel) GETSET(ftol_abs, double, ftol_abs) diff --git a/auglag/auglag.c b/auglag/auglag.c index 808d20e..c5b65f0 100644 --- a/auglag/auglag.c +++ b/auglag/auglag.c @@ -91,6 +91,7 @@ nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, ret = nlopt_set_min_objective(sub_opt, auglag, &d); if (ret<0) return ret; ret = nlopt_set_lower_bounds(sub_opt, lb); if (ret<0) return ret; ret = nlopt_set_upper_bounds(sub_opt, ub); if (ret<0) return ret; + ret = nlopt_set_stopval(sub_opt, stop->minf_max); if (ret<0) return ret; ret = nlopt_remove_inequality_constraints(sub_opt); if (ret<0) return ret; ret = nlopt_remove_equality_constraints(sub_opt); if (ret<0) return ret; for (i = 0; i < m; ++i) { diff --git a/mma/mma.c b/mma/mma.c index 3451b49..feba141 100644 --- a/mma/mma.c +++ b/mma/mma.c @@ -231,6 +231,7 @@ nlopt_result mma_minimize(int n, nlopt_func f, void *f_data, nlopt_set_min_objective(dual_opt, dual_func, &dd); nlopt_set_lower_bounds(dual_opt, dual_lb); nlopt_set_upper_bounds(dual_opt, dual_ub); + nlopt_set_stopval(dual_opt, -HUGE_VAL); while (1) { /* outer iterations */ double fprev = fcur; -- 2.30.2