chiark / gitweb /
more conservative ftol test in subplex, based on max delta f in simplices, to avoid...
authorstevenj <stevenj@alum.mit.edu>
Tue, 11 Nov 2008 22:52:06 +0000 (17:52 -0500)
committerstevenj <stevenj@alum.mit.edu>
Tue, 11 Nov 2008 22:52:06 +0000 (17:52 -0500)
darcs-hash:20081111225206-c8de0-28b9f96be4888599e1201b849664e6dc402d640d.gz

neldermead/neldermead.h
neldermead/nldrmd.c
neldermead/sbplx.c

index f1f35f5d8005672a2785653045181b8da920fff5..9b6bc4fa076aa69207226fbe857a6e2f36ce8cb9 100644 (file)
@@ -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 */
index 72d0d02457d006b860f9ce92852058c4090e5ec9..5091e334d27f38f05b2c23847febfd0e3cf67a3e 100644 (file)
@@ -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;
 }
index 9d896888b28543cba0ced935029cca99da599663..0e970c3c50e5ec306dd3614f20234507c7182a0a 100644 (file)
@@ -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]);