提交 61fe5161 编写于 作者: S Steven G. Johnson

add nlopt_get_errmsg(opt) for more informative error messages; automatically...

add nlopt_get_errmsg(opt) for more informative error messages; automatically used in C++ and Python exceptions
上级 05b7e9df
......@@ -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) {
......
......@@ -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 */
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
}
/*************************************************************************/
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)
......
......@@ -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;
......
......@@ -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));
......
......@@ -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));
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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]);
}
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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,
......
......@@ -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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册