From: stevenj Date: Thu, 28 Oct 2010 23:00:02 +0000 (-0400) Subject: fix support for maxtime in Luksan algorithms and ORIG_DIRECT; thanks to Jurgen Werner... X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=edc79911a3f97b2067b4ccef8bbfa6a4da9eaff1;p=nlopt.git fix support for maxtime in Luksan algorithms and ORIG_DIRECT; thanks to Jurgen Werner for the bug report darcs-hash:20101028230002-c8de0-c51903a73ffc18f3ddd4e5d68edc3580d1676f3d.gz --- diff --git a/api/optimize.c b/api/optimize.c index cfaa3c5..25e0852 100644 --- a/api/optimize.c +++ b/api/optimize.c @@ -227,7 +227,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) opt->fc)); if (!opt->work) return NLOPT_OUT_OF_MEMORY; dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf, - stop.maxeval, -1, 0.0, 0.0, + stop.maxeval, -1, + stop.start, stop.maxtime, + 0.0, 0.0, pow(stop.xtol_rel, (double) n), -1.0, stop.force_stop, stop.minf_max, 0.0, @@ -248,6 +250,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) case DIRECT_MAXFEVAL_EXCEEDED: case DIRECT_MAXITER_EXCEEDED: return NLOPT_MAXEVAL_REACHED; + case DIRECT_MAXTIME_EXCEEDED: + return NLOPT_MAXTIME_REACHED; case DIRECT_GLOBAL_FOUND: return NLOPT_MINF_MAX_REACHED; case DIRECT_VOLTOL: @@ -271,7 +275,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) return NLOPT_FAILURE; break; #else - return NLOPT_FAILURE; + return NLOPT_INVALID_ARGS; #endif #if 0 diff --git a/cobyla/cobyla.c b/cobyla/cobyla.c index 64c605f..f8b08e9 100644 --- a/cobyla/cobyla.c +++ b/cobyla/cobyla.c @@ -562,8 +562,10 @@ static nlopt_result cobylb(int *n, int *m, int *mpp, L40: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; - else if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; - else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; + else if (stop->nevals > 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++; diff --git a/direct/DIRect.c b/direct/DIRect.c index 1bd4bbf..f0a7c1a 100644 --- a/direct/DIRect.c +++ b/direct/DIRect.c @@ -44,7 +44,7 @@ /* | Lipschitz continues. However, DIRECT has proven to be effective on | */ /* | more complex problems than these. | */ /* +-----------------------------------------------------------------------+ */ -/* Subroutine */ void direct_direct_(fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs, integer *maxf, integer *maxt, int *force_stop, doublereal *minf, doublereal *l, +/* Subroutine */ void direct_direct_(fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs, integer *maxf, integer *maxt, double starttime, double maxtime, int *force_stop, doublereal *minf, doublereal *l, doublereal *u, integer *algmethod, integer *ierror, FILE *logfile, doublereal *fglobal, doublereal *fglper, doublereal *volper, doublereal *sigmaper, void *fcn_data) @@ -406,7 +406,7 @@ logfile, arrayi, &maxi, list2, w, &x[1], &l[1], &u[1], minf, &minpos, thirds, levels, &MAXFUNC, &MAXDEEP, n, n, & fmax, &ifeasiblef, &iinfesiblef, ierror, fcn_data, jones, - force_stop); + starttime, maxtime, force_stop); /* +-----------------------------------------------------------------------+ */ /* | Added error checking. | */ /* +-----------------------------------------------------------------------+ */ @@ -423,6 +423,7 @@ } if (*ierror == -102) goto L100; } + else if (*ierror == DIRECT_MAXTIME_EXCEEDED) goto L100; numfunc = maxi + 1 + maxi; actmaxdeep = 1; oldpos = 0; @@ -551,6 +552,10 @@ *ierror = -102; goto L100; } + if (nlopt_stop_time_(starttime, maxtime)) { + *ierror = DIRECT_MAXTIME_EXCEEDED; + goto L100; + } if (oops > 0) { if (logfile) fprintf(logfile, "WARNING: Error occured in routine DIRsamplef.\n"); diff --git a/direct/DIRsubrout.c b/direct/DIRsubrout.c index b5889a5..7414961 100644 --- a/direct/DIRsubrout.c +++ b/direct/DIRsubrout.c @@ -1144,7 +1144,7 @@ L50: doublereal *thirds, doublereal *levels, integer *maxfunc, const integer * maxdeep, integer *n, integer *maxor, doublereal *fmax, integer * ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata, - integer jones, int *force_stop) + integer jones, double starttime, double maxtime, int *force_stop) { /* System generated locals */ integer c_dim1, c_offset, length_dim1, length_offset, list2_dim1, @@ -1262,6 +1262,10 @@ L50: point[1] = 0; *free = 2; delta = thirds[1]; + if (nlopt_stop_time_(starttime, maxtime)) { + *ierror = DIRECT_MAXTIME_EXCEEDED; + return; + } direct_dirget_i__(&length[length_offset], &c__1, &arrayi[1], maxi, n, maxfunc); new__ = *free; direct_dirsamplepoints_(&c__[c_offset], &arrayi[1], &delta, &c__1, &new__, & @@ -1288,6 +1292,10 @@ L50: *ierror = -102; return; } + if (nlopt_stop_time_(starttime, maxtime)) { + *ierror = DIRECT_MAXTIME_EXCEEDED; + return; + } /* +-----------------------------------------------------------------------+ */ /* | JG 01/23/01 Added error checking. | */ /* +-----------------------------------------------------------------------+ */ diff --git a/direct/direct-internal.h b/direct/direct-internal.h index ed3e4df..fb4b274 100644 --- a/direct/direct-internal.h +++ b/direct/direct-internal.h @@ -40,7 +40,7 @@ extern void direct_dirinit_( doublereal *thirds, doublereal *levels, integer *maxfunc, const integer * maxdeep, integer *n, integer *maxor, doublereal *fmax, integer * ifeasiblef, integer *iinfeasible, integer *ierror, void *fcndata, - integer jones, int *force_stop); + integer jones, double starttime, double maxtime, int *force_stop); extern void direct_dirinitlist_( integer *anchor, integer *free, integer * point, doublereal *f, integer *maxfunc, const integer *maxdeep); @@ -108,7 +108,9 @@ extern void direct_dirsamplef_( /* DIRect.c */ extern void direct_direct_( fp fcn, doublereal *x, integer *n, doublereal *eps, doublereal epsabs, - integer *maxf, integer *maxt, int *force_stop, doublereal *minf, doublereal *l, + integer *maxf, integer *maxt, + double starttime, double maxtime, + int *force_stop, doublereal *minf, doublereal *l, doublereal *u, integer *algmethod, integer *ierror, FILE *logfile, doublereal *fglobal, doublereal *fglper, doublereal *volper, doublereal *sigmaper, void *fcn_data); diff --git a/direct/direct.h b/direct/direct.h index cd6a124..2b100b2 100644 --- a/direct/direct.h +++ b/direct/direct.h @@ -28,6 +28,7 @@ typedef enum { DIRECT_GLOBAL_FOUND = 3, DIRECT_VOLTOL = 4, DIRECT_SIGMATOL = 5, + DIRECT_MAXTIME_EXCEEDED = 6, DIRECT_OUT_OF_MEMORY = -100, DIRECT_INVALID_ARGS = -101, @@ -44,7 +45,8 @@ extern direct_return_code direct_optimize( double *x, double *minf, - int max_feval, int max_iter, + int max_feval, int max_iter, + double start, double maxtime, double magic_eps, double magic_eps_abs, double volume_reltol, double sigma_reltol, int *force_stop, diff --git a/direct/direct_wrap.c b/direct/direct_wrap.c index 330743d..98d7c28 100644 --- a/direct/direct_wrap.c +++ b/direct/direct_wrap.c @@ -48,6 +48,7 @@ direct_return_code direct_optimize( double *x, double *minf, int max_feval, int max_iter, + double start, double maxtime, double magic_eps, double magic_eps_abs, double volume_reltol, double sigma_reltol, int *force_stop, @@ -86,7 +87,8 @@ direct_return_code direct_optimize( } direct_direct_(f, x, &dimension, &magic_eps, magic_eps_abs, - &max_feval, &max_iter, force_stop, + &max_feval, &max_iter, + start, maxtime, force_stop, minf, l, u, &algmethod, diff --git a/luksan/plip.c b/luksan/plip.c index c7aef14..7d4e599 100644 --- a/luksan/plip.c +++ b/luksan/plip.c @@ -277,10 +277,10 @@ static void plip_(int *nf, int *nb, double *x, int * if (*iterm != 0) { goto L11190; } - if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++stop->nevals; ++stat_1->nfg; + if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); luksan_pyfut1__(nf, f, &fo, &umax, gmax, xstop, stop, tolg, @@ -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 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } diff --git a/luksan/plis.c b/luksan/plis.c index 9258953..03552f0 100644 --- a/luksan/plis.c +++ b/luksan/plis.c @@ -259,10 +259,10 @@ static void plis_(int *nf, int *nb, double *x, int * if (*iterm != 0) { goto L11190; } - if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++stop->nevals; ++stat_1->nfg; + if (nlopt_stop_time(stop)) { *iterm = 100; goto L11190; } L11120: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); luksan_pyfut1__(nf, f, &fo, &umax, gmax, xstop, stop, tolg, @@ -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 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } diff --git a/luksan/pnet.c b/luksan/pnet.c index f37195c..ac009c7 100644 --- a/luksan/pnet.c +++ b/luksan/pnet.c @@ -301,6 +301,7 @@ static void pnet_(int *nf, int *nb, double *x, int * *f = objgrad(*nf, &x[1], &gf[1], objgrad_data); ++stop->nevals; ++stat_1->nfg; + if (nlopt_stop_time(stop)) { *iterm = 100; goto L11080; } ld = kd; L11020: luksan_pytrcg__(nf, nf, &ix[1], &gf[1], &umax, gmax, &kbf, &iold); @@ -659,6 +660,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 100: return NLOPT_MAXTIME_REACHED; case -999: return NLOPT_FORCED_STOP; default: return NLOPT_FAILURE; } diff --git a/newuoa/newuoa.c b/newuoa/newuoa.c index cc35215..7f5568f 100644 --- a/newuoa/newuoa.c +++ b/newuoa/newuoa.c @@ -2100,8 +2100,10 @@ L290: ++nf; L310: if (nlopt_stop_forced(stop)) rc = NLOPT_FORCED_STOP; - else if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED; - else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED; + else if (stop->nevals > 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++; diff --git a/util/nlopt-util.h b/util/nlopt-util.h index 222ce6f..29934d4 100644 --- a/util/nlopt-util.h +++ b/util/nlopt-util.h @@ -92,6 +92,7 @@ extern int nlopt_stop_xs(const nlopt_stopping *stop, const double *xs, const double *oldxs, const double *scale_min, const double *scale_max); extern int nlopt_stop_evals(const nlopt_stopping *stop); +extern int nlopt_stop_time_(double start, double maxtime); 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); diff --git a/util/stop.c b/util/stop.c index 09e8686..7484ecb 100644 --- a/util/stop.c +++ b/util/stop.c @@ -86,9 +86,14 @@ int nlopt_stop_evals(const nlopt_stopping *s) return (s->maxeval > 0 && s->nevals >= s->maxeval); } +int nlopt_stop_time_(double start, double maxtime) +{ + return (maxtime > 0 && nlopt_seconds() - start >= maxtime); +} + int nlopt_stop_time(const nlopt_stopping *s) { - return (s->maxtime > 0 && nlopt_seconds() - s->start >= s->maxtime); + return nlopt_stop_time_(s->start, s->maxtime); } int nlopt_stop_evalstime(const nlopt_stopping *stop)