chiark / gitweb /
add nlopt_get_errmsg(opt) for more informative error messages; automatically used...
authorSteven G. Johnson <stevenj@alum.mit.edu>
Fri, 17 Apr 2015 02:26:50 +0000 (22:26 -0400)
committerSteven G. Johnson <stevenj@alum.mit.edu>
Fri, 17 Apr 2015 02:26:50 +0000 (22:26 -0400)
17 files changed:
api/nlopt-in.hpp
api/nlopt-internal.h
api/nlopt.h
api/optimize.c
api/options.c
configure.ac
crs/crs.c
esch/esch.c
isres/isres.c
mlsl/mlsl.c
mma/ccsa_quadratic.c
mma/mma.c
neldermead/nldrmd.c
newuoa/newuoa.c
slsqp/slsqp.c
util/nlopt-util.h
util/stop.c

index d2ef93f74f7a04e70da7c3472e1adf2470cba502..582c676fd9704e7dd073d6e8a043356f4ae9bf2a 100644 (file)
@@ -77,9 +77,9 @@ namespace nlopt {
     
     void mythrow(nlopt_result ret) const {
       switch (ret) {
-      case NLOPT_FAILURE: throw std::runtime_error("nlopt failure");
+      case NLOPT_FAILURE: throw std::runtime_error(get_errmsg() ? get_errmsg() : "nlopt failure");
       case NLOPT_OUT_OF_MEMORY: throw std::bad_alloc();
-      case NLOPT_INVALID_ARGS: throw std::invalid_argument("nlopt invalid argument");
+      case NLOPT_INVALID_ARGS: throw std::invalid_argument(get_errmsg() ? get_errmsg() : "nlopt invalid argument");
       case NLOPT_ROUNDOFF_LIMITED: throw roundoff_limited();
       case NLOPT_FORCED_STOP: throw forced_stop();
       default: break;
@@ -468,6 +468,11 @@ namespace nlopt {
     NLOPT_GETSET(int, force_stop)
     void force_stop() { set_force_stop(1); }
 
+    const char *get_errmsg() const { 
+        if (!o) throw std::runtime_error("uninitialized nlopt::opt");
+        return nlopt_get_errmsg(o);
+    }
+
     // algorithm-specific parameters:
 
     void set_local_optimizer(const opt &lo) {
index bc67e44eea27912acc9bd42bc57af117c527d7a0..c4d13d11d20abd870eaf0191fdf969fa264d49ee 100644 (file)
@@ -73,6 +73,8 @@ struct nlopt_opt_s {
      unsigned vector_storage; /* max subspace dimension (0 for default) */
 
      void *work; /* algorithm-specific workspace during optimization */
+
+     char *errmsg; /* description of most recent error */
 };
 
 /*********************************************************************/
@@ -88,6 +90,20 @@ extern unsigned nlopt_stochastic_population;
 
 /*********************************************************************/
 
+#define RETURN_ERR(err, opt, msg) do {          \
+    nlopt_set_errmsg(opt, msg);                 \
+    return err;                                 \
+} while (0)
+
+extern const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+extern void nlopt_unset_errmsg(nlopt_opt opt);
+
+/*********************************************************************/
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif /* __cplusplus */
index b9bb61909d0a1e8a7537e28c1688be6d00c18db9..a0e6b384b1f9f65c23ea086e82bffd31aa408ab5 100644 (file)
@@ -209,6 +209,8 @@ NLOPT_EXTERN(nlopt_result) nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_
 NLOPT_EXTERN(nlopt_algorithm) nlopt_get_algorithm(const nlopt_opt opt);
 NLOPT_EXTERN(unsigned) nlopt_get_dimension(const nlopt_opt opt);
 
+NLOPT_EXTERN(const char*) nlopt_get_errmsg(nlopt_opt opt);
+
 /* constraints: */
 
 NLOPT_EXTERN(nlopt_result) nlopt_set_lower_bounds(nlopt_opt opt, 
index f6f1236599486a211960f0bd0c681985345932f2..2087d8f69480b8e008e32eba45e2c2b1c65cfb17 100644 (file)
@@ -375,7 +375,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
      nlopt_stopping stop;
 
      if (!opt || !x || !minf || !opt->f
-        || opt->maximize) return NLOPT_INVALID_ARGS;
+        || opt->maximize) RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                                      "NULL args to nlopt_optimize_");
 
      /* reset stopping flag */
      nlopt_set_force_stop(opt, 0);
@@ -400,8 +401,11 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
 
      /* check bound constraints */
      for (i = 0; i < n; ++i)
-         if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i])
-              return NLOPT_INVALID_ARGS;
+         if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i]) {
+             nlopt_set_errmsg(opt, "bounds %d fail %g <= %g <= %g",
+                              i, lb[i], x[i], ub[i]);
+             return NLOPT_INVALID_ARGS;
+         }
 
      stop.n = n;
      stop.minf_max = opt->stopval;
