diff --git a/doc/docs/NLopt_Algorithms.md b/doc/docs/NLopt_Algorithms.md index 83592ae0..acb14560 100644 --- a/doc/docs/NLopt_Algorithms.md +++ b/doc/docs/NLopt_Algorithms.md @@ -337,6 +337,7 @@ specified using the [`nlopt_set_param` API](NLopt_Reference.md#algorithm-specifi * `dual_algorithm` (defaults to `NLOPT_LD_MMA`), `dual_ftol_rel` (defaults to `1e-14`), `dual_ftol_abs` (defaults to `0`), `dual_xtol_rel` (defaults to `0`), `dual_xtol_abs` (defaults to `0`), `dual_maxeval` (defaults to `100000`): These specify how the algorithm internally solves the "dual" optimization problem for its approximate objective. Because this subsidiary solve requires no evaluations of the user's objective function, it is typically fast enough that we can solve it to high precision without worrying too much about the details. Howeve,r in high-dimensional problems you may notice that MMA/CCSA is taking a long time between optimization steps, in which case you may want to increase `dual_ftol_rel` or make other changes. If these parameters are not specified, NLopt takes them from the [subsidiary-optimizer algorithm](NLopt_Reference.md#localsubsidiary-optimization-algorithm) if that has been specified, and otherwise uses the defaults indicated here. * `verbosity`: If > 0, causes the algorithm to print internal status information on each iteration. * `rho_init`: if specified, should be a rough upper bound for the second derivative (the biggest eigenvalue of the Hessian of the objective or constraints); defaults to `1.0`. CCSA/MMA will adaptively adjust this as the optimization progresses, so even it if `rho_init` is completely wrong the algorithm will still converge. A `rho_init` that is too large will cause the algorithm to take overly small steps at the beginning, while a `rho_init` that is too small will cause it to take overly large steps (and have to backtrack) at the beginning. Similarly, you can also use the "initial stepsize" option ([NLopt reference](NLopt_Reference.md#initial-step-size)) to control the maximum size of the initial steps (half the diameter of the trust region). +* `outer_mineval_xftol`: When the outer iteration step of MMA/CCSA is less than `outer_mineval_xftol`, the stopping criteria of `xtol` and `ftol` are disabled. This is quite useful in some optimization problems where there is a "startup" process during which *x* and *f* change slowly. The default value of `outer_mineval_xftol` is `0`. ### SLSQP diff --git a/src/algs/mma/ccsa_quadratic.c b/src/algs/mma/ccsa_quadratic.c index f89fc78e..f405002c 100644 --- a/src/algs/mma/ccsa_quadratic.c +++ b/src/algs/mma/ccsa_quadratic.c @@ -218,7 +218,7 @@ nlopt_result ccsa_quadratic_minimize( double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, - nlopt_opt dual_opt, int inner_maxeval, unsigned verbose, double rho_init, + nlopt_opt dual_opt, int inner_maxeval, int outer_mineval_xftol, unsigned verbose, double rho_init, const double *sigma_init) { nlopt_result ret = NLOPT_SUCCESS; @@ -523,9 +523,9 @@ nlopt_result ccsa_quadratic_minimize( printf(" CCSA rhoc[%u] -> %g\n", i,rhoc[i]); } - if (nlopt_stop_ftol(stop, fcur, fprev)) + if (k >= outer_mineval_xftol && nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; - if (nlopt_stop_x(stop, xcur, xprev)) + if (k >= outer_mineval_xftol && nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; if (ret != NLOPT_SUCCESS) goto done; diff --git a/src/algs/mma/mma.c b/src/algs/mma/mma.c index 3236099c..bb47ab2a 100644 --- a/src/algs/mma/mma.c +++ b/src/algs/mma/mma.c @@ -148,7 +148,7 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, - nlopt_opt dual_opt, int inner_maxeval, unsigned verbose, double rho_init, + nlopt_opt dual_opt, int inner_maxeval, int outer_mineval_xftol, unsigned verbose, double rho_init, const double *sigma_init) { nlopt_result ret = NLOPT_SUCCESS; @@ -375,9 +375,9 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, printf(" MMA rhoc[%u] -> %g\n", i,rhoc[i]); } - if (nlopt_stop_ftol(stop, fcur, fprev)) + if (k >= outer_mineval_xftol && nlopt_stop_ftol(stop, fcur, fprev)) ret = NLOPT_FTOL_REACHED; - if (nlopt_stop_x(stop, xcur, xprev)) + if (k >= outer_mineval_xftol && nlopt_stop_x(stop, xcur, xprev)) ret = NLOPT_XTOL_REACHED; if (ret != NLOPT_SUCCESS) goto done; diff --git a/src/algs/mma/mma.h b/src/algs/mma/mma.h index ca2131c4..5aba5257 100644 --- a/src/algs/mma/mma.h +++ b/src/algs/mma/mma.h @@ -40,7 +40,7 @@ nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data, double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, - nlopt_opt dual_opt, int inner_maxeval, unsigned verbose, double rho_init, + nlopt_opt dual_opt, int inner_maxeval, int outer_mineval_xftol, unsigned verbose, double rho_init, const double *sigma_init); nlopt_result ccsa_quadratic_minimize( @@ -53,7 +53,7 @@ nlopt_result ccsa_quadratic_minimize( double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, - nlopt_opt dual_opt, int inner_maxeval, unsigned verbose, double rho_init, + nlopt_opt dual_opt, int inner_maxeval, int outer_mineval_xftol, unsigned verbose, double rho_init, const double *sigma_init); #ifdef __cplusplus diff --git a/src/api/optimize.c b/src/api/optimize.c index 4cc6583b..38f4013f 100644 --- a/src/api/optimize.c +++ b/src/api/optimize.c @@ -796,6 +796,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) case NLOPT_LD_CCSAQ: { int inner_maxeval = (int)nlopt_get_param(opt, "inner_maxeval",0); + int outer_mineval_xftol = (int)nlopt_get_param(opt, "outer_mineval_xftol", 0); int verbosity = (int)nlopt_get_param(opt, "verbosity",0); double rho_init = nlopt_get_param(opt, "rho_init",1.0); nlopt_opt dual_opt; @@ -817,9 +818,9 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) nlopt_set_maxeval(dual_opt, (int)nlopt_get_param(opt, "dual_maxeval", LO(maxeval, 100000))); #undef LO if (algorithm == NLOPT_LD_MMA) - ret = mma_minimize(n, f, f_data, opt->m, opt->fc, lb, ub, x, minf, &stop, dual_opt, inner_maxeval, (unsigned)verbosity, rho_init, opt->dx); + ret = mma_minimize(n, f, f_data, opt->m, opt->fc, lb, ub, x, minf, &stop, dual_opt, inner_maxeval, outer_mineval_xftol, (unsigned)verbosity, rho_init, opt->dx); else - ret = ccsa_quadratic_minimize(n, f, f_data, opt->m, opt->fc, opt->pre, lb, ub, x, minf, &stop, dual_opt, inner_maxeval, (unsigned)verbosity, rho_init, opt->dx); + ret = ccsa_quadratic_minimize(n, f, f_data, opt->m, opt->fc, opt->pre, lb, ub, x, minf, &stop, dual_opt, inner_maxeval, outer_mineval_xftol, (unsigned)verbosity, rho_init, opt->dx); nlopt_destroy(dual_opt); return ret; }