From: stevenj Date: Tue, 11 Nov 2008 22:52:06 +0000 (-0500) Subject: more conservative ftol test in subplex, based on max delta f in simplices, to avoid... X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=6a769934be89122a221bc8bbb695a9ae404a428b;p=nlopt.git more conservative ftol test in subplex, based on max delta f in simplices, to avoid false positives in early iterations where the stepssize is too big to make progress darcs-hash:20081111225206-c8de0-28b9f96be4888599e1201b849664e6dc402d640d.gz --- diff --git a/neldermead/neldermead.h b/neldermead/neldermead.h index f1f35f5..9b6bc4f 100644 --- a/neldermead/neldermead.h +++ b/neldermead/neldermead.h @@ -44,7 +44,7 @@ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop, - double psi, double *scratch); + double psi, double *scratch, double *fdiff); nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ diff --git a/neldermead/nldrmd.c b/neldermead/nldrmd.c index 72d0d02..5091e33 100644 --- a/neldermead/nldrmd.c +++ b/neldermead/nldrmd.c @@ -98,14 +98,18 @@ static int reflectpt(int n, double *xnew, ordinary termination tests, set psi = 0. scratch should contain an array of length >= (n+1)*(n+1) + 2*n, - used as scratch workspace. */ + used as scratch workspace. + + On output, *fdiff will contain the difference between the high + and low function values of the last simplex. */ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, const double *xstep, /* initial step sizes */ nlopt_stopping *stop, - double psi, double *scratch) + double psi, double *scratch, + double *fdiff) { double *pts; /* (n+1) x (n+1) array of n+1 points plus function val [0] */ double *c; /* centroid * n */ @@ -122,6 +126,8 @@ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, rb_tree_init(&t, simplex_compare); + *fdiff = HUGE_VAL; + /* initialize the simplex based on the starting xstep */ memcpy(pts+1, x, sizeof(double)*n); pts[0] = *minf; @@ -165,6 +171,8 @@ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data, double fh = high->k[0], *xh = high->k + 1; double fr; + *fdiff = fh - fl; + if (init_diam == 0) /* initialize diam. for psi convergence test */ for (i = 0; i < n; ++i) init_diam = fabs(xl[i] - xh[i]); @@ -278,7 +286,7 @@ nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, nlopt_stopping *stop) { nlopt_result ret; - double *scratch; + double *scratch, fdiff; *minf = f(n, x, NULL, f_data); stop->nevals++; @@ -290,7 +298,7 @@ nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data, if (!scratch) return NLOPT_OUT_OF_MEMORY; ret = nldrmd_minimize_(n, f, f_data, lb, ub, x, minf, xstep, stop, - 0.0, scratch); + 0.0, scratch, &fdiff); free(scratch); return ret; } diff --git a/neldermead/sbplx.c b/neldermead/sbplx.c index 9d89688..0e970c3 100644 --- a/neldermead/sbplx.c +++ b/neldermead/sbplx.c @@ -107,6 +107,7 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, double normdx = 0; int ns, nsubs = 0; int nevals = stop->nevals; + double fdiff, fdiff_max = 0; memcpy(xprev, x, n * sizeof(double)); fprev = *minf; @@ -153,7 +154,8 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, ++nsubs; nevals = stop->nevals; ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, - xsstep, stop, psi, scratch); + 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); @@ -173,16 +175,17 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, ++nsubs; nevals = stop->nevals; ret = nldrmd_minimize_(ns, subspace_func, &sd, lbs,ubs,xs, minf, - xsstep, stop, psi, scratch); + xsstep, stop, psi, scratch, &fdiff); + if (fdiff > fdiff_max) fdiff_max = fdiff; if (sbplx_verbose) - printf("%d NM iterations for (%d,%d) subspace\n", + printf("sbplx: %d NM iterations for (%d,%d) subspace\n", stop->nevals - 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; /* termination tests: */ - if (nlopt_stop_ftol(stop, *minf, fprev)) { + if (nlopt_stop_ftol(stop, *minf, *minf + fdiff_max)) { ret = NLOPT_FTOL_REACHED; goto done; } @@ -220,6 +223,8 @@ nlopt_result sbplx_minimize(int n, nlopt_func f, void *f_data, if (scale < omega) scale = omega; if (scale > 1/omega) scale = 1/omega; } + if (sbplx_verbose) + printf("sbplx: stepsize scale factor = %g\n", scale); for (i = 0; i < n; ++i) xstep[i] = (dx[i] == 0) ? -(xstep[i] * scale) : copysign(xstep[i] * scale, dx[i]);