@@ -414,12 +418,15 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
      stop.maxtime = opt->maxtime;
      stop.start = nlopt_seconds();
      stop.force_stop = &(opt->force_stop);
+     stop.stop_msg = &(opt->errmsg);
 
      switch (algorithm) {
         case NLOPT_GN_DIRECT:
         case NLOPT_GN_DIRECT_L: 
         case NLOPT_GN_DIRECT_L_RAND: 
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              return cdirect(ni, f, f_data, 
                             lb, ub, x, minf, &stop, 0.0, 
                             (algorithm != NLOPT_GN_DIRECT)
@@ -431,7 +438,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_GN_DIRECT_NOSCAL:
         case NLOPT_GN_DIRECT_L_NOSCAL: 
         case NLOPT_GN_DIRECT_L_RAND_NOSCAL: 
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, 
                                      &stop, 0.0, 
                                      (algorithm != NLOPT_GN_DIRECT)
@@ -441,7 +450,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_GN_ORIG_DIRECT:
         case NLOPT_GN_ORIG_DIRECT_L: {
              direct_return_code dret;
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              opt->work = malloc(sizeof(double) *
                                 nlopt_max_constraint_dim(opt->m,
                                                          opt->fc));
@@ -460,13 +471,22 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
              free(opt->work); opt->work = NULL;
              switch (dret) {
                  case DIRECT_INVALID_BOUNDS:
+                      RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                                 "invalid bounds for DIRECT");
                  case DIRECT_MAXFEVAL_TOOBIG:
+                      RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                                 "maxeval too big for DIRECT");
                  case DIRECT_INVALID_ARGS:
                       return NLOPT_INVALID_ARGS;
                  case DIRECT_INIT_FAILED:
+                      RETURN_ERR(NLOPT_FAILURE, opt,
+                                 "init failed for DIRECT");
                  case DIRECT_SAMPLEPOINTS_FAILED:
+                      RETURN_ERR(NLOPT_FAILURE, opt,
+                                 "sample-points failed for DIRECT");
                  case DIRECT_SAMPLE_FAILED:
-                      return NLOPT_FAILURE;
+                      RETURN_ERR(NLOPT_FAILURE, opt,
+                                 "sample failed for DIRECT");
                  case DIRECT_MAXFEVAL_EXCEEDED:
                  case DIRECT_MAXITER_EXCEEDED:
                       return NLOPT_MAXEVAL_REACHED;
@@ -488,7 +508,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_GD_STOGO:
         case NLOPT_GD_STOGO_RAND:
 #ifdef WITH_CXX
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop,
                                  algorithm == NLOPT_GD_STOGO
                                  ? 0 : (int) POP(2*n)))
@@ -554,7 +576,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
                                 1 + (algorithm - NLOPT_LD_TNEWTON) / 2);
 
         case NLOPT_GN_CRS2_LM:
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, 
                                  (int) POP(0), 0);
 
@@ -566,10 +590,13 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_GD_MLSL_LDS: {
              nlopt_opt local_opt = opt->local_opt;
              nlopt_result ret;
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              if (!local_opt && (algorithm == NLOPT_G_MLSL 
                                 || algorithm == NLOPT_G_MLSL_LDS))
-                  return NLOPT_INVALID_ARGS;
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "local optimizer must be specified for G_MLSL");
              if (!local_opt) { /* default */
                   nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL ||
                                                algorithm == NLOPT_GN_MLSL_LDS)
