From e4d7f03b782427fed448a48fa0d850f9db92305f Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Tue, 14 Nov 2017 18:16:49 +0100 Subject: [PATCH] Add nlopt_get_numevals (#160) * Add nlopt_get_numevals We reuse stop.nevals which becomes stop.nevals_p, a pointer to opt.numevals, an int that we can return to the user. * Add doc --- api/f77funcs_.h | 1 + api/nlopt-in.hpp | 6 +++++ api/nlopt-internal.h | 1 + api/nlopt.h | 2 ++ api/optimize.c | 2 +- api/options.c | 3 +++ auglag/auglag.c | 8 +++---- bobyqa/bobyqa.c | 30 ++++++++++++------------- cdirect/cdirect.c | 2 +- cdirect/hybrid.c | 10 ++++----- cobyla/cobyla.c | 20 ++++++++--------- cquad/cquad.c | 6 ++--- crs/crs.c | 6 ++--- doc/docs/NLopt_C-plus-plus_Reference.md | 7 ++++++ doc/docs/NLopt_Fortran_Reference.md | 8 +++++++ doc/docs/NLopt_Guile_Reference.md | 8 +++++++ doc/docs/NLopt_Python_Reference.md | 11 +++++++++ doc/docs/NLopt_Reference.md | 8 +++++++ doc/docs/NLopt_release_notes.md | 1 + esch/esch.c | 4 ++-- isres/isres.c | 2 +- luksan/luksan.h | 2 +- luksan/plip.c | 4 ++-- luksan/plis.c | 4 ++-- luksan/pnet.c | 6 ++--- mlsl/mlsl.c | 8 +++---- mma/ccsa_quadratic.c | 4 ++-- mma/mma.c | 4 ++-- neldermead/nldrmd.c | 4 ++-- neldermead/sbplx.c | 12 +++++----- newuoa/newuoa.c | 4 ++-- praxis/praxis.c | 4 ++-- slsqp/slsqp.c | 2 +- stogo/local.cc | 6 ++--- subplex/subplex.c | 14 ++++++------ test/t_python.py | 7 +++--- util/nlopt-util.h | 2 +- util/stop.c | 2 +- 38 files changed, 146 insertions(+), 89 deletions(-) diff --git a/api/f77funcs_.h b/api/f77funcs_.h index a8534fd..1f10ba2 100644 --- a/api/f77funcs_.h +++ b/api/f77funcs_.h @@ -148,6 +148,7 @@ F77_GETSET(ftol_abs, FTOL_ABS, double) F77_GETSET(xtol_rel, XTOL_REL, double) F77_GETSETA(xtol_abs, XTOL_ABS, double) F77_GETSET(maxeval, MAXEVAL, int) +F77_GET(numevals, NUMEVALS, int) F77_GETSET(maxtime, MAXTIME, double) F77_GETSET(force_stop, FORCE_STOP, int) diff --git a/api/nlopt-in.hpp b/api/nlopt-in.hpp index 582c676..d742c0a 100644 --- a/api/nlopt-in.hpp +++ b/api/nlopt-in.hpp @@ -463,6 +463,12 @@ namespace nlopt { NLOPT_GETSET(double, xtol_rel) NLOPT_GETSET_VEC(xtol_abs) NLOPT_GETSET(int, maxeval) + + int get_numevals() const { + if (!o) throw std::runtime_error("uninitialized nlopt::opt"); + return nlopt_get_numevals(o); + } + NLOPT_GETSET(double, maxtime) NLOPT_GETSET(int, force_stop) diff --git a/api/nlopt-internal.h b/api/nlopt-internal.h index c4d13d1..b1aa318 100644 --- a/api/nlopt-internal.h +++ b/api/nlopt-internal.h @@ -58,6 +58,7 @@ struct nlopt_opt_s { double ftol_rel, ftol_abs; /* relative/absolute f tolerances */ double xtol_rel, *xtol_abs; /* rel/abs x tolerances */ int maxeval; /* max # evaluations */ + int numevals; /* number of evaluations */ double maxtime; /* max time (seconds) */ int force_stop; /* if nonzero, force a halt the next time we diff --git a/api/nlopt.h b/api/nlopt.h index a0e6b38..328b6d0 100644 --- a/api/nlopt.h +++ b/api/nlopt.h @@ -272,6 +272,8 @@ NLOPT_EXTERN(nlopt_result) nlopt_get_xtol_abs(const nlopt_opt opt, NLOPT_EXTERN(nlopt_result) nlopt_set_maxeval(nlopt_opt opt, int maxeval); NLOPT_EXTERN(int) nlopt_get_maxeval(const nlopt_opt opt); +NLOPT_EXTERN(int) nlopt_get_numevals(const nlopt_opt opt); + NLOPT_EXTERN(nlopt_result) nlopt_set_maxtime(nlopt_opt opt, double maxtime); NLOPT_EXTERN(double) nlopt_get_maxtime(const nlopt_opt opt); diff --git a/api/optimize.c b/api/optimize.c index d9e78b7..2c8bbdd 100644 --- a/api/optimize.c +++ b/api/optimize.c @@ -411,7 +411,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) stop.ftol_abs = opt->ftol_abs; stop.xtol_rel = opt->xtol_rel; stop.xtol_abs = opt->xtol_abs; - stop.nevals = 0; + stop.nevals_p = &(opt->numevals); stop.maxeval = opt->maxeval; stop.maxtime = opt->maxtime; stop.start = nlopt_seconds(); diff --git a/api/options.c b/api/options.c index b3f7470..632eb38 100644 --- a/api/options.c +++ b/api/options.c @@ -86,6 +86,7 @@ nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n) opt->ftol_rel = opt->ftol_abs = 0; opt->xtol_rel = 0; opt->xtol_abs = NULL; opt->maxeval = 0; + opt->numevals = 0; opt->maxtime = 0; opt->force_stop = 0; opt->force_stop_child = NULL; @@ -627,6 +628,8 @@ NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs) GETSET(maxeval, int, maxeval) +GETSET(numevals, int, numevals) + GETSET(maxtime, double, maxtime) /*************************************************************************/ diff --git a/auglag/auglag.c b/auglag/auglag.c index 0092484..384194a 100644 --- a/auglag/auglag.c +++ b/auglag/auglag.c @@ -34,7 +34,7 @@ static double auglag(unsigned n, const double *x, double *grad, void *data) unsigned j, k; L = d->f(n, x, grad, d->f_data); - d->stop->nevals++; + ++ *(d->stop->nevals_p); if (nlopt_stop_forced(d->stop)) return L; for (ii = i = 0; i < d->p; ++i) { @@ -143,7 +143,7 @@ nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, /* starting rho suggested by B & M */ if (d.p > 0 || d.m > 0) { double con2 = 0; - d.stop->nevals++; + ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } @@ -191,14 +191,14 @@ nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, double prev_ICM = ICM; ret = nlopt_optimize_limited(sub_opt, xcur, &fcur, - stop->maxeval - stop->nevals, + stop->maxeval - *(stop->nevals_p), stop->maxtime - (nlopt_seconds() - stop->start)); if (auglag_verbose) printf("auglag: subopt return code %d\n", ret); if (ret < 0) break; - d.stop->nevals++; + ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } diff --git a/bobyqa/bobyqa.c b/bobyqa/bobyqa.c index 2ef46a3..e51b0a2 100644 --- a/bobyqa/bobyqa.c +++ b/bobyqa/bobyqa.c @@ -675,7 +675,7 @@ L260: /* L290: */ } - stop->nevals++; + ++ *(stop->nevals_p); f = calfun(*n, &w[1], calfun_data); fval[kpt] = f; if (f < fval[*kopt]) { @@ -1877,7 +1877,7 @@ L50: } /* L60: */ } - stop->nevals++; + ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); fval[nf] = f; if (nf == 1) { @@ -2098,12 +2098,12 @@ static nlopt_result bobyqb_(int *n, int *npt, double *x, rho = *rhobeg; delta = rho; - nresc = stop->nevals; + nresc = *(stop->nevals_p); ntrits = 0; diffa = zero; diffb = zero; itest = 0; - nfsav = stop->nevals; + nfsav = *(stop->nevals_p); /* Update GOPT if necessary before the first iteration and after each */ /* call of RESCUE that makes a call of CALFUN. */ @@ -2123,7 +2123,7 @@ L20: gopt[i__] += hq[ih] * xopt[j]; } } - if (stop->nevals > *npt) { + if (*(stop->nevals_p) > *npt) { i__2 = *npt; for (k = 1; k <= i__2; ++k) { temp = zero; @@ -2161,7 +2161,7 @@ L60: /* Computing 2nd power */ d__1 = ten * rho; distsq = d__1 * d__1; - if (stop->nevals <= nfsav + 2) { + if (*(stop->nevals_p) <= nfsav + 2) { goto L650; } @@ -2331,7 +2331,7 @@ L90: /* useful safeguard, but is not invoked in most applications of BOBYQA. */ L190: - nfsav = stop->nevals; + nfsav = *(stop->nevals_p); kbase = kopt; rc2 = rescue_(n, npt, &xl[1], &xu[1], stop, calfun, calfun_data, @@ -2359,9 +2359,9 @@ L190: rc = rc2; goto L720; } - nresc = stop->nevals; - if (nfsav < stop->nevals) { - nfsav = stop->nevals; + nresc = *(stop->nevals_p); + if (nfsav < *(stop->nevals_p)) { + nfsav = *(stop->nevals_p); goto L20; } if (ntrits > 0) { @@ -2477,7 +2477,7 @@ L230: /* Computing 2nd power */ d__1 = vlag[knew]; if (denom <= half * (d__1 * d__1)) { - if (stop->nevals > nresc) { + if (*(stop->nevals_p) > nresc) { goto L190; } /* Return from BOBYQA because of much cancellation in a @@ -2540,7 +2540,7 @@ L350: ; } if (scaden <= half * biglsq) { - if (stop->nevals > nresc) { + if (*(stop->nevals_p) > nresc) { goto L190; } /* Return from BOBYQA because of much cancellation in a @@ -2579,7 +2579,7 @@ L360: else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; if (rc != NLOPT_SUCCESS) goto L720; - stop->nevals++; + ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); if (ntrits == -1) { fsave = f; @@ -2625,7 +2625,7 @@ L360: diffb = diffa; diffa = fabs(diff); if (dnorm > rho) { - nfsav = stop->nevals; + nfsav = *(stop->nevals_p); } /* Pick the next value of DELTA after a trust region step. */ @@ -3015,7 +3015,7 @@ L680: } delta = MAX2(delta,rho); ntrits = 0; - nfsav = stop->nevals; + nfsav = *(stop->nevals_p); goto L60; } diff --git a/cdirect/cdirect.c b/cdirect/cdirect.c index 165f8e8..d4d1cd5 100644 --- a/cdirect/cdirect.c +++ b/cdirect/cdirect.c @@ -139,7 +139,7 @@ static double function_eval(const double *x, params *p) { p->minf = f; memcpy(p->xmin, x, sizeof(double) * p->n); } - p->stop->nevals++; + ++ *(p->stop->nevals_p); return f; } #define FUNCTION_EVAL(fv,x,p,freeonerr) fv = function_eval(x, p); if (nlopt_stop_forced((p)->stop)) { free(freeonerr); return NLOPT_FORCED_STOP; } else if (p->minf < p->stop->minf_max) { free(freeonerr); return NLOPT_MINF_MAX_REACHED; } else if (nlopt_stop_evals((p)->stop)) { free(freeonerr); return NLOPT_MAXEVAL_REACHED; } else if (nlopt_stop_time((p)->stop)) { free(freeonerr); return NLOPT_MAXTIME_REACHED; } diff --git a/cdirect/hybrid.c b/cdirect/hybrid.c index 97103ba..9179313 100644 --- a/cdirect/hybrid.c +++ b/cdirect/hybrid.c @@ -65,7 +65,7 @@ typedef struct { static double fcount(int n, const double *x, double *grad, void *p_) { params *p = (params *) p_; - p->stop->nevals++; + ++ *(p->stop->nevals_p); return p->f(n, x, grad, p->f_data); } @@ -80,7 +80,7 @@ static nlopt_result optimize_rect(double *r, params *p) nlopt_result ret; if (stop->maxeval > 0 && - stop->nevals >= stop->maxeval) return NLOPT_MAXEVAL_REACHED; + *(stop->nevals_p) >= stop->maxeval) return NLOPT_MAXEVAL_REACHED; if (stop->maxtime > 0 && t - stop->start >= stop->maxtime) return NLOPT_MAXTIME_REACHED; @@ -94,8 +94,8 @@ static nlopt_result optimize_rect(double *r, params *p) stop->xtol_rel, stop->xtol_abs, p->local_maxeval > 0 ? MIN(p->local_maxeval, - stop->maxeval - stop->nevals) - : stop->maxeval - stop->nevals, + stop->maxeval - *(stop->nevals_p)) + : stop->maxeval - *(stop->nevals_p), stop->maxtime - (t - stop->start)); r[1] = -minf; if (ret > 0) { @@ -144,7 +144,7 @@ static nlopt_result divide_largest(params *p) double wmax; nlopt_result ret; - /* printf("rect:, %d, %g, %g, %g, %g\n", p->stop->nevals, c[0], c[1], w[0], w[1]); */ + /* printf("rect:, %d, %g, %g, %g, %g\n", p->stop->nevals_p, c[0], c[1], w[0], w[1]); */ /* check xtol */ for (i = 0; i < n; ++i) diff --git a/cobyla/cobyla.c b/cobyla/cobyla.c index 2e7a81c..17fd70b 100644 --- a/cobyla/cobyla.c +++ b/cobyla/cobyla.c @@ -383,7 +383,7 @@ nlopt_result cobyla(int n, int m, double *x, double *minf, double rhobeg, double * for the main calculation. */ - stop->nevals = 0; + *(stop->nevals_p) = 0; if (n == 0) { @@ -568,13 +568,13 @@ static nlopt_result cobylb(int *n, int *m, int *mpp, L40: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; - else if (stop->nevals > 0) { + else if (*(stop->nevals_p) > 0) { if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; } if (rc != NLOPT_SUCCESS) goto L600; - stop->nevals++; + ++ *(stop->nevals_p); if (calcfc(*n, *m, &x[1], &f, &con[1], state)) { if (*iprint >= 1) { @@ -602,9 +602,9 @@ L40: goto L620; /* not L600 because we want to use current x, f, resmax */ } - if (stop->nevals == *iprint - 1 || *iprint == 3) { + if (*(stop->nevals_p) == *iprint - 1 || *iprint == 3) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", - stop->nevals, f, resmax); + *(stop->nevals_p), f, resmax); i__1 = iptem; fprintf(stderr, "cobyla: X ="); for (i__ = 1; i__ <= i__1; ++i__) { @@ -636,7 +636,7 @@ L40: for (k = 1; k <= i__1; ++k) { datmat[k + jdrop * datmat_dim1] = con[k]; } - if (stop->nevals > np) { + if (*(stop->nevals_p) > np) { goto L130; } @@ -671,8 +671,8 @@ L40: } } } - if (stop->nevals <= *n) { /* evaluating initial simplex */ - jdrop = stop->nevals; + if (*(stop->nevals_p) <= *n) { /* evaluating initial simplex */ + jdrop = *(stop->nevals_p); /* SGJ: was += rho, but using sim[jdrop,jdrop] enforces consistency if we change the stepsize above to stay in [lb,ub]. */ x[jdrop] += sim[jdrop + jdrop * sim_dim1]; @@ -1179,7 +1179,7 @@ L550: } if (*iprint == 2) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", - stop->nevals, datmat[mp + np * datmat_dim1], datmat[*mpp + np * datmat_dim1]); + *(stop->nevals_p), datmat[mp + np * datmat_dim1], datmat[*mpp + np * datmat_dim1]); fprintf(stderr, "cobyla: X ="); i__1 = iptem; @@ -1220,7 +1220,7 @@ L620: *minf = f; if (*iprint >= 1) { fprintf(stderr, "cobyla: NFVALS = %4d, F =%13.6E, MAXCV =%13.6E\n", - stop->nevals, f, resmax); + *(stop->nevals_p), f, resmax); i__1 = iptem; fprintf(stderr, "cobyla: X ="); for (i__ = 1; i__ <= i__1; ++i__) { diff --git a/cquad/cquad.c b/cquad/cquad.c index b2dc27c..e20ff98 100644 --- a/cquad/cquad.c +++ b/cquad/cquad.c @@ -303,7 +303,7 @@ nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, model.model.q0 = f(n, x0, NULL, f_data); memcpy(X + (iM++ * n), x0, n * sizeof(double)); memset(model.model.Q, 0, sizeof(double) * n*n); - stop->nevals++; + *(stop->nevals_p)++; feasible_cur = 1; for (i = 0; i < m; ++i) { modelc[i].model.q0 = fc(n, x0, NULL, fc_data + fc_datum_size*i); @@ -330,7 +330,7 @@ nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, xcur[j] = x0[j] + (2*s - 1) * dx[j]; fmp[s] = fcur = f(n, xcur, NULL, f_data); memcpy(X + (iM++ * n), xcur, n * sizeof(double)); - stop->nevals++; + *(stop->nevals_p)++; feasible_cur = 1; for (i = 0; i < m; ++i) { fcmp[s][i] = fcval_cur[i] = @@ -416,7 +416,7 @@ nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, gcval[i] = cmodel_func(n, xcur, NULL, modelc + i); fcur = f(n, xcur, NULL, f_data); - stop->nevals++; + *(stop->nevals_p)++; feasible_cur = 1; inner_done = gval >= fcur; for (i = 0; i < m; ++i) { diff --git a/crs/crs.c b/crs/crs.c index 16f4ad5..ce27f64 100644 --- a/crs/crs.c +++ b/crs/crs.c @@ -131,7 +131,7 @@ static nlopt_result crs_trial(crs_data *d) random_trial(d, d->p + 1, best); do { d->p[0] = d->f(n, d->p + 1, NULL, d->f_data); - d->stop->nevals++; + ++ *(d->stop->nevals_p); if (nlopt_stop_forced(d->stop)) return NLOPT_FORCED_STOP; if (d->p[0] < worst->k[0]) break; if (nlopt_stop_evals(d->stop)) return NLOPT_MAXEVAL_REACHED; @@ -203,7 +203,7 @@ static nlopt_result crs_init(crs_data *d, int n, const double *x, /* generate initial points randomly, plus starting guess x */ memcpy(d->ps + 1, x, sizeof(double) * n); d->ps[0] = f(n, x, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (!rb_tree_insert(&d->t, d->ps)) return NLOPT_OUT_OF_MEMORY; if (d->ps[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; @@ -218,7 +218,7 @@ static nlopt_result crs_init(crs_data *d, int n, const double *x, k[1 + j] = nlopt_urand(lb[j], ub[j]); } k[0] = f(n, k + 1, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (!rb_tree_insert(&d->t, k)) return NLOPT_OUT_OF_MEMORY; if (k[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; diff --git a/doc/docs/NLopt_C-plus-plus_Reference.md b/doc/docs/NLopt_C-plus-plus_Reference.md index f511d42..463deb3 100644 --- a/doc/docs/NLopt_C-plus-plus_Reference.md +++ b/doc/docs/NLopt_C-plus-plus_Reference.md @@ -229,6 +229,13 @@ double nlopt::opt::get_maxtime() const; Stop when the optimization time (in seconds) exceeds `maxtime`. +``` +int nlopt::opt::get_numevals() const; +``` + + +Request the number of evaluations. + ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. You can do this by throwing *any* exception inside your objective/constraint functions: the exception will be caught, the optimization will be halted gracefully, and another exception (possibly not the same one) will be rethrown. See [Exceptions](#Exceptions.md), below. The C++ equivalent of `nlopt_forced_stop` from the [C API](NLopt_Reference#Forced_termination.md) is to throw an `nlopt::forced_stop` exception. diff --git a/doc/docs/NLopt_Fortran_Reference.md b/doc/docs/NLopt_Fortran_Reference.md index 559d42c..295e89c 100644 --- a/doc/docs/NLopt_Fortran_Reference.md +++ b/doc/docs/NLopt_Fortran_Reference.md @@ -256,8 +256,16 @@ call nlo_get_maxeval(maxeval, opt) ``` + Stop when the number of function evaluations exceeds the `integer` `maxeval`. (Zero or negative for no limit.) +``` +call nlo_get_numevals(nevals, opt) +``` + +Request the number of evaluations. + + ``` call nlo_set_maxtime(ires, opt, maxtime) call nlo_get_maxtime(maxtime, opt) diff --git a/doc/docs/NLopt_Guile_Reference.md b/doc/docs/NLopt_Guile_Reference.md index de39664..11b875d 100644 --- a/doc/docs/NLopt_Guile_Reference.md +++ b/doc/docs/NLopt_Guile_Reference.md @@ -186,6 +186,14 @@ Set absolute tolerances on optimization parameters. The `tol` input must be a ve Stop when the number of function evaluations exceeds `maxeval`. (0 or negative for no limit.) +``` +(nlopt-opt-get-nevals opt) +``` + + +Request the number of evaluations. + + ``` (nlopt-opt-set-maxtime opt maxtime) (nlopt-opt-get-maxtime opt) diff --git a/doc/docs/NLopt_Python_Reference.md b/doc/docs/NLopt_Python_Reference.md index 8728f6a..5bdc8a7 100644 --- a/doc/docs/NLopt_Python_Reference.md +++ b/doc/docs/NLopt_Python_Reference.md @@ -239,6 +239,17 @@ opt.get_maxtime() Stop when the optimization time (in seconds) exceeds `maxtime`. (0 or negative for no limit.) + + +``` +opt.get_numevals() +``` + + +Request the number of evaluations. + + + ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. You can do this by raise *any* exception inside your objective/constraint functions:the optimization will be halted gracefully, and the same exception will be raised to the caller. See [Exceptions](#Exceptions.md), below. The Python equivalent of `nlopt_forced_stop` from the [C API](NLopt_Reference#Forced_termination.md) is to throw an `nlopt.ForcedStop` exception. diff --git a/doc/docs/NLopt_Reference.md b/doc/docs/NLopt_Reference.md index ae0eaee..e59a09c 100644 --- a/doc/docs/NLopt_Reference.md +++ b/doc/docs/NLopt_Reference.md @@ -272,6 +272,14 @@ double nlopt_get_maxtime(nlopt_opt opt); Stop when the optimization time (in seconds) exceeds `maxtime`. (This is not a strict maximum: the time may exceed maxtime slightly, depending upon the algorithm and on how slow your function evaluation is.) Criterion is disabled if `maxtime` is non-positive. +``` +int nlopt_get_numevals(nlopt_opt opt); +``` + + +Request the number of evaluations. + + ### Forced termination In certain cases, the caller may wish to *force* the optimization to halt, for some reason unknown to NLopt. For example, if the user presses Ctrl-C, or there is an error of some sort in the objective function. (This is used to implement exception handling in the NLopt wrappers for C++ and other languages.) In this case, it is possible to tell NLopt to halt the optimization gracefully, returning the best point found so far, by calling the following function from *within* your objective or constraint functions: diff --git a/doc/docs/NLopt_release_notes.md b/doc/docs/NLopt_release_notes.md index c46801a..8d3e867 100644 --- a/doc/docs/NLopt_release_notes.md +++ b/doc/docs/NLopt_release_notes.md @@ -10,6 +10,7 @@ NLopt 2.5.0 TBA - Using CMake build system instead of autotools +- Add int nlopt_get_numevals() function NLopt 2.4.2 ----------- diff --git a/esch/esch.c b/esch/esch.c index 6fd5ecb..ef16ee4 100644 --- a/esch/esch.c +++ b/esch/esch.c @@ -165,7 +165,7 @@ nlopt_result chevolutionarystrategy( esparents[id].fitness = f(nparameters, esparents[id].parameters, NULL, data_f); estotal[id].fitness = esparents[id].fitness; - stop->nevals++; + ++ *(stop->nevals_p); if (*minf > esparents[id].fitness) { *minf = esparents[id].fitness; memcpy(x, esparents[id].parameters, @@ -218,7 +218,7 @@ nlopt_result chevolutionarystrategy( /*esoffsprings[id].fitness = (double)fitness(esoffsprings[id].parameters, nparameters,fittype);*/ esoffsprings[id].fitness = f(nparameters, esoffsprings[id].parameters, NULL, data_f); estotal[id+np].fitness = esoffsprings[id].fitness; - stop->nevals++; + ++ *(stop->nevals_p); if (*minf > esoffsprings[id].fitness) { *minf = esoffsprings[id].fitness; memcpy(x, esoffsprings[id].parameters, diff --git a/isres/isres.c b/isres/isres.c index c6de700..ad5fc25 100644 --- a/isres/isres.c +++ b/isres/isres.c @@ -134,7 +134,7 @@ nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, for (k = 0; k < population; ++k) { int feasible = 1; double gpenalty; - stop->nevals++; + ++ *(stop->nevals_p); fval[k] = f(n, xs + k*n, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } diff --git a/luksan/luksan.h b/luksan/luksan.h index 01ac07b..214fb92 100644 --- a/luksan/luksan.h +++ b/luksan/luksan.h @@ -136,7 +136,7 @@ void luksan_pnint1__(double *rl, double *ru, double *fl, /* Common Block Declarations */ typedef struct { int nres, ndec, nin, nit; - /* int nfv; -- now stored in stop->nevals */ + /* int nfv; -- now stored in stop->nevals_p */ int nfg, nfh; } stat_common; diff --git a/luksan/plip.c b/luksan/plip.c index 8bce79e..efc3fd0 100644 --- a/luksan/plip.c +++ b/luksan/plip.c @@ -279,7 +279,7 @@ static void plip_(int *nf, int *nb, double *x, int * goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: @@ -384,7 +384,7 @@ L11170: luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); goto L11170; diff --git a/luksan/plis.c b/luksan/plis.c index 11d371f..8bd7bb3 100644 --- a/luksan/plis.c +++ b/luksan/plis.c @@ -261,7 +261,7 @@ static void plis_(int *nf, int *nb, double *x, int * goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: @@ -391,7 +391,7 @@ L11170: luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); goto L11170; diff --git a/luksan/pnet.c b/luksan/pnet.c index 3e25634..f2e324b 100644 --- a/luksan/pnet.c +++ b/luksan/pnet.c @@ -300,7 +300,7 @@ static void pnet_(int *nf, int *nb, double *x, int * luksan_pyadc0__(nf, &n, &x[1], &ix[1], &xl[1], &xu[1], &inew); } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++(*stop->nevals_p); ++stat_1->nfg; if (nlopt_stop_time(stop)) { *iterm = 100; goto L11080; } ld = kd; @@ -398,7 +398,7 @@ L12520: ld = 0; luksan_mxudir__(nf, &pp, &xs[1], &xo[1], &x[1], &ix[1], &kbf); objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; ld = kd; luksan_mxvdif__(nf, &gf[1], &gn[1], &go[1]); @@ -526,7 +526,7 @@ L11060: luksan_mxudir__(nf, &r__, &s[1], &xo[1], &x[1], &ix[1], &kbf); luksan_pcbs04__(nf, &x[1], &ix[1], &xl[1], &xu[1], &eps9, &kbf); *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); - ++stop->nevals; + ++*(stop->nevals_p); ++stat_1->nfg; ld = kd; p = luksan_mxudot__(nf, &gf[1], &s[1], &ix[1], &kbf); diff --git a/mlsl/mlsl.c b/mlsl/mlsl.c index b90d690..ff1d517 100644 --- a/mlsl/mlsl.c +++ b/mlsl/mlsl.c @@ -251,7 +251,7 @@ static pt *alloc_pt(int n) static double fcount(unsigned n, const double *x, double *grad, void *p_) { mlsl_data *p = (mlsl_data *) p_; - p->stop->nevals++; + ++ *(p->stop->nevals_p); return p->f(n, x, grad, p->f_data); } @@ -333,7 +333,7 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, memcpy(p->x, x, n * sizeof(double)); p->f = f(n, x, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } @@ -358,7 +358,7 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, for (j = 0; j < n; ++j) p->x[j] = nlopt_urand(lb[j],ub[j]); } p->f = f(n, p->x, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } @@ -402,7 +402,7 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, if (!lm) { ret = NLOPT_OUT_OF_MEMORY; goto done; } memcpy(lm+1, p->x, sizeof(double) * n); lret = nlopt_optimize_limited(local_opt, lm+1, lm, - stop->maxeval - stop->nevals, + stop->maxeval - *(stop->nevals_p), stop->maxtime - (t - stop->start)); p->minimized = 1; diff --git a/mma/ccsa_quadratic.c b/mma/ccsa_quadratic.c index 2b34527..23ffbba 100644 --- a/mma/ccsa_quadratic.c +++ b/mma/ccsa_quadratic.c @@ -333,7 +333,7 @@ nlopt_result ccsa_quadratic_minimize( } dd.fval = fcur = *minf = f(n, x, dfdx, f_data); - stop->nevals++; + ++ *(stop->nevals_p); memcpy(xcur, x, sizeof(double) * n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } @@ -441,7 +441,7 @@ nlopt_result ccsa_quadratic_minimize( } fcur = f(n, xcur, dfdx_cur, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible_cur = 1; infeasibility_cur = 0; diff --git a/mma/mma.c b/mma/mma.c index 7f14375..94668bd 100644 --- a/mma/mma.c +++ b/mma/mma.c @@ -209,7 +209,7 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, } dd.fval = fcur = *minf = f(n, x, dfdx, f_data); - stop->nevals++; + ++ *(stop->nevals_p); memcpy(xcur, x, sizeof(double) * n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } @@ -287,7 +287,7 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, } fcur = f(n, xcur, dfdx_cur, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } feasible_cur = 1; infeasibility_cur = 0; diff --git a/neldermead/nldrmd.c b/neldermead/nldrmd.c index a8e7ee4..f4a8e7e 100644 --- a/neldermead/nldrmd.c +++ b/neldermead/nldrmd.c @@ -77,7 +77,7 @@ static int reflectpt(int n, double *xnew, } #define CHECK_EVAL(xc,fc) \ - stop->nevals++; \ + ++ *(stop->nevals_p); \ if (nlopt_stop_forced(stop)) { ret=NLOPT_FORCED_STOP; goto done; } \ if ((fc) <= *minf) { \ *minf = (fc); memcpy(x, (xc), n * sizeof(double)); \ @@ -295,7 +295,7 @@ nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, double *scratch, fdiff; *minf = f(n, x, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; diff --git a/neldermead/sbplx.c b/neldermead/sbplx.c index f2ad6f3..cbad38f 100644 --- a/neldermead/sbplx.c +++ b/neldermead/sbplx.c @@ -78,7 +78,7 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, double fprev; *minf = f(n, x, NULL, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; @@ -107,7 +107,7 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, double normi = 0; double normdx = 0; int ns, nsubs = 0; - int nevals = stop->nevals; + int nevals = *(stop->nevals_p); double fdiff, fdiff_max = 0; memcpy(xprev, x, n * sizeof(double)); @@ -153,13 +153,13 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, ubs[k-i] = ub[p[k]]; } ++nsubs; - nevals = stop->nevals; + nevals = *(stop->nevals_p); ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, xsstep, stop, psi, scratch, &fdiff); if (fdiff > fdiff_max) fdiff_max = fdiff; if (sbplx_verbose) printf("%d NM iterations for (%d,%d) subspace\n", - stop->nevals - nevals, sd.is, ns); + *(stop->nevals_p) - nevals, sd.is, ns); for (k = i; k < i+ns; ++k) x[p[k]] = xs[k-i]; if (ret == NLOPT_FAILURE) { ret=NLOPT_XTOL_REACHED; goto done; } if (ret != NLOPT_XTOL_REACHED) goto done; @@ -174,13 +174,13 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, ubs[i-sd.is] = ub[p[i]]; } ++nsubs; - nevals = stop->nevals; + nevals = *(stop->nevals_p); ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, xsstep, stop, psi, scratch, &fdiff); if (fdiff > fdiff_max) fdiff_max = fdiff; if (sbplx_verbose) printf("sbplx: %d NM iterations for (%d,%d) subspace\n", - stop->nevals - nevals, sd.is, ns); + *(stop->nevals_p) - nevals, sd.is, ns); for (i = sd.is; i < n; ++i) x[p[i]] = xs[i-sd.is]; if (ret == NLOPT_FAILURE) { ret=NLOPT_XTOL_REACHED; goto done; } if (ret != NLOPT_XTOL_REACHED) goto done; diff --git a/newuoa/newuoa.c b/newuoa/newuoa.c index a22849e..83c1211 100644 --- a/newuoa/newuoa.c +++ b/newuoa/newuoa.c @@ -2100,13 +2100,13 @@ L290: ++nf; L310: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; - else if (stop->nevals > 0) { + else if (*(stop->nevals_p) > 0) { if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; } if (rc != NLOPT_SUCCESS) goto L530; - stop->nevals++; + ++ *(stop->nevals_p); f = calfun(*n, &x[1], calfun_data); if (f < stop->minf_max) { rc = NLOPT_MINF_MAX_REACHED; diff --git a/praxis/praxis.c b/praxis/praxis.c index a032904..e6ce82e 100644 --- a/praxis/praxis.c +++ b/praxis/praxis.c @@ -182,7 +182,7 @@ nlopt_result praxis_(double t0, double machep, double h0, prev_fbest = q_1.fbest = global_1.fx = f(n, &x[1], f_data); memcpy(q_1.xbest, &x[1], n*sizeof(double)); memcpy(prev_xbest, &x[1], n*sizeof(double)); - stop->nevals++; + ++ *(stop->nevals_p); q_1.stop = stop; q_1.qf1 = global_1.fx; if (t0 > 0) @@ -1236,7 +1236,7 @@ L2: L4: ++(*nf); ret_val = f(n, t, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (ret_val < q_1->fbest) { q_1->fbest = ret_val; memcpy(q_1->xbest, t, n * sizeof(double)); diff --git a/slsqp/slsqp.c b/slsqp/slsqp.c index 8a4be2d..f648f5d 100644 --- a/slsqp/slsqp.c +++ b/slsqp/slsqp.c @@ -2509,7 +2509,7 @@ nlopt_result nlopt_slsqp(unsigned n, nlopt_func f, void *f_data, } feasible_cur = 1; infeasibility_cur = 0; fcur = f(n, xcur, newgrad, f_data); - stop->nevals++; + ++ *(stop->nevals_p); if (nlopt_stop_forced(stop)) { fcur = HUGE_VAL; ret = NLOPT_FORCED_STOP; goto done; } if (nlopt_isfinite(fcur)) { diff --git a/stogo/local.cc b/stogo/local.cc index 89802b6..f95884b 100644 --- a/stogo/local.cc +++ b/stogo/local.cc @@ -12,7 +12,7 @@ #include "tools.h" #ifdef NLOPT_UTIL_H -# define IF_NLOPT_CHECK_EVALS stop->nevals++; \ +# define IF_NLOPT_CHECK_EVALS ++ *(stop->nevals_p); \ if (nlopt_stop_evalstime(stop)) \ return LS_MaxEvalTime #else @@ -44,7 +44,7 @@ static double f_local(int n, const double *x, double *grad, void *data_) grad?OBJECTIVE_AND_GRADIENT:OBJECTIVE_ONLY); if (grad) data->maxgrad = max(data->maxgrad, normInf(gv)); xv.elements = gv.elements = 0; // prevent deallocation - data->stop->nevals++; + ++ *(data->stop->nevals_p); return f; } #endif @@ -98,7 +98,7 @@ int local(Trial &T, TBox &box, TBox &domain, double eps_cl, double *mgr, stop->minf_max, stop->ftol_rel, stop->ftol_abs, stop->xtol_rel, stop->xtol_abs, - stop->maxeval - stop->nevals, + stop->maxeval - *(stop->nevals_p), stop->maxtime - stop->start); *mgr = data.maxgrad; T.xvals=x ; T.objval=f ; diff --git a/subplex/subplex.c b/subplex/subplex.c index 28b9a75..c8c767b 100644 --- a/subplex/subplex.c +++ b/subplex/subplex.c @@ -1384,7 +1384,7 @@ static int simplx_(D_fp f, void *fdata, integer *n, doublereal *step, integer * if (usubc_1.irepl > 0) { isubc_1.new__ = FALSE_; evalf_((D_fp)f,fdata, ns, &ips[1], &s[s_dim1 + 1], n, &x[1], &fs[1], nfe); - stop->nevals++; + *(stop->nevals_p)++; } else { fs[1] = *fx; } @@ -1393,7 +1393,7 @@ static int simplx_(D_fp f, void *fdata, integer *n, doublereal *step, integer * for (j = 2; j <= i__1; ++j) { evalf_((D_fp)f, fdata,ns, &ips[1], &s[j * s_dim1 + 1], n, &x[1], &fs[j], nfe); - stop->nevals++; + *(stop->nevals_p)++; /* L10: */ } il = 1; @@ -1415,7 +1415,7 @@ L20: goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[itemp * s_dim1 + 1], n, &x[1], &fr, nfe); - stop->nevals++; + *(stop->nevals_p)++; if (fr < fs[il]) { /* expand */ @@ -1427,7 +1427,7 @@ L20: goto L40; } evalf_((D_fp)f,fdata, ns, &ips[1], &s[ih * s_dim1 + 1], n, &x[1], &fe, nfe); - stop->nevals++; + *(stop->nevals_p)++; if (fe < fr) { fs[ih] = fe; } else { @@ -1459,7 +1459,7 @@ L20: } evalf_((D_fp)f,fdata, ns, &ips[1], &s[itemp * s_dim1 + 1], n, &x[1], &fc, nfe); - stop->nevals++; + *(stop->nevals_p)++; /* Computing MIN */ d__1 = fr, d__2 = fs[ih]; if (fc < MIN2(d__1,d__2)) { @@ -1481,7 +1481,7 @@ L20: } evalf_((D_fp)f,fdata, ns, &ips[1], &s[j * s_dim1 + 1], n, &x[1], &fs[j], nfe); - stop->nevals++; + *(stop->nevals_p)++; } /* L30: */ } @@ -2037,7 +2037,7 @@ static int subplx_(D_fp f, void *fdata, integer *n, isubc_1.new__ = TRUE_; usubc_1.initx = TRUE_; evalf_((D_fp)f, fdata, &c__0, &iwork[1], &dum, n, &x[1], &sfx, nfe); - stop->nevals++; + *(stop->nevals_p)++; usubc_1.initx = FALSE_; } else { diff --git a/test/t_python.py b/test/t_python.py index 8dee3db..3ce7bdd 100644 --- a/test/t_python.py +++ b/test/t_python.py @@ -20,11 +20,12 @@ def myconstraint(x, grad, a, b): opt = nlopt.opt(nlopt.LD_MMA, 2) opt.set_lower_bounds([-float('inf'), 0]) opt.set_min_objective(myfunc) -opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,2,0), 1e-8) -opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,-1,1), 1e-8) +opt.add_inequality_constraint(lambda x, grad: myconstraint(x,grad, 2, 0), 1e-8) +opt.add_inequality_constraint(lambda x, grad: myconstraint(x,grad, -1, 1), 1e-8) opt.set_xtol_rel(1e-4) x = opt.optimize([1.234, 5.678]) minf = opt.last_optimum_value() -print('optimum at ', x[0],x[1]) +print('optimum at ', x[0], x[1]) print('minimum value = ', minf) print('result code = ', opt.last_optimize_result()) +print('nevals = ', opt.get_numevals()) diff --git a/util/nlopt-util.h b/util/nlopt-util.h index 89740c4..437cb67 100644 --- a/util/nlopt-util.h +++ b/util/nlopt-util.h @@ -82,7 +82,7 @@ typedef struct { double ftol_abs; double xtol_rel; const double *xtol_abs; - int nevals, maxeval; + int *nevals_p, maxeval; double maxtime, start; int *force_stop; char **stop_msg; /* pointer to msg string to update */ diff --git a/util/stop.c b/util/stop.c index 7349df1..b834b55 100644 --- a/util/stop.c +++ b/util/stop.c @@ -87,7 +87,7 @@ int nlopt_stop_xs(const nlopt_stopping *s, int nlopt_stop_evals(const nlopt_stopping *s) { - return (s->maxeval > 0 && s->nevals >= s->maxeval); + return (s->maxeval > 0 && *(s->nevals_p) >= s->maxeval); } int nlopt_stop_time_(double start, double maxtime) -- 2.30.2