From 2afd2f7665f166664936bc3b372219025d39ee36 Mon Sep 17 00:00:00 2001 From: stevenj Date: Fri, 28 May 2010 12:36:00 -0400 Subject: [PATCH] added nlopt_force_stop termination darcs-hash:20100528163600-c8de0-aa1d026191abea2ffd7870265933673fe18ab890.gz --- api/nlopt-in.hpp | 3 +++ api/nlopt-internal.h | 6 ++++++ api/nlopt.3 | 5 +++++ api/nlopt.h | 5 +++++ api/optimize.c | 10 ++++++++++ api/options.c | 29 +++++++++++++++++++++++++---- auglag/auglag.c | 1 + bobyqa/bobyqa.c | 12 ++++++++---- cdirect/cdirect.c | 2 +- cobyla/cobyla.c | 3 ++- cquad/cquad.c | 6 ++++-- crs/crs.c | 1 + isres/isres.c | 3 ++- luksan/plip.c | 1 + luksan/plis.c | 1 + luksan/pnet.c | 1 + luksan/pssubs.c | 4 ++++ mlsl/mlsl.c | 10 ++++++++-- mma/mma.c | 6 ++++-- neldermead/nldrmd.c | 2 ++ neldermead/sbplx.c | 1 + newuoa/newuoa.c | 3 ++- praxis/praxis.c | 3 ++- subplex/subplex.c | 4 +++- util/nlopt-util.h | 2 ++ util/stop.c | 5 +++++ 26 files changed, 109 insertions(+), 20 deletions(-) diff --git a/api/nlopt-in.hpp b/api/nlopt-in.hpp index 5187afb..a188544 100644 --- a/api/nlopt-in.hpp +++ b/api/nlopt-in.hpp @@ -222,6 +222,9 @@ namespace nlopt { NLOPT_GETSET(int, maxeval) NLOPT_GETSET(double, maxtime) + NLOPT_GETSET(int, force_stop) + void force_stop() { set_force_stop(1); } + // algorithm-specific parameters: void set_local_optimizer(const nlopt_opt lo) { diff --git a/api/nlopt-internal.h b/api/nlopt-internal.h index 8068911..67af6b1 100644 --- a/api/nlopt-internal.h +++ b/api/nlopt-internal.h @@ -57,6 +57,12 @@ struct nlopt_opt_s { int maxeval; /* max # evaluations */ double maxtime; /* max time (seconds) */ + int force_stop; /* if nonzero, force a halt the next time we + try to evaluate the objective during optimization */ + /* when local optimization is used, we need a force_stop in the + parent object to force a stop in child optimizations */ + struct nlopt_opt_s *force_stop_child; + /* algorithm-specific parameters */ nlopt_opt local_opt; /* local optimizer */ unsigned stochastic_population; /* population size for stochastic algs */ diff --git a/api/nlopt.3 b/api/nlopt.3 index cec713b..e5e862b 100644 --- a/api/nlopt.3 +++ b/api/nlopt.3 @@ -634,6 +634,11 @@ Ran out of memory. .TP .B NLOPT_ROUNDOFF_LIMITED Halted because roundoff errors limited progress. +.TP +.B NLOPT_FORCE_STOP +Halted because the user called \fBnlopt_force_stop\fR(\fIopt\fR) on +the optimization's \fBnlopt_opt\fR object \fIopt\fR from the user's +objective function. .SH LOCAL OPTIMIZER Some of the algorithms, especially MLSL and AUGLAG, use a different optimization algorithm as a subroutine, typically for local diff --git a/api/nlopt.h b/api/nlopt.h index beeaf53..39cddfd 100644 --- a/api/nlopt.h +++ b/api/nlopt.h @@ -135,6 +135,7 @@ typedef enum { NLOPT_INVALID_ARGS = -2, NLOPT_OUT_OF_MEMORY = -3, NLOPT_ROUNDOFF_LIMITED = -4, + NLOPT_FORCE_STOP = -5, NLOPT_SUCCESS = 1, /* generic success code */ NLOPT_STOPVAL_REACHED = 2, NLOPT_FTOL_REACHED = 3, @@ -227,6 +228,10 @@ NLOPT_EXTERN int nlopt_get_maxeval(nlopt_opt opt); NLOPT_EXTERN nlopt_result nlopt_set_maxtime(nlopt_opt opt, double maxtime); NLOPT_EXTERN double nlopt_get_maxtime(nlopt_opt opt); +NLOPT_EXTERN nlopt_result nlopt_force_stop(nlopt_opt opt); +NLOPT_EXTERN nlopt_result nlopt_set_force_stop(nlopt_opt opt, int val); +NLOPT_EXTERN int nlopt_get_force_stop(nlopt_opt opt); + /* more algorithm-specific parameters */ NLOPT_EXTERN nlopt_result nlopt_set_local_optimizer(nlopt_opt opt, diff --git a/api/optimize.c b/api/optimize.c index a684e9a..49595c0 100644 --- a/api/optimize.c +++ b/api/optimize.c @@ -150,6 +150,10 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) if (!opt || !x || !minf || !opt->f || opt->maximize) return NLOPT_INVALID_ARGS; + + /* reset stopping flag */ + nlopt_set_force_stop(opt, 0); + opt->force_stop_child = NULL; /* copy a few params to local vars for convenience */ n = opt->n; @@ -184,6 +188,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) stop.maxeval = opt->maxeval; stop.maxtime = opt->maxtime; stop.start = nlopt_seconds(); + stop.force_stop = &(opt->force_stop); switch (algorithm) { case NLOPT_GN_DIRECT: @@ -267,6 +272,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) if (freedx) { free(opt->dx); opt->dx = NULL; } switch (iret) { case -2: return NLOPT_INVALID_ARGS; + case -20: return NLOPT_FORCE_STOP; case -10: return NLOPT_MAXTIME_REACHED; case -1: return NLOPT_MAXEVAL_REACHED; case 0: return NLOPT_XTOL_REACHED; @@ -378,9 +384,11 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) nlopt_set_ftol_rel(local_opt, 1e-15); nlopt_set_xtol_rel(local_opt, 1e-7); } + opt->force_stop_child = local_opt; ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop, local_opt, (int) POP(0), algorithm >= NLOPT_GN_MLSL_LDS); + opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } @@ -476,6 +484,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); nlopt_set_initial_step(local_opt, opt->dx); } + opt->force_stop_child = local_opt; ret = auglag_minimize(ni, f, f_data, opt->m, opt->fc, opt->p, opt->h, @@ -483,6 +492,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) local_opt, algorithm == NLOPT_LN_AUGLAG_EQ || algorithm == NLOPT_LD_AUGLAG_EQ); + opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } diff --git a/api/options.c b/api/options.c index 83a4da6..f002a7b 100644 --- a/api/options.c +++ b/api/options.c @@ -69,6 +69,8 @@ nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n) opt->xtol_rel = 0; opt->xtol_abs = NULL; opt->maxeval = 0; opt->maxtime = 0; + opt->force_stop = 0; + opt->force_stop_child = NULL; opt->local_opt = NULL; opt->stochastic_population = 0; @@ -105,6 +107,7 @@ nlopt_opt nlopt_copy(const nlopt_opt opt) nopt->m_alloc = nopt->p_alloc = 0; nopt->local_opt = NULL; nopt->dx = NULL; + opt->force_stop_child = NULL; if (opt->n > 0) { nopt->lb = (double *) malloc(sizeof(double) * (opt->n)); @@ -157,11 +160,11 @@ oom: nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) { - if (opt && f) { + if (opt) { opt->f = f; opt->f_data = f_data; opt->maximize = 0; if (nlopt_isinf(opt->stopval) && opt->stopval > 0) - opt->stopval = -HUGE_VAL; + opt->stopval = -HUGE_VAL; /* switch default from max to min */ return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; @@ -169,11 +172,11 @@ nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) nlopt_result nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data) { - if (opt && f) { + if (opt) { opt->f = f; opt->f_data = f_data; opt->maximize = 1; if (nlopt_isinf(opt->stopval) && opt->stopval < 0) - opt->stopval = +HUGE_VAL; + opt->stopval = +HUGE_VAL; /* switch default from min to max */ return NLOPT_SUCCESS; } return NLOPT_INVALID_ARGS; @@ -379,6 +382,22 @@ GETSET(maxtime, double, maxtime) /*************************************************************************/ +nlopt_result nlopt_set_force_stop(nlopt_opt opt, int force_stop) +{ + if (opt) { + opt->force_stop = force_stop; + if (opt->force_stop_child) + return nlopt_set_force_stop(opt->force_stop_child, force_stop); + return NLOPT_SUCCESS; + } + return NLOPT_INVALID_ARGS; +} + +GET(force_stop, int, force_stop) +nlopt_result nlopt_force_stop(nlopt_opt opt) { nlopt_set_force_stop(opt, 1); } + +/*************************************************************************/ + GET(algorithm, nlopt_algorithm, algorithm) GET(dimension, unsigned, n) @@ -397,6 +416,8 @@ nlopt_result nlopt_set_local_optimizer(nlopt_opt opt, nlopt_set_upper_bounds(opt->local_opt, opt->ub); nlopt_remove_inequality_constraints(opt->local_opt); nlopt_remove_equality_constraints(opt->local_opt); + nlopt_set_min_objective(opt->local_opt, NULL, NULL); + opt->local_opt->force_stop = 0; } return NLOPT_SUCCESS; } diff --git a/auglag/auglag.c b/auglag/auglag.c index c5b65f0..8c85f39 100644 --- a/auglag/auglag.c +++ b/auglag/auglag.c @@ -215,6 +215,7 @@ nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, if (ret != NLOPT_SUCCESS) break; } + if (nlopt_stop_forced(stop)) {ret = NLOPT_FORCE_STOP; break;} if (nlopt_stop_evals(stop)) {ret = NLOPT_MAXEVAL_REACHED; break;} if (nlopt_stop_time(stop)) {ret = NLOPT_MAXTIME_REACHED; break;} diff --git a/bobyqa/bobyqa.c b/bobyqa/bobyqa.c index 0161621..9ca6de7 100644 --- a/bobyqa/bobyqa.c +++ b/bobyqa/bobyqa.c @@ -592,7 +592,8 @@ L260: goto L340; } - if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; ih = 0; @@ -678,7 +679,8 @@ L260: if (f < fval[*kopt]) { *kopt = kpt; } - if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; + if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP; + else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; @@ -1937,7 +1939,8 @@ L50: temp = xpt[nf + ipt * xpt_dim1] * xpt[nf + jpt * xpt_dim1]; hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / temp; } - if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; + if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP; + else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; if (nf < *npt) { @@ -2569,7 +2572,8 @@ L360: /* L380: */ } - if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) rc = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; if (rc != NLOPT_SUCCESS) goto L720; diff --git a/cdirect/cdirect.c b/cdirect/cdirect.c index b403e8b..8ab211c 100644 --- a/cdirect/cdirect.c +++ b/cdirect/cdirect.c @@ -142,7 +142,7 @@ static double function_eval(const double *x, params *p) { p->stop->nevals++; return f; } -#define FUNCTION_EVAL(fv,x,p,freeonerr) fv = function_eval(x, p); 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; } +#define FUNCTION_EVAL(fv,x,p,freeonerr) fv = function_eval(x, p); if (nlopt_stop_forced((p)->stop)) { free(freeonerr); return NLOPT_FORCE_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; } #define THIRD (0.3333333333333333333333) diff --git a/cobyla/cobyla.c b/cobyla/cobyla.c index 32a6520..a285793 100644 --- a/cobyla/cobyla.c +++ b/cobyla/cobyla.c @@ -499,7 +499,8 @@ static nlopt_result cobylb(int *n, int *m, int *mpp, #*&!%*@ Fortran-66 spaghetti code */ L40: - if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) rc = NLOPT_FORCE_STOP; + else 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; diff --git a/cquad/cquad.c b/cquad/cquad.c index ae4e657..8e3bb69 100644 --- a/cquad/cquad.c +++ b/cquad/cquad.c @@ -315,7 +315,8 @@ nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, memcpy(x, x0, sizeof(double) * n); feasible = 1; } - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; if (ret != NLOPT_SUCCESS) goto done; @@ -341,7 +342,8 @@ nlopt_result cquad_minimize(int n, nlopt_func f, void *f_data, memcpy(x, xcur, sizeof(double) * n); feasible = 1; } - if (nlopt_stop_evals(stop)) + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; diff --git a/crs/crs.c b/crs/crs.c index 49b3a13..36cbc3e 100644 --- a/crs/crs.c +++ b/crs/crs.c @@ -132,6 +132,7 @@ static nlopt_result crs_trial(crs_data *d) do { d->p[0] = d->f(n, d->p + 1, NULL, d->f_data); d->stop->nevals++; + if (nlopt_stop_forced(d->stop)) return NLOPT_FORCE_STOP; if (d->p[0] < worst->k[0]) break; if (nlopt_stop_evals(d->stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(d->stop)) return NLOPT_MAXTIME_REACHED; diff --git a/isres/isres.c b/isres/isres.c index 496c7f0..53da615 100644 --- a/isres/isres.c +++ b/isres/isres.c @@ -164,7 +164,8 @@ nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, if (ret != NLOPT_SUCCESS) goto done; } - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; if (ret != NLOPT_SUCCESS) goto done; } diff --git a/luksan/plip.c b/luksan/plip.c index 7d1e254..975a5b0 100644 --- a/luksan/plip.c +++ b/luksan/plip.c @@ -516,6 +516,7 @@ nlopt_result luksan_plip(int n, nlopt_func f, void *f_data, case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; + case -999: return NLOPT_FORCE_STOP; default: return NLOPT_FAILURE; } } diff --git a/luksan/plis.c b/luksan/plis.c index e9ef510..d0e4adf 100644 --- a/luksan/plis.c +++ b/luksan/plis.c @@ -509,6 +509,7 @@ nlopt_result luksan_plis(int n, nlopt_func f, void *f_data, case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; + case -999: return NLOPT_FORCE_STOP; default: return NLOPT_FAILURE; } } diff --git a/luksan/pnet.c b/luksan/pnet.c index c563c96..4f506af 100644 --- a/luksan/pnet.c +++ b/luksan/pnet.c @@ -659,6 +659,7 @@ nlopt_result luksan_pnet(int n, nlopt_func f, void *f_data, case 4: return NLOPT_SUCCESS; /* gradient tolerance reached */ case 6: return NLOPT_SUCCESS; case 12: case 13: return NLOPT_MAXEVAL_REACHED; + case -999: return NLOPT_FORCE_STOP; default: return NLOPT_FAILURE; } } diff --git a/luksan/pssubs.c b/luksan/pssubs.c index 2096c19..cf7b1db 100644 --- a/luksan/pssubs.c +++ b/luksan/pssubs.c @@ -894,6 +894,10 @@ void luksan_pyfut1__(int *n, double *f, double *fo, double *umax, d__1 = sqrt((fabs(*f))), d__2 = fabs(*f) / 10.; *fo = *f + min(d__1,d__2); } + if (nlopt_stop_forced(stop)) { + *iterm = -999; + return; + } if (*f <= stop->minf_max /* *tolb */) { *iterm = 3; return; diff --git a/mlsl/mlsl.c b/mlsl/mlsl.c index 434706c..fa48301 100644 --- a/mlsl/mlsl.c +++ b/mlsl/mlsl.c @@ -333,7 +333,8 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; @@ -357,7 +358,8 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, if (!rb_tree_insert(&d.pts, (rb_key) p)) { free(p); ret = NLOPT_OUT_OF_MEMORY; } - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else { @@ -382,6 +384,9 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, double *lm; double t = nlopt_seconds(); + if (nlopt_stop_forced(stop)) { + ret = NLOPT_FORCE_STOP; break; + } if (nlopt_stop_evals(stop)) { ret = NLOPT_MAXEVAL_REACHED; break; } @@ -401,6 +406,7 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data, if (!rb_tree_insert(&d.lms, lm)) { free(lm); ret = NLOPT_OUT_OF_MEMORY; } + else if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; else if (*lm < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_evals(stop)) diff --git a/mma/mma.c b/mma/mma.c index feba141..d882ef8 100644 --- a/mma/mma.c +++ b/mma/mma.c @@ -235,7 +235,8 @@ nlopt_result mma_minimize(int n, nlopt_func f, void *f_data, while (1) { /* outer iterations */ double fprev = fcur; - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; @@ -317,7 +318,8 @@ nlopt_result mma_minimize(int n, nlopt_func f, void *f_data, else if (new_infeasible_constraint) feasible = 0; } - if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; else if (feasible && *minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; diff --git a/neldermead/nldrmd.c b/neldermead/nldrmd.c index f991679..4c30751 100644 --- a/neldermead/nldrmd.c +++ b/neldermead/nldrmd.c @@ -78,6 +78,7 @@ static int reflectpt(int n, double *xnew, #define CHECK_EVAL(xc,fc) \ stop->nevals++; \ + if (nlopt_stop_forced(stop)) { ret=NLOPT_FORCE_STOP; goto done; } \ if ((fc) <= *minf) { \ *minf = (fc); memcpy(x, (xc), n * sizeof(double)); \ if (*minf < stop->minf_max) { ret=NLOPT_MINF_MAX_REACHED; goto done; } \ @@ -290,6 +291,7 @@ nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, *minf = f(n, x, NULL, f_data); stop->nevals++; + if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; diff --git a/neldermead/sbplx.c b/neldermead/sbplx.c index e68bc44..efe68a4 100644 --- a/neldermead/sbplx.c +++ b/neldermead/sbplx.c @@ -79,6 +79,7 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, *minf = f(n, x, NULL, f_data); stop->nevals++; + if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP; if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED; if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED; if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED; diff --git a/newuoa/newuoa.c b/newuoa/newuoa.c index 233b325..d993813 100644 --- a/newuoa/newuoa.c +++ b/newuoa/newuoa.c @@ -2099,7 +2099,8 @@ L290: } ++nf; L310: - if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) rc = NLOPT_FORCE_STOP; + else 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; diff --git a/praxis/praxis.c b/praxis/praxis.c index f68e28b..c9f1356 100644 --- a/praxis/praxis.c +++ b/praxis/praxis.c @@ -1241,7 +1241,8 @@ L4: q_1->fbest = ret_val; memcpy(q_1->xbest, t, n * sizeof(double)); } - if (nlopt_stop_evals(stop)) *ret = NLOPT_MAXEVAL_REACHED; + if (nlopt_stop_forced(stop)) *ret = NLOPT_FORCE_STOP; + else if (nlopt_stop_evals(stop)) *ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) *ret = NLOPT_MAXTIME_REACHED; else if (ret_val <= stop->minf_max) *ret = NLOPT_MINF_MAX_REACHED; return ret_val; diff --git a/subplex/subplex.c b/subplex/subplex.c index 35a5a36..5bbe1d6 100644 --- a/subplex/subplex.c +++ b/subplex/subplex.c @@ -1500,7 +1500,9 @@ L40: *fx = isubc_1.sfbest; } L50: - if (*fx < stop->minf_max) + if (nlopt_stop_forced(stop)) + *iflag = -20; + else if (*fx < stop->minf_max) *iflag = 2; else if (nlopt_stop_evals(stop)) *iflag = -1; diff --git a/util/nlopt-util.h b/util/nlopt-util.h index 2c3f654..715e669 100644 --- a/util/nlopt-util.h +++ b/util/nlopt-util.h @@ -75,6 +75,7 @@ typedef struct { const double *xtol_abs; int nevals, maxeval; double maxtime, start; + int *force_stop; } nlopt_stopping; extern int nlopt_stop_f(const nlopt_stopping *stop, double f, double oldf); extern int nlopt_stop_ftol(const nlopt_stopping *stop, double f, double oldf); @@ -88,6 +89,7 @@ extern int nlopt_stop_xs(const nlopt_stopping *stop, extern int nlopt_stop_evals(const nlopt_stopping *stop); extern int nlopt_stop_time(const nlopt_stopping *stop); extern int nlopt_stop_evalstime(const nlopt_stopping *stop); +extern int nlopt_stop_forced(const nlopt_stopping *stop); /* for local optimizations, temporarily setting eval/time limits */ extern nlopt_result nlopt_optimize_limited(nlopt_opt opt, diff --git a/util/stop.c b/util/stop.c index d77683c..eac93dc 100644 --- a/util/stop.c +++ b/util/stop.c @@ -95,3 +95,8 @@ int nlopt_stop_evalstime(const nlopt_stopping *stop) { return nlopt_stop_evals(stop) || nlopt_stop_time(stop); } + +int nlopt_stop_forced(const nlopt_stopping *stop) +{ + return stop->force_stop && *(stop->force_stop); +} -- 2.30.2