@@ -582,7 +609,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
                                     algorithm == NLOPT_GN_MLSL_LDS)
                             ? NLOPT_LN_COBYLA : NLOPT_LD_MMA;
                   local_opt = nlopt_create(local_alg, n);
-                  if (!local_opt) return NLOPT_FAILURE;
+                  if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt,
+                                              "failed to create local_opt");
                   nlopt_set_ftol_rel(local_opt, opt->ftol_rel);
                   nlopt_set_ftol_abs(local_opt, opt->ftol_abs);
                   nlopt_set_xtol_rel(local_opt, opt->xtol_rel);
@@ -616,7 +644,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
                                         nlopt_local_search_alg_deriv),
                                      nlopt_count_constraints(opt->m,
                                                              opt->fc));
-             if (!dual_opt) return NLOPT_FAILURE;
+             if (!dual_opt) RETURN_ERR(NLOPT_FAILURE, opt,
+                                        "failed creating dual optimizer");
              nlopt_set_ftol_rel(dual_opt, LO(ftol_rel, 1e-14));
              nlopt_set_ftol_abs(dual_opt, LO(ftol_abs, 0.0));
              nlopt_set_maxeval(dual_opt, LO(maxeval, 100000));
@@ -639,7 +668,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
              if (!opt->dx) {
                   freedx = 1;
                   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
-                       return NLOPT_OUT_OF_MEMORY;
+                       RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt,
+                                  "failed to allocate initial step");
              }
              ret = cobyla_minimize(n, f, f_data, 
                                     opt->m, opt->fc,
@@ -653,7 +683,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_LN_NEWUOA: {
              double step;
              if (initial_step(opt, x, &step) != NLOPT_SUCCESS)
-                  return NLOPT_OUT_OF_MEMORY;
+                  RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt,
+                             "failed to allocate initial step");
              return newuoa(ni, 2*n+1, x, 0, 0, step,
                            &stop, minf, f_noderiv, opt);
         }
@@ -661,7 +692,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         case NLOPT_LN_NEWUOA_BOUND: {
              double step;
              if (initial_step(opt, x, &step) != NLOPT_SUCCESS)
-                  return NLOPT_OUT_OF_MEMORY;
+                  RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt,
+                             "failed to allocate initial step");
              return newuoa(ni, 2*n+1, x, lb, ub, step,
                            &stop, minf, f_noderiv, opt);
         }
@@ -672,7 +704,8 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
              if (!opt->dx) {
                   freedx = 1;
                   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
-                       return NLOPT_OUT_OF_MEMORY;
+                       RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt,
+                                  "failed to allocate initial step");
              }
              ret = bobyqa(ni, 2*n+1, x, lb, ub, opt->dx,
                           &stop, minf, opt->f, opt->f_data);
@@ -688,12 +721,13 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
              if (!opt->dx) {
                   freedx = 1;
                   if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS)
-                       return NLOPT_OUT_OF_MEMORY;
+                       RETURN_ERR(NLOPT_OUT_OF_MEMORY, opt,
+                                  "failed to allocate initial step");
              }
              if (algorithm == NLOPT_LN_NELDERMEAD)
-                  ret= nldrmd_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
+                  ret=nldrmd_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
              else
-                  ret= sbplx_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
+                  ret=sbplx_minimize(ni,f,f_data,lb,ub,x,minf,opt->dx,&stop);
              if (freedx) { free(opt->dx); opt->dx = NULL; }
              return ret;
         }
@@ -708,14 +742,16 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
              nlopt_result ret;
              if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ)
                  && !local_opt)
