From 6a67155ca70e9bb924dfe48a85c16a5cc6e87a4e Mon Sep 17 00:00:00 2001 From: stevenj Date: Mon, 10 Nov 2008 21:41:21 -0500 Subject: [PATCH] first stab at nlopt_minimize_constrained Matlab/Octave wrappers darcs-hash:20081111024121-c8de0-db5892685407b546fc41139d3e2034cd39b898c9.gz --- octave/Makefile.am | 24 ++-- octave/nlopt_minimize.m | 4 + ...mex.c => nlopt_minimize_constrained-mex.c} | 128 ++++++++++++------ ...t.cc => nlopt_minimize_constrained-oct.cc} | 74 ++++++---- octave/nlopt_minimize_constrained.m | 87 ++++++++++++ 5 files changed, 236 insertions(+), 81 deletions(-) rename octave/{nlopt_minimize-mex.c => nlopt_minimize_constrained-mex.c} (61%) rename octave/{nlopt_minimize-oct.cc => nlopt_minimize_constrained-oct.cc} (70%) create mode 100644 octave/nlopt_minimize_constrained.m diff --git a/octave/Makefile.am b/octave/Makefile.am index a3b76e6..0639567 100644 --- a/octave/Makefile.am +++ b/octave/Makefile.am @@ -6,29 +6,29 @@ MFILES = NLOPT_GN_DIRECT.m NLOPT_GN_DIRECT_L.m NLOPT_GN_DIRECT_L_RAND.m NLOPT_GN octdir = $(OCT_INSTALL_DIR) mdir = $(M_INSTALL_DIR) if WITH_OCTAVE -oct_DATA = nlopt_minimize.oct -m_DATA = $(MFILES) nlopt_minimize.m +oct_DATA = nlopt_minimize_constrained.oct +m_DATA = $(MFILES) nlopt_minimize.m nlopt_minimize_constrained.m endif -nlopt_minimize.oct: nlopt_minimize-oct.cc nlopt_minimize_usage.h - $(MKOCTFILE) -o $@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(srcdir)/nlopt_minimize-oct.cc $(LDFLAGS) -L$(top_builddir)/.libs -lnlopt@NLOPT_SUFFIX@ +nlopt_minimize_constrained.oct: nlopt_minimize_constrained-oct.cc nlopt_minimize_constrained_usage.h + $(MKOCTFILE) -o $@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(srcdir)/nlopt_minimize_constrained-oct.cc $(LDFLAGS) -L$(top_builddir)/.libs -lnlopt@NLOPT_SUFFIX@ -nlopt_minimize_usage.h: $(srcdir)/nlopt_minimize.m - echo "#define NLOPT_MINIMIZE_USAGE \\" > $@ - sed 's/\"/\\"/g' $(srcdir)/nlopt_minimize.m | sed 's,^% ,\",;s,^%,\",;s,$$,\\n\" \\,' >> $@ +nlopt_minimize_constrained_usage.h: $(srcdir)/nlopt_minimize_constrained.m + echo "#define NLOPT_MINIMIZE_CONSTRAINED_USAGE \\" > $@ + sed 's/\"/\\"/g' $(srcdir)/nlopt_minimize_constrained.m | sed 's,^% ,\",;s,^%,\",;s,$$,\\n\" \\,' >> $@ echo "" >> $@ ####################################################################### mexdir = $(MEX_INSTALL_DIR) if WITH_MATLAB -mex_DATA = nlopt_minimize.$(MEXSUFF) $(MFILES) nlopt_minimize.m +mex_DATA = nlopt_minimize_constrained.$(MEXSUFF) $(MFILES) nlopt_minimize.m nlopt_minimize_constrained.m endif -nlopt_minimize.$(MEXSUFF): nlopt_minimize-mex.c - $(MEX) -output nlopt_minimize -O $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(srcdir)/nlopt_minimize-mex.c $(LDFLAGS) -L$(top_builddir)/.libs -lnlopt@NLOPT_SUFFIX@ +nlopt_minimize_constrained.$(MEXSUFF): nlopt_minimize_constrained-mex.c + $(MEX) -output nlopt_minimize_constrained -O $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(srcdir)/nlopt_minimize_constrained-mex.c $(LDFLAGS) -L$(top_builddir)/.libs -lnlopt@NLOPT_SUFFIX@ ####################################################################### -EXTRA_DIST = nlopt_minimize-oct.cc nlopt_minimize-mex.c $(MFILES) nlopt_minimize.m +EXTRA_DIST = nlopt_minimize_constrained-oct.cc nlopt_minimize_constrained-mex.c $(MFILES) nlopt_minimize.m nlopt_minimize_constrained.m -CLEANFILES = nlopt_minimize.oct nlopt_minimize_usage.h nlopt_minimize.$(MEXSUFF) nlopt_minimize-oct.o +CLEANFILES = nlopt_minimize_constrained.oct nlopt_minimize_constrained_usage.h nlopt_minimize_constrained.$(MEXSUFF) nlopt_minimize_constrained-oct.o diff --git a/octave/nlopt_minimize.m b/octave/nlopt_minimize.m index 3c95e0c..5dc64e1 100644 --- a/octave/nlopt_minimize.m +++ b/octave/nlopt_minimize.m @@ -64,3 +64,7 @@ % % For more information on individual functions, see their individual % help pages (e.g. "help NLOPT_LN_SUBPLEX"). +[xopt, fmin, retcode] = nlopt_minimize(algorithm, f, f_data, lb, ub, xinit, stop) + + [xopt, fmin, retcode] = nlopt_minimize_constrained(algorithm, f, f_data, {}, {}, lb, ub, xinit, stop); + diff --git a/octave/nlopt_minimize-mex.c b/octave/nlopt_minimize_constrained-mex.c similarity index 61% rename from octave/nlopt_minimize-mex.c rename to octave/nlopt_minimize_constrained-mex.c index f36b0c3..92620f3 100644 --- a/octave/nlopt_minimize-mex.c +++ b/octave/nlopt_minimize_constrained-mex.c @@ -20,7 +20,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Matlab MEX interface to NLopt, and in particular to nlopt_minimize */ +/* Matlab MEX interface to NLopt, and in particular to nlopt_minimize_constrained */ #include #include @@ -46,8 +46,8 @@ static double struct_val_default(const mxArray *s, const char *name, double dflt return dflt; } -#define FLEN 1024 /* max length of user function name */ -#define MAXRHS 1024 /* max nrhs for user function */ +#define FLEN 128 /* max length of user function name */ +#define MAXRHS 128 /* max nrhs for user function */ typedef struct { char f[FLEN]; mxArray *plhs[2]; @@ -84,7 +84,7 @@ static double user_function(int n, const double *x, mxDestroyArray(d->plhs[1]); } d->neval++; - if (d->verbose) mexPrintf("nlopt_minimize eval #%d: %g\n", d->neval, f); + if (d->verbose) mexPrintf("nlopt_minimize_constrained eval #%d: %g\n", d->neval, f); return f; } @@ -92,16 +92,16 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { nlopt_algorithm algorithm; - int n, i; + int n, m, i, j; double *lb, *ub, *x, *x0; double minf_max, ftol_rel, ftol_abs, xtol_rel, *xtol_abs, maxtime; int maxeval; nlopt_result ret; mxArray *x_mx; double minf = HUGE_VAL; - user_function_data d; + user_function_data d, *dc; - CHECK(nrhs == 7 && nlhs <= 3, "wrong number of arguments"); + CHECK(nrhs == 9 && nlhs <= 3, "wrong number of arguments"); /* algorithm = prhs[0] */ CHECK(mxIsNumeric(prhs[0]) && !mxIsComplex(prhs[0]) @@ -121,7 +121,7 @@ void mexFunction(int nlhs, mxArray *plhs[], d.xrhs = 0; } else { - d.prhs[0] = prhs[1]; + d.prhs[0] = (mxArray *) prhs[1]; strcpy(d.f, "feval"); d.nrhs = 2; d.xrhs = 1; @@ -135,39 +135,80 @@ void mexFunction(int nlhs, mxArray *plhs[], for (i = 0; i < d.nrhs - (1+d.xrhs); ++i) d.prhs[(1+d.xrhs)+i] = mxGetCell(prhs[2], i); - /* lb = prhs[3] */ - CHECK(mxIsDouble(prhs[3]) && !mxIsComplex(prhs[3]) - && (mxGetM(prhs[3]) == 1 || mxGetN(prhs[3]) == 1), + /* m = length(fc = prhs[3]) = length(fc_data = prhs[4]) */ + CHECK(mxIsCell(prhs[3]), "fc must be a Cell array"); + CHECK(mxIsCell(prhs[4]), "fc_data must be a Cell array"); + m = mxGetM(prhs[3]) * mxGetN(prhs[3]); + CHECK(m == mxGetM(prhs[4]) * mxGetN(prhs[4]), "fc and fc_data must have the same length"); + dc = (user_function_data *) malloc(sizeof(user_function_data) * m); + + for (j = 0; j < m; ++j) { + mxArray *fc, *fc_data; + + /* function fc = phrs[3] */ + fc = mxGetCell(prhs[3], j); + CHECK(mxIsChar(fc) || mxIsFunctionHandle(fc), + "fc must be Cell array of function handles or function names"); + if (mxIsChar(fc)) { + CHECK(mxGetString(fc, dc[j].f, FLEN) == 0, + "error reading function name string (too long?)"); + dc[j].nrhs = 1; + dc[j].xrhs = 0; + } + else { + dc[j].prhs[0] = fc; + strcpy(dc[j].f, "feval"); + dc[j].nrhs = 2; + dc[j].xrhs = 1; + } + + /* Cell fc_data = prhs[4] */ + fc_data = mxGetCell(prhs[4], j); + CHECK(mxIsCell(fc_data), "fc_data must be a Cell array of Cell arrays"); + CHECK(mxGetM(fc_data) * mxGetN(fc_data) + 1 <= MAXRHS, + "user function cannot have more than " STRIZE(MAXRHS) " arguments"); + dc[j].nrhs += mxGetM(fc_data) * mxGetN(fc_data); + for (i = 0; i < dc[j].nrhs - (1+dc[j].xrhs); ++i) + dc[j].prhs[(1+dc[j].xrhs)+i] = mxGetCell(fc_data, i); + } + + /* lb = prhs[5] */ + CHECK(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) + && (mxGetM(prhs[5]) == 1 || mxGetN(prhs[5]) == 1), "lb must be real row or column vector"); - lb = mxGetPr(prhs[3]); - n = mxGetM(prhs[3]) * mxGetN(prhs[3]); + lb = mxGetPr(prhs[5]); + n = mxGetM(prhs[5]) * mxGetN(prhs[5]); - /* ub = prhs[4] */ - CHECK(mxIsDouble(prhs[4]) && !mxIsComplex(prhs[4]) - && (mxGetM(prhs[4]) == 1 || mxGetN(prhs[4]) == 1) - && mxGetM(prhs[4]) * mxGetN(prhs[4]) == n, + /* ub = prhs[6] */ + CHECK(mxIsDouble(prhs[6]) && !mxIsComplex(prhs[6]) + && (mxGetM(prhs[6]) == 1 || mxGetN(prhs[6]) == 1) + && mxGetM(prhs[6]) * mxGetN(prhs[6]) == n, "ub must be real row or column vector of same length as lb"); - ub = mxGetPr(prhs[4]); + ub = mxGetPr(prhs[6]); - /* x0 = prhs[5] */ - CHECK(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) - && (mxGetM(prhs[5]) == 1 || mxGetN(prhs[5]) == 1) - && mxGetM(prhs[5]) * mxGetN(prhs[5]) == n, + /* x0 = prhs[7] */ + CHECK(mxIsDouble(prhs[7]) && !mxIsComplex(prhs[7]) + && (mxGetM(prhs[7]) == 1 || mxGetN(prhs[7]) == 1) + && mxGetM(prhs[7]) * mxGetN(prhs[7]) == n, "x must be real row or column vector of same length as lb"); - x0 = mxGetPr(prhs[5]); - - /* stopping criteria = prhs[6] */ - CHECK(mxIsStruct(prhs[6]), "stopping criteria must be a struct"); - minf_max = struct_val_default(prhs[6], "minf_max", -HUGE_VAL); - ftol_rel = struct_val_default(prhs[6], "ftol_rel", 0); - ftol_abs = struct_val_default(prhs[6], "ftol_abs", 0); - xtol_rel = struct_val_default(prhs[6], "xtol_rel", 0); - maxeval = (int) (struct_val_default(prhs[6], "maxeval", -1) + 0.5); - maxtime = struct_val_default(prhs[6], "maxtime", -1); - d.verbose = (int) struct_val_default(prhs[6], "verbose", 0); + x0 = mxGetPr(prhs[7]); + + /* stopping criteria = prhs[8] */ + CHECK(mxIsStruct(prhs[8]), "stopping criteria must be a struct"); + minf_max = struct_val_default(prhs[8], "minf_max", -HUGE_VAL); + ftol_rel = struct_val_default(prhs[8], "ftol_rel", 0); + ftol_abs = struct_val_default(prhs[8], "ftol_abs", 0); + xtol_rel = struct_val_default(prhs[8], "xtol_rel", 0); + maxeval = (int) (struct_val_default(prhs[8], "maxeval", -1) + 0.5); + maxtime = struct_val_default(prhs[8], "maxtime", -1); + d.verbose = (int) struct_val_default(prhs[8], "verbose", 0); d.neval = 0; + for (i = 0; i < m; ++i) { + dc[i].verbose = d.verbose > 1; + dc[i].neval = 0; + } { - mxArray *val = mxGetField(prhs[6], 0, "xtol_abs"); + mxArray *val = mxGetField(prhs[8], 0, "xtol_abs"); if (val) { CHECK(mxIsNumeric(val) && !mxIsComplex(val) && (mxGetM(val) == 1 || mxGetN(val) == 1) @@ -185,23 +226,26 @@ void mexFunction(int nlhs, mxArray *plhs[], memcpy(x, x0, sizeof(double) * n); d.prhs[d.xrhs] = mxCreateDoubleMatrix(1, n, mxREAL); + for (i = 0; i < m;++i) + dc[i].prhs[dc[i].xrhs] = d.prhs[d.xrhs]; - ret = nlopt_minimize(algorithm, - n, - user_function, &d, - lb, ub, x, &minf, - minf_max, ftol_rel, ftol_abs, xtol_rel, xtol_abs, - maxeval, maxtime); + ret = nlopt_minimize_constrained(algorithm, + n, + user_function, &d, + m, user_function, dc, + sizeof(user_function_data), + lb, ub, x, &minf, minf_max, + ftol_rel, ftol_abs, xtol_rel, xtol_abs, + maxeval, maxtime); mxDestroyArray(d.prhs[d.xrhs]); + free(dc); plhs[0] = x_mx; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[1])) = minf; } - else - mxDestroyArray(d.plhs[0]); if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[2])) = (int) ret; diff --git a/octave/nlopt_minimize-oct.cc b/octave/nlopt_minimize_constrained-oct.cc similarity index 70% rename from octave/nlopt_minimize-oct.cc rename to octave/nlopt_minimize_constrained-oct.cc index 953f958..ba75c7a 100644 --- a/octave/nlopt_minimize-oct.cc +++ b/octave/nlopt_minimize_constrained-oct.cc @@ -27,7 +27,7 @@ #include #include "nlopt.h" -#include "nlopt_minimize_usage.h" +#include "nlopt_minimize_constrained_usage.h" static double struct_val_default(Octave_map &m, const std::string& k, double dflt) @@ -73,11 +73,11 @@ static double user_function(int n, const double *x, args(1 + i) = data->f_data(i); octave_value_list res = data->f->do_multi_index_op(gradient ? 2 : 1, args); if (res.length() < (gradient ? 2 : 1)) - gripe_user_supplied_eval("nlopt_minimize"); + gripe_user_supplied_eval("nlopt_minimize_constrained"); else if (!res(0).is_real_scalar() || (gradient && !res(1).is_real_matrix() && !(n == 1 && res(1).is_real_scalar()))) - gripe_user_returned_invalid("nlopt_minimize"); + gripe_user_returned_invalid("nlopt_minimize_constrained"); else { if (gradient) { if (n == 1 && res(1).is_real_scalar()) @@ -89,52 +89,69 @@ static double user_function(int n, const double *x, } } data->neval++; - if (data->verbose) printf("nlopt_minimize eval #%d: %g\n", + if (data->verbose) printf("nlopt_minimize_constrained eval #%d: %g\n", data->neval, res(0).double_value()); return res(0).double_value(); } return 0; } -#define CHECK(cond, msg) if (!(cond)) { fprintf(stderr, msg "\n\n"); print_usage("nlopt_minimize"); return retval; } +#define CHECK(cond, msg) if (!(cond)) { fprintf(stderr, msg "\n\n"); print_usage("nlopt_minimize_constrained"); return retval; } -DEFUN_DLD(nlopt_minimize, args, nargout, NLOPT_MINIMIZE_USAGE) +DEFUN_DLD(nlopt_minimize_constrained, args, nargout, NLOPT_MINIMIZE_CONSTRAINED_USAGE) { octave_value_list retval; double A; - CHECK(args.length() == 7 && nargout <= 3, "wrong number of args"); + CHECK(args.length() == 9 && nargout <= 3, "wrong number of args"); CHECK(args(0).is_real_scalar(), "n must be real scalar"); nlopt_algorithm algorithm = nlopt_algorithm(args(0).int_value()); user_function_data d; CHECK(args(1).is_function() || args(1).is_function_handle(), - "f must be function"); + "f must be a function handle"); d.f = args(1).function_value(); CHECK(args(2).is_cell(), "f_data must be cell array"); d.f_data = args(2).cell_value(); - CHECK(args(3).is_real_matrix() || args(3).is_real_scalar(), + CHECK(args(3).is_cell(), "fc must be cell array"); + CHECK(args(4).is_cell(), "fc_data must be cell array"); + int m = args(3).length(); + CHECK(m == args(4).length(), "fc and fc_data must have the same length"); + user_function_data *dc = new user_function_data[m]; + { + Cell fc = args(3).cell_value(); + Cell fc_data = args(4).cell_value(); + for (int i; i < m; ++i) { + CHECK(fc(i).is_function() || fc(i).is_function_handle(), + "fc must be a cell array of function handles"); + dc[i].f = fc(i).function_value(); + CHECK(fc_data(i).is_cell(), "fc_data must be cell array of cell arrays"); + dc[i].f_data = fc_data(i).cell_value(); + } + } + + CHECK(args(5).is_real_matrix() || args(5).is_real_scalar(), "lb must be real vector"); - Matrix lb = args(3).is_real_scalar() ? - Matrix(1, 1, args(3).double_value()) : args(3).matrix_value(); + Matrix lb = args(5).is_real_scalar() ? + Matrix(1, 1, args(5).double_value()) : args(5).matrix_value(); int n = lb.length(); - CHECK(args(4).is_real_matrix() || args(4).is_real_scalar(), + CHECK(args(6).is_real_matrix() || args(6).is_real_scalar(), "ub must be real vector"); - Matrix ub = args(4).is_real_scalar() ? - Matrix(1, 1, args(4).double_value()) : args(4).matrix_value(); + Matrix ub = args(6).is_real_scalar() ? + Matrix(1, 1, args(6).double_value()) : args(6).matrix_value(); CHECK(n == ub.length(), "lb and ub must have same length"); - CHECK(args(5).is_real_matrix() || args(5).is_real_scalar(), + CHECK(args(7).is_real_matrix() || args(7).is_real_scalar(), "x must be real vector"); - Matrix x = args(5).is_real_scalar() ? - Matrix(1, 1, args(5).double_value()) : args(5).matrix_value(); + Matrix x = args(7).is_real_scalar() ? + Matrix(1, 1, args(7).double_value()) : args(7).matrix_value(); CHECK(n == x.length(), "x and lb/ub must have same length"); - CHECK(args(6).is_map(), "stop must be structure"); - Octave_map stop = args(6).map_value(); + CHECK(args(8).is_map(), "stop must be structure"); + Octave_map stop = args(8).map_value(); double minf_max = struct_val_default(stop, "minf_max", -HUGE_VAL); double ftol_rel = struct_val_default(stop, "ftol_rel", 0); double ftol_abs = struct_val_default(stop, "ftol_abs", 0); @@ -146,14 +163,15 @@ DEFUN_DLD(nlopt_minimize, args, nargout, NLOPT_MINIMIZE_USAGE) double maxtime = struct_val_default(stop, "maxtime", -1); double minf = HUGE_VAL; - nlopt_result ret = nlopt_minimize(algorithm, - n, - user_function, &d, - lb.data(), ub.data(), - x.fortran_vec(), &minf, - minf_max, ftol_rel, ftol_abs, - xtol_rel, xtol_abs.data(), - maxeval, maxtime); + nlopt_result ret = nlopt_minimize_constrained(algorithm, + n, user_function, &d, + m, user_function, dc, + sizeof(user_function_data), + lb.data(), ub.data(), + x.fortran_vec(), &minf, + minf_max, ftol_rel, ftol_abs, + xtol_rel, xtol_abs.data(), + maxeval, maxtime); retval(0) = x; if (nargout > 1) @@ -161,5 +179,7 @@ DEFUN_DLD(nlopt_minimize, args, nargout, NLOPT_MINIMIZE_USAGE) if (nargout > 2) retval(2) = int(ret); + delete[] dc; + return retval; } diff --git a/octave/nlopt_minimize_constrained.m b/octave/nlopt_minimize_constrained.m new file mode 100644 index 0000000..271b35d --- /dev/null +++ b/octave/nlopt_minimize_constrained.m @@ -0,0 +1,87 @@ +% Usage: [xopt, fmin, retcode] = nlopt_minimize_constrained +% (algorithm, f, f_data, +% fc, fc_data, lb, ub, +% xinit, stop) +% +% Minimizes a nonlinear multivariable function f(x, f_data{:}), subject +% to nonlinear constraints described by fc and fc_data (see below), where +% x is a row vector, returning the optimal x found (xopt) along with +% the minimum function value (fmin = f(xopt)) and a return code (retcode). +% A variety of local and global optimization algorithms can be used, +% as specified by the algorithm parameter described below. lb and ub +% are row vectors giving the upper and lower bounds on x, xinit is +% a row vector giving the initial guess for x, and stop is a struct +% containing termination conditions (see below). +% +% This function is a front-end for the external routine +% nlopt_minimize_constrained in the free NLopt nonlinear-optimization +% library, which is a wrapper around a number of free/open-source +% optimization subroutines. More details can be found on the NLopt +% web page (ab-initio.mit.edu/nlopt) and also under +% 'man nlopt_minimize_constrained' on Unix. +% +% f should be a handle (@) to a function of the form: +% +% [val, gradient] = f(x, ...) +% +% where x is a row vector, val is the function value f(x), and gradient +% is a row vector giving the gradient of the function with respect to x. +% The gradient is only used for gradient-based optimization algorithms; +% some of the algorithms (below) are derivative-free and only require +% f to return val (its value). f can take additional arguments (...) +% which are passed via the argument f_data: f_data is a cell array +% of the additional arguments to pass to f. (Recall that cell arrays +% are specified by curly brackets { ... }. For example, pass f_data={} +% for functions that require no additional arguments.) +% +% A few of the algorithms (below) support nonlinear constraints, +% in particular NLOPT_LD_MMA and NLOPT_LN_COBYLA. These (if any) +% are specified by fc and fc_data. fc is a cell array of +% function handles, and fc_data is a cell array of cell arrays of the +% corresponding arguments. Both must have the same length m, the +% number of nonlinear constraints. That is, fc{i} is a handle +% to a function of the form: +% +% [val, gradient] = fc(x, ...) +% +% (where the gradient is only used for gradient-based algorithms), +% and the ... arguments are given by fc_data{i}{:}. +% +% If you have no nonlinear constraints, i.e. fc = fc_data = {}, then +% it is equivalent to calling the the nlopt_minimize() function, +% which omits the fc and fc_data arguments. +% +% stop describes the termination criteria, and is a struct with a +% number of optional fields: +% stop.ftol_rel = fractional tolerance on function value +% stop.ftol_abs = absolute tolerance on function value +% stop.xtol_rel = fractional tolerance on x +% stop.xtol_abs = row vector of absolute tolerances on x components +% stop.fmin_max = stop when f < fmin_max is found +% stop.maxeval = maximum number of function evaluations +% stop.maxtime = maximum run time in seconds +% stop.verbose = > 0 indicates verbose output +% Minimization stops when any one of these conditions is met; any +% condition that is omitted from stop will be ignored. WARNING: +% not all algorithms interpret the stopping criteria in exactly the +% same way, and in any case ftol/xtol specify only a crude estimate +% for the accuracy of the minimum function value/x. +% +% The algorithm should be one of the following constants (name and +% interpretation are the same as for the C function). Names with +% _G*_ are global optimization, and names with _L*_ are local +% optimization. Names with _*N_ are derivative-free, while names +% with _*D_ are gradient-based algorithms. Algorithms: +% +% NLOPT_GD_MLSL_LDS, NLOPT_GD_MLSL, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, +% NLOPT_GN_CRS2_LM, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_NOSCAL, +% NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_DIRECT, +% NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_MLSL_LDS, NLOPT_GN_MLSL, +% NLOPT_GN_ORIG_DIRECT_L, NLOPT_GN_ORIG_DIRECT, NLOPT_LD_LBFGS, +% NLOPT_LD_MMA, NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_PRECOND, +% NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_LD_TNEWTON_RESTART, +% NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LN_COBYLA, NLOPT_LN_NELDERMEAD, +% NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NEWUOA, NLOPT_LN_PRAXIS, NLOPT_LN_SBPLX +% +% For more information on individual functions, see their individual +% help pages (e.g. "help NLOPT_LN_SUBPLEX"). -- 2.30.2