void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { unsigned n; double *x, *x0, opt_f; nlopt_result ret; mxArray *x_mx, *mx; user_function_data d, dpre, *dfc = NULL, *dh = NULL; nlopt_opt opt = NULL; CHECK(nrhs == 2 && nlhs <= 3, "wrong number of arguments"); /* options = prhs[0] */ CHECK(mxIsStruct(prhs[0]), "opt must be a struct"); /* x0 = prhs[1] */ CHECK(mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1]) && (mxGetM(prhs[1]) == 1 || mxGetN(prhs[1]) == 1), "x must be real row or column vector"); n = mxGetM(prhs[1]) * mxGetN(prhs[1]), x0 = mxGetPr(prhs[1]); CHECK(opt = make_opt(prhs[0], n), "error initializing nlopt options"); d.neval = 0; d.verbose = (int) struct_val_default(prhs[0], "verbose", 0); d.opt = opt; /* function f = prhs[1] */ mx = struct_funcval(prhs[0], "min_objective"); if (!mx) mx = struct_funcval(prhs[0], "max_objective"); CHECK(mx, "either opt.min_objective or opt.max_objective must exist"); if (mxIsChar(mx)) { CHECK(mxGetString(mx, d.f, FLEN) == 0, "error reading function name string (too long?)"); d.nrhs = 1; d.xrhs = 0; } else { d.prhs[0] = mx; strcpy(d.f, "feval"); d.nrhs = 2; d.xrhs = 1; } d.prhs[d.xrhs] = mxCreateDoubleMatrix(1, n, mxREAL); if ((mx = struct_funcval(prhs[0], "pre"))) { CHECK(mxIsChar(mx) || mxIsFunctionHandle(mx), "pre must contain function handles or function names"); if (mxIsChar(mx)) { CHECK(mxGetString(mx, dpre.f, FLEN) == 0, "error reading function name string (too long?)"); dpre.nrhs = 2; dpre.xrhs = 0; } else { dpre.prhs[0] = mx; strcpy(dpre.f, "feval"); dpre.nrhs = 3; dpre.xrhs = 1; } dpre.verbose = d.verbose > 2; dpre.opt = opt; dpre.neval = 0; dpre.prhs[dpre.xrhs] = d.prhs[d.xrhs]; dpre.prhs[d.xrhs+1] = mxCreateDoubleMatrix(1, n, mxREAL); d.dpre = &dpre; if (struct_funcval(prhs[0], "min_objective")) nlopt_set_precond_min_objective(opt, user_function,user_pre,&d); else nlopt_set_precond_max_objective(opt, user_function,user_pre,&d); } else { dpre.nrhs = 0; if (struct_funcval(prhs[0], "min_objective")) nlopt_set_min_objective(opt, user_function, &d); else nlopt_set_max_objective(opt, user_function, &d); } if ((mx = mxGetField(prhs[0], 0, "fc"))) { int j, m; double *fc_tol; CHECK(mxIsCell(mx), "fc must be a Cell array"); m = mxGetM(mx) * mxGetN(mx);; dfc = (user_function_data *) mxCalloc(m, sizeof(user_function_data)); fc_tol = struct_arrval(prhs[0], "fc_tol", m, NULL); for (j = 0; j < m; ++j) { mxArray *fc = mxGetCell(mx, j); CHECK(mxIsChar(fc) || mxIsFunctionHandle(fc), "fc must contain function handles or function names"); if (mxIsChar(fc)) { CHECK(mxGetString(fc, dfc[j].f, FLEN) == 0, "error reading function name string (too long?)"); dfc[j].nrhs = 1; dfc[j].xrhs = 0; } else { dfc[j].prhs[0] = fc; strcpy(dfc[j].f, "feval"); dfc[j].nrhs = 2; dfc[j].xrhs = 1; } dfc[j].verbose = d.verbose > 1; dfc[j].opt = opt; dfc[j].neval = 0; dfc[j].prhs[dfc[j].xrhs] = d.prhs[d.xrhs]; CHECK(nlopt_add_inequality_constraint(opt, user_function, dfc + j, fc_tol ? fc_tol[j] : 0) > 0, "nlopt error adding inequality constraint"); } } if ((mx = mxGetField(prhs[0], 0, "h"))) { int j, m; double *h_tol; CHECK(mxIsCell(mx), "h must be a Cell array"); m = mxGetM(mx) * mxGetN(mx);; dh = (user_function_data *) mxCalloc(m, sizeof(user_function_data)); h_tol = struct_arrval(prhs[0], "h_tol", m, NULL); for (j = 0; j < m; ++j) { mxArray *h = mxGetCell(mx, j); CHECK(mxIsChar(h) || mxIsFunctionHandle(h), "h must contain function handles or function names"); if (mxIsChar(h)) { CHECK(mxGetString(h, dh[j].f, FLEN) == 0, "error reading function name string (too long?)"); dh[j].nrhs = 1; dh[j].xrhs = 0; } else { dh[j].prhs[0] = h; strcpy(dh[j].f, "feval"); dh[j].nrhs = 2; dh[j].xrhs = 1; } dh[j].verbose = d.verbose > 1; dh[j].opt = opt; dh[j].neval = 0; dh[j].prhs[dh[j].xrhs] = d.prhs[d.xrhs]; CHECK(nlopt_add_equality_constraint(opt, user_function, dh + j, h_tol ? h_tol[j] : 0) > 0, "nlopt error adding equality constraint"); } } x_mx = mxCreateDoubleMatrix(mxGetM(prhs[1]), mxGetN(prhs[1]), mxREAL); x = mxGetPr(x_mx); memcpy(x, x0, sizeof(double) * n); ret = nlopt_optimize(opt, x, &opt_f); mxFree(dh); mxFree(dfc); mxDestroyArray(d.prhs[d.xrhs]); if (dpre.nrhs > 0) mxDestroyArray(dpre.prhs[d.xrhs+1]); nlopt_destroy(opt); plhs[0] = x_mx; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[1])) = opt_f; } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL); *(mxGetPr(plhs[2])) = (int) ret; } }
nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data) { return nlopt_set_precond_min_objective(opt, f, NULL, f_data); }