-                  return NLOPT_INVALID_ARGS;
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "local optimizer must be specified for AUGLAG");
              if (!local_opt) { /* default */
                   local_opt = nlopt_create(
                        algorithm == NLOPT_LN_AUGLAG || 
                        algorithm == NLOPT_LN_AUGLAG_EQ
                        ? nlopt_local_search_alg_nonderiv
                        : nlopt_local_search_alg_deriv, n);
-                  if (!local_opt) return NLOPT_FAILURE;
+                  if (!local_opt) RETURN_ERR(NLOPT_FAILURE, opt,
+                                              "failed to create local_opt");
                   nlopt_set_ftol_rel(local_opt, opt->ftol_rel);
                   nlopt_set_ftol_abs(local_opt, opt->ftol_abs);
                   nlopt_set_xtol_rel(local_opt, opt->xtol_rel);
@@ -738,7 +774,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
         }
 
         case NLOPT_GN_ISRES:
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              return isres_minimize(ni, f, f_data, 
                                    (int) (opt->m), opt->fc,
                                    (int) (opt->p), opt->h,
@@ -746,7 +784,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf)
                                    (int) POP(0));
 
        case NLOPT_GN_ESCH:
-             if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS;
+              if (!finite_domain(n, lb, ub))
+                  RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                             "finite domain required for global algorithm");
              return chevolutionarystrategy(n, f, f_data, 
                                            lb, ub, x, minf, &stop,
                                            (unsigned) POP(0),
@@ -803,7 +843,9 @@ NLOPT_STDCALL nlopt_optimize(nlopt_opt opt, double *x, double *opt_f)
      int maximize;
      nlopt_result ret;
 
-     if (!opt || !opt_f || !opt->f) return NLOPT_INVALID_ARGS;
+     nlopt_unset_errmsg(opt);
+     if (!opt || !opt_f || !opt->f) RETURN_ERR(NLOPT_INVALID_ARGS, opt,
+                                               "NULL args to nlopt_optimize");
      f = opt->f; f_data = opt->f_data; pre = opt->pre;
 
      /* for maximizing, just minimize the f_max wrapper, which 
@@ -820,7 +862,11 @@ NLOPT_STDCALL nlopt_optimize(nlopt_opt opt, double *x, double *opt_f)
          nlopt_opt elim_opt = opt;
          if (elimdim_wrapcheck(opt)) {
               elim_opt = elimdim_create(opt);
-              if (!elim_opt) { ret = NLOPT_OUT_OF_MEMORY; goto done; }
+              if (!elim_opt) { 
+                   nlopt_set_errmsg(opt, "failure allocating elim_opt");
+                   ret = NLOPT_OUT_OF_MEMORY;
+                   goto done;
+               }
               elimdim_shrink(opt->n, x, opt->lb, opt->ub);
          }
 
@@ -852,7 +898,9 @@ nlopt_result nlopt_optimize_limited(nlopt_opt opt, double *x, double *minf,
      double save_maxtime;
      nlopt_result ret;
 
-     if (!opt) return NLOPT_INVALID_ARGS;
+     nlopt_unset_errmsg(opt);
+
+     if (!opt) RETURN_ERR(NLOPT_INVALID_ARGS, opt, "NULL opt arg");
 
      save_maxeval = nlopt_get_maxeval(opt);
      save_maxtime = nlopt_get_maxtime(opt);
index d6d18278ad8b3bec6ec44cdeba57e62998a135fe..69c7693cb2e1597e8af459d6668ec5dca2b2524d 100644 (file)
@@ -25,6 +25,7 @@
 #include <math.h>
 #include <string.h>
 #include <float.h>
+#include <stdarg.h>
 
 #include "nlopt-internal.h"
 
@@ -53,6 +54,7 @@ void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt)
          nlopt_destroy(opt->local_opt);
          free(opt->dx);
          free(opt->work);
+         free(opt->errmsg);
          free(opt);
      }
 }
@@ -91,6 +93,7 @@ nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n)
          opt->vector_storage = 0;
          opt->dx = NULL;
          opt->work = NULL;
+         opt->errmsg = NULL;
 
          if (n > 0) {
               opt->lb = (double *) malloc(sizeof(double) * (n));
@@ -126,7 +129,8 @@ nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt)
          nopt->local_opt = NULL;
          nopt->dx = NULL;
          nopt->work = NULL;
-         opt->force_stop_child = NULL;
+         nopt->errmsg = NULL;
+         nopt->force_stop_child = NULL;
 
          munge = nopt->munge_on_copy;
          if (munge && nopt->f_data)
@@ -751,3 +755,25 @@ void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt,
 }
 
 /*************************************************************************/
+
+const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    opt->errmsg = nlopt_vsprintf(opt->errmsg, format, ap);
+    va_end(ap);
+    return opt->errmsg;
+}
+
+void nlopt_unset_errmsg(nlopt_opt opt)
+{
+    free(opt->errmsg);
+    opt->errmsg = NULL;
+}
+
+const char *nlopt_get_errmsg(nlopt_opt opt)
+{
+    return opt->errmsg;
+}
+
+/*************************************************************************/
index 3b9308006cb2a20e9d6812d0e22643637ba490e2..cb8a4f9fa1d75bd9ac02b0fe27d75d9a33204288 100644 (file)
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(nlopt, 2.4.2, stevenj@alum.mit.edu)
+AC_INIT(nlopt, 2.5, stevenj@alum.mit.edu)
 AC_CONFIG_SRCDIR(api/nlopt.h)
-SHARED_VERSION_INFO="8:2:8" # CURRENT:REVISION:AGE
+SHARED_VERSION_INFO="9:0:9" # CURRENT:REVISION:AGE
 
 AM_INIT_AUTOMAKE(1.7)
 AM_CONFIG_HEADER(config.h)
index d6eb5e2f4354e17ad250a8abdbfa67d0792d5be2..16f4ad5e63556fe1bbd09dde79531fe629c4bdbe 100644 (file)
--- a/crs/crs.c
+++ b/crs/crs.c
@@ -177,8 +177,11 @@ static nlopt_result crs_init(crs_data *d, int n, const double *x,
      }
      else
          d->N = population;
-     if (d->N < n + 1) /* population must be big enough for a simplex */
-         return NLOPT_INVALID_ARGS;
+     if (d->N < n + 1) { /* population must be big enough for a simplex */
+          nlopt_stop_msg(stop, "population %d should be >= dimension + 1 = %d",
+                         d->N, n+1);
+          return NLOPT_INVALID_ARGS;
+     }
 
      d->n = n;
      d->stop = stop;
index e2c01d745a461d30ca89889a724f2b089807226a..8a21cb9ccce23a4baa184ce0bfdb0cfcc9ed5398 100644 (file)
@@ -95,7 +95,10 @@ nlopt_result chevolutionarystrategy(
      // -------------------------------
      if (!np) np = 40;
      if (!no) no = 60;     
-     if ((np < 1)||(no<1)) return NLOPT_INVALID_ARGS;
+     if ((np < 1)||(no<1)) {
+         nlopt_stop_msg(stop, "populations %d, %d are too small", np, no);
+         return NLOPT_INVALID_ARGS;
+     }
      esparents    = (Individual*) malloc(sizeof(Individual) * np);
      esoffsprings = (Individual*) malloc(sizeof(Individual) * no);
      estotal    = (Individual*) malloc(sizeof(Individual) * (np+no));
index 02b6f3c211ca76c4828c4fb83ae64059d4175b43..0e40106db27b7b190953930cfabc8de83da3f8b7 100644 (file)
@@ -86,15 +86,20 @@ nlopt_result isres_minimize(int n, nlopt_func f, void *f_data,
      *minf = HUGE_VAL;
 
      if (!population) population = 20 * (n + 1);
-     if (population < 1) return NLOPT_INVALID_ARGS;
+     if (population < 1) {
+         nlopt_stop_msg(stop, "population %d is too small", population);
+         return NLOPT_INVALID_ARGS;
+     }
      survivors = ceil(population * SURVIVOR);
 
      taup = PHI / sqrt(2*n);
      tau = PHI / sqrt(2*sqrt(n));
 
      /* we don't handle unbounded search regions */
-     for (j = 0; j < n; ++j) if (nlopt_isinf(lb[j]) || nlopt_isinf(ub[j]))
-                                 return NLOPT_INVALID_ARGS;
+     for (j = 0; j < n; ++j) if (nlopt_isinf(lb[j]) || nlopt_isinf(ub[j])) {
+             nlopt_stop_msg(stop, "isres requires a finite search region");
+             return NLOPT_INVALID_ARGS;
+         }
 
      ires = imax2(nlopt_max_constraint_dim(m, fc),
                  nlopt_max_constraint_dim(p, h));
index da57c95cecb26ae36b7daaec7a62f18259c47b71..b90d690487e08b1fa9323925680809128dfd5172 100644 (file)
@@ -292,7 +292,10 @@ nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data,
          d.N = 4; /* FIXME: what is good number of samples per iteration? */
      else
          d.N = Nsamples;
-     if (d.N < 1) return NLOPT_INVALID_ARGS;
+     if (d.N < 1) {
+         nlopt_stop_msg(stop, "population %d is too small", d.N);
+         return NLOPT_INVALID_ARGS;
+     }
 
      d.n = n;
      d.lb = lb; d.ub = ub;
index 199005e8cc9cbd31e4ef9be116fb4ffac88d1039..ddbf77e13147744773354880acf3bae26f90ed5d 100644 (file)
@@ -234,7 +234,11 @@ nlopt_result ccsa_quadratic_minimize(
      nlopt_opt pre_opt = NULL;
 
      m = nlopt_count_constraints(mfc = m, fc);
-     if (nlopt_get_dimension(dual_opt) != m) return NLOPT_INVALID_ARGS;
+     if (nlopt_get_dimension(dual_opt) != m) {
+         nlopt_stop_msg(stop, "dual optimizer has wrong dimension %d != %d",
+                        nlopt_get_dimension(dual_opt), m);
+         return NLOPT_INVALID_ARGS;
+     }
      sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7));
      if (!sigma) return NLOPT_OUT_OF_MEMORY;
      dfdx = sigma + n;
@@ -298,7 +302,11 @@ nlopt_result ccsa_quadratic_minimize(
          pre_ub = pre_lb + n;
 
          pre_opt = nlopt_create(nlopt_get_algorithm(dual_opt), n);
-         if (!pre_opt) { ret = NLOPT_FAILURE; goto done; }
+         if (!pre_opt) { 
+              nlopt_stop_msg(stop, "failure creating precond. optimizer");
+              ret = NLOPT_FAILURE;
+              goto done;
+          }
          ret = nlopt_set_min_objective(pre_opt, g0, &dd);
          if (ret < 0) goto done;
          ret = nlopt_add_inequality_mconstraint(pre_opt, m, gi, &dd, NULL);
index 3d03bfd6a932043ed533a2a00f9beef6a64708e0..d7e9725ad5c21e01e4c6380a6c915c6747fc52de 100644 (file)
--- a/mma/mma.c
+++ b/mma/mma.c
@@ -166,7 +166,11 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data,
      unsigned mfc;
 
      m = nlopt_count_constraints(mfc = m, fc);
-     if (nlopt_get_dimension(dual_opt) != m) return NLOPT_INVALID_ARGS;
+     if (nlopt_get_dimension(dual_opt) != m) {
+         nlopt_stop_msg(stop, "dual optimizer has wrong dimension %d != %d",
+                        nlopt_get_dimension(dual_opt), m);
+         return NLOPT_INVALID_ARGS;
+     }
      sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7));
      if (!sigma) return NLOPT_OUT_OF_MEMORY;
      dfdx = sigma + n;
index 5bdc1f33bfff53d045ea5ffcdb46e8275d8ea0aa..a8e7ee479b079560dc04587c1be3c4b0d2d634dc 100644 (file)
@@ -153,7 +153,12 @@ nlopt_result nldrmd_minimize_(int n, nlopt_func f, void *f_data,
                                           ub[i] : lb[i]) + x[i]);
               }
          }
-         if (close(pt[1+i], x[i])) { ret=NLOPT_FAILURE; goto done; }
+         if (close(pt[1+i], x[i])) { 
+              nlopt_stop_msg(stop, "starting step size led to simplex that was too small in dimension %d: %g is too close to x[%d]=%g",
+                             i, pt[1+i], i, x[i]);
+              ret=NLOPT_FAILURE;
+              goto done; 
+          }
          pt[0] = f(n, pt+1, NULL, f_data);
          CHECK_EVAL(pt+1, pt[0]);
      }
index 711cf4f73a6502a7e5b2334dcf9abf64fe8f409c..f6ad2ce72c7a630ea7d75a5cb9ed5ec2d9c8fd71 100644 (file)
@@ -2519,8 +2519,13 @@ nlopt_result newuoa(int n, int npt, double *x,
     /* Function Body */
     np = n + 1;
     nptm = npt - np;
-    if (n < 2 || npt < n + 2 || npt > (n + 2) * np / 2) {
-        return NLOPT_INVALID_ARGS;
+    if (n < 2) {
+        nlopt_stop_msg(stop, "dimension %d must be >= 2", n);
+        return NLOPT_INVALID_ARGS;
+    }
+    if (npt < n + 2 || npt > (n + 2) * np / 2) {
+        nlopt_stop_msg(stop, "invalid # of interpolation conditions %d", npt);
+        return NLOPT_INVALID_ARGS;
     }
     ndim = npt + n;
     ixb = 1;
index 7a341d60785ff49f362407a31f9c8befe627fe99..2548e91d1e10d65c94da08a6be8b176a347acc93 100644 (file)
@@ -2580,10 +2580,12 @@ nlopt_result nlopt_slsqp(unsigned n, nlopt_func f, void *f_data,
              case 4: /* inequality constraints incompatible */
              case 3: /* more than 3*n iterations in LSQ subproblem */
              case 9: /* more than iter iterations in SQP */
+                  nlopt_stop_msg(stop, "bug: more than iter SQP iterations");
                  ret = NLOPT_FAILURE;
                  goto done;
              case 2: /* number of equality constraints > n */
              default: /* >= 10: working space w or jw too small */
+                  nlopt_stop_msg(stop, "bug: workspace is too small");
                  ret = NLOPT_INVALID_ARGS;
                  goto done;
          }
index d20a8b1674e9c13249ade741e97bf6c7dfc81c97..a2f5fd61b428de12d6919b072ba64d91f393fc7c 100644 (file)
@@ -24,6 +24,7 @@
 #define NLOPT_UTIL_H
 
 #include <stdlib.h>
+#include <stdarg.h>
 #include <math.h>
 #include "config.h"
 
@@ -82,6 +83,7 @@ typedef struct {
      int nevals, maxeval;
      double maxtime, start;
      int *force_stop;
+     char **stop_msg; /* pointer to msg string to update */
 } 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);
@@ -98,6 +100,14 @@ 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);
 
+/* like vsprintf, but reallocs p to whatever size is needed */
+extern char *nlopt_vsprintf(char *p, const char *format, va_list ap);
+extern void nlopt_stop_msg(const nlopt_stopping *s, const char *format, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+
 /* for local optimizations, temporarily setting eval/time limits */
 extern nlopt_result nlopt_optimize_limited(nlopt_opt opt, 
                                           double *x, double *minf,
index 9e29a75a8959458bd986a4d1460bd3ec89141c4e..8d999bfadf497d92b447fa0fb29d35a5eb643f66 100644 (file)
@@ -21,6 +21,9 @@
  */
 
 #include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
 #include "nlopt-util.h"
 
 /* utility routines to implement the various stopping criteria */
@@ -132,3 +135,31 @@ void nlopt_eval_constraint(double *result, double *grad,
      else
          c->mf(c->m, result, n, x, grad, c->f_data);
 }
+
+char *nlopt_vsprintf(char *p, const char *format, va_list ap)
+{
+    size_t len = strlen(format) + 128;
+    int ret;
+
+    p = (char *) realloc(p, len);
+    if (!p) abort();
+    
+    while ((ret = vsnprintf(p, len, format, ap)) < 0 || (size_t)ret >= len) {
+        /* C99 vsnprintf returns the required number of bytes (excluding \0)
+           if the buffer is too small; older versions (e.g. MS) return -1 */
+        len = ret >= 0 ? (size_t)(ret + 1) : (len*3)>>1;
+        p = realloc(p, len);
+        if (!p) abort();
+    }
+    return p;
+}
+
+void nlopt_stop_msg(const nlopt_stopping *s, const char *format, ...)
+{
+    va_list ap;
+    if (s->stop_msg) {
+        va_start(ap, format);
+        *(s->stop_msg) = nlopt_vsprintf(*(s->stop_msg), format, ap);
+        va_end(ap);
+    }
+}