nlopt_result auglag_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, int p, nlopt_constraint *h, const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, nlopt_opt sub_opt, int sub_has_fc) { auglag_data d; nlopt_result ret = NLOPT_SUCCESS; double ICM = HUGE_VAL, minf_penalty = HUGE_VAL, penalty; double *xcur = NULL, fcur; int i, ii, feasible, minf_feasible = 0; unsigned int k; int auglag_iters = 0; int max_constraint_dim; /* magic parameters from Birgin & Martinez */ const double tau = 0.5, gam = 10; const double lam_min = -1e20, lam_max = 1e20, mu_max = 1e20; d.f = f; d.f_data = f_data; d.m = m; d.fc = fc; d.p = p; d.h = h; d.stop = stop; /* whether we handle inequality constraints via the augmented Lagrangian penalty function, or directly in the sub-algorithm */ if (sub_has_fc) d.m = 0; else m = 0; max_constraint_dim = MAX(nlopt_max_constraint_dim(d.m, fc), nlopt_max_constraint_dim(d.p, h)); d.mm = nlopt_count_constraints(d.m, fc); d.pp = nlopt_count_constraints(d.p, h); ret = nlopt_set_min_objective(sub_opt, auglag, &d); if (ret<0) return ret; ret = nlopt_set_lower_bounds(sub_opt, lb); if (ret<0) return ret; ret = nlopt_set_upper_bounds(sub_opt, ub); if (ret<0) return ret; ret = nlopt_set_stopval(sub_opt, d.m==0 && d.p==0 ? stop->minf_max : -HUGE_VAL); if (ret<0) return ret; ret = nlopt_remove_inequality_constraints(sub_opt); if (ret<0) return ret; ret = nlopt_remove_equality_constraints(sub_opt); if (ret<0) return ret; for (i = 0; i < m; ++i) { if (fc[i].f) ret = nlopt_add_inequality_constraint(sub_opt, fc[i].f, fc[i].f_data, fc[i].tol[0]); else ret = nlopt_add_inequality_mconstraint(sub_opt, fc[i].m, fc[i].mf, fc[i].f_data, fc[i].tol); if (ret < 0) return ret; } xcur = (double *) malloc(sizeof(double) * (n + max_constraint_dim * (1 + n) + d.pp + d.mm)); if (!xcur) return NLOPT_OUT_OF_MEMORY; memcpy(xcur, x, sizeof(double) * n); d.restmp = xcur + n; d.gradtmp = d.restmp + max_constraint_dim; memset(d.gradtmp, 0, sizeof(double) * (n*max_constraint_dim + d.pp+d.mm)); d.lambda = d.gradtmp + n * max_constraint_dim; d.mu = d.lambda + d.pp; *minf = HUGE_VAL; /* starting rho suggested by B & M */ if (d.p > 0 || d.m > 0) { double con2 = 0; ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } penalty = 0; feasible = 1; for (i = 0; i < d.p; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.h + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.h[i].m; ++k) { double hi = d.restmp[k]; penalty += fabs(hi); feasible = feasible && fabs(hi) <= h[i].tol[k]; con2 += hi * hi; } } for (i = 0; i < d.m; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.fc + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.fc[i].m; ++k) { double fci = d.restmp[k]; penalty += fci > 0 ? fci : 0; feasible = feasible && fci <= fc[i].tol[k]; if (fci > 0) con2 += fci * fci; } } *minf = fcur; minf_penalty = penalty; minf_feasible = feasible; d.rho = MAX(1e-6, MIN(10, 2 * fabs(*minf) / con2)); } else d.rho = 1; /* whatever, doesn't matter */ if (auglag_verbose) { printf("auglag: initial rho=%g\nauglag initial lambda=", d.rho); for (i = 0; i < d.pp; ++i) printf(" %g", d.lambda[i]); printf("\nauglag initial mu = "); for (i = 0; i < d.mm; ++i) printf(" %g", d.mu[i]); printf("\n"); } do { double prev_ICM = ICM; ret = nlopt_optimize_limited(sub_opt, xcur, &fcur, stop->maxeval - *(stop->nevals_p), stop->maxtime - (nlopt_seconds() - stop->start)); if (auglag_verbose) printf("auglag: subopt return code %d\n", ret); if (ret < 0) break; ++ *(d.stop->nevals_p); fcur = f(n, xcur, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } if (auglag_verbose) printf("auglag: fcur = %g\n", fcur); ICM = 0; penalty = 0; feasible = 1; for (i = ii = 0; i < d.p; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.h + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.h[i].m; ++k) { double hi = d.restmp[k]; double newlam = d.lambda[ii] + d.rho * hi; penalty += fabs(hi); feasible = feasible && fabs(hi) <= h[i].tol[k]; ICM = MAX(ICM, fabs(hi)); d.lambda[ii++] = MIN(MAX(lam_min, newlam), lam_max); } } for (i = ii = 0; i < d.m; ++i) { nlopt_eval_constraint(d.restmp, NULL, d.fc + i, n, xcur); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (k = 0; k < d.fc[i].m; ++k) { double fci = d.restmp[k]; double newmu = d.mu[ii] + d.rho * fci; penalty += fci > 0 ? fci : 0; feasible = feasible && fci <= fc[i].tol[k]; ICM = MAX(ICM, fabs(MAX(fci, -d.mu[ii] / d.rho))); d.mu[ii++] = MIN(MAX(0.0, newmu), mu_max); } } if (ICM > tau * prev_ICM) { d.rho *= gam; } auglag_iters++; if (auglag_verbose) { printf("auglag %d: ICM=%g (%sfeasible), rho=%g\nauglag lambda=", auglag_iters, ICM, feasible ? "" : "not ", d.rho); for (i = 0; i < d.pp; ++i) printf(" %g", d.lambda[i]); printf("\nauglag %d: mu = ", auglag_iters); for (i = 0; i < d.mm; ++i) printf(" %g", d.mu[i]); printf("\n"); } if ((feasible && (!minf_feasible || penalty < minf_penalty || fcur < *minf)) || (!minf_feasible && penalty < minf_penalty)) { ret = NLOPT_SUCCESS; if (feasible) { if (fcur < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED; else if (nlopt_stop_ftol(stop, fcur, *minf)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xcur, x)) ret = NLOPT_XTOL_REACHED; } *minf = fcur; minf_penalty = penalty; minf_feasible = feasible; memcpy(x, xcur, sizeof(double) * n); if (ret != NLOPT_SUCCESS) break; } if (nlopt_stop_forced(stop)) {ret = NLOPT_FORCED_STOP; break;} if (nlopt_stop_evals(stop)) {ret = NLOPT_MAXEVAL_REACHED; break;} if (nlopt_stop_time(stop)) {ret = NLOPT_MAXTIME_REACHED; break;} /* TODO: use some other stopping criterion on ICM? */ /* The paper uses ICM <= epsilon and DFM <= epsilon, where DFM is a measure of the size of the Lagrangian gradient. Besides the fact that these kinds of absolute tolerances (non-scale-invariant) are unsatisfying and it is not clear how the user should specify it, the ICM <= epsilon condition seems not too different from requiring feasibility, especially now that the user can provide constraint-specific tolerances analogous to epsilon. */ if (ICM == 0) {ret = NLOPT_FTOL_REACHED; break;} } while (1); done: free(xcur); return ret; }
nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, int m, nlopt_constraint *fc, /* fc <= 0 */ int p, nlopt_constraint *h, /* h == 0 */ const double *lb, const double *ub, /* bounds */ double *x, /* in: initial guess, out: minimizer */ double *minf, nlopt_stopping *stop, int population) /* pop. size (= 0 for default) */ { const double ALPHA = 0.2; /* smoothing factor from paper */ const double GAMMA = 0.85; /* step-reduction factor from paper */ const double PHI = 1.0; /* expected rate of convergence, from paper */ const double PF = 0.45; /* fitness probability, from paper */ const double SURVIVOR = 1.0/7.0; /* survivor fraction, from paper */ int survivors; nlopt_result ret = NLOPT_SUCCESS; double *sigmas = 0, *xs; /* population-by-n arrays (row-major) */ double *fval; /* population array of function vals */ double *penalty; /* population array of penalty vals */ double *x0; int *irank = 0; int k, i, j, c; int mp = m + p; double minf_penalty = HUGE_VAL, minf_gpenalty = HUGE_VAL; double taup, tau; double *results = 0; /* scratch space for mconstraint results */ unsigned ires; *minf = HUGE_VAL; if (!population) population = 20 * (n + 1); if (population < 1) return NLOPT_INVALID_ARGS; survivors = ceil(population * SURVIVOR); taup = PHI / sqrt((double) 2*n); tau = PHI / sqrt((double) 2*sqrt((double) 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; ires = imax2(nlopt_max_constraint_dim(m, fc), nlopt_max_constraint_dim(p, h)); results = (double *) malloc(ires * sizeof(double)); if (ires > 0 && !results) return NLOPT_OUT_OF_MEMORY; sigmas = (double*) malloc(sizeof(double) * (population*n*2 + population + population + n)); if (!sigmas) { free(results); return NLOPT_OUT_OF_MEMORY; } xs = sigmas + population*n; fval = xs + population*n; penalty = fval + population; x0 = penalty + population; irank = (int*) malloc(sizeof(int) * population); if (!irank) { ret = NLOPT_OUT_OF_MEMORY; goto done; } for (k = 0; k < population; ++k) { for (j = 0; j < n; ++j) { sigmas[k*n+j] = (ub[j] - lb[j]) / sqrt((double) n); xs[k*n+j] = nlopt_urand(lb[j], ub[j]); } } memcpy(xs, x, sizeof(double) * n); /* use input x for xs_0 */ while (1) { /* each loop body = one generation */ int all_feasible = 1; /* evaluate f and constraint violations for whole population */ for (k = 0; k < population; ++k) { int feasible = 1; double gpenalty; stop->nevals++; fval[k] = f(n, xs + k*n, NULL, f_data); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } penalty[k] = 0; for (c = 0; c < m; ++c) { /* inequality constraints */ nlopt_eval_constraint(results, NULL, fc + c, n, xs + k*n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (ires = 0; ires < fc[c].m; ++ires) { double gval = results[ires]; if (gval > fc[c].tol[ires]) feasible = 0; if (gval < 0) gval = 0; penalty[k] += gval*gval; } } gpenalty = penalty[k]; for (c = m; c < mp; ++c) { /* equality constraints */ nlopt_eval_constraint(results, NULL, h + (c-m), n, xs + k*n); if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; } for (ires = 0; ires < h[c-m].m; ++ires) { double hval = results[ires]; if (fabs(hval) > h[c-m].tol[ires]) feasible = 0; penalty[k] += hval*hval; } } if (penalty[k] > 0) all_feasible = 0; /* convergence criteria (FIXME: improve?) */ /* FIXME: with equality constraints, how do we decide which solution is the "best" so far? ... need some total order on the solutions? */ if ((penalty[k] <= minf_penalty || feasible) && (fval[k] <= *minf || minf_gpenalty > 0) && ((feasible ? 0 : penalty[k]) != minf_penalty || fval[k] != *minf)) { if (fval[k] < stop->minf_max && feasible) ret = NLOPT_MINF_MAX_REACHED; else if (!nlopt_isinf(*minf)) { if (nlopt_stop_f(stop, fval[k], *minf) && nlopt_stop_f(stop, feasible ? 0 : penalty[k], minf_penalty)) ret = NLOPT_FTOL_REACHED; else if (nlopt_stop_x(stop, xs+k*n, x)) ret = NLOPT_XTOL_REACHED; } memcpy(x, xs+k*n, sizeof(double)*n); *minf = fval[k]; minf_penalty = feasible ? 0 : penalty[k]; minf_gpenalty = feasible ? 0 : gpenalty; if (ret != NLOPT_SUCCESS) goto done; } if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP; else if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; if (ret != NLOPT_SUCCESS) goto done; } /* "selection" step: rank the population */ for (k = 0; k < population; ++k) irank[k] = k; if (all_feasible) /* special case: rank by objective function */ nlopt_qsort_r(irank, population, sizeof(int), fval,key_compare); else { /* Runarsson & Yao's stochastic ranking of the population */ for (i = 0; i < population; ++i) { int swapped = 0; for (j = 0; j < population-1; ++j) { double u = nlopt_urand(0,1); if (u < PF || (penalty[irank[j]] == 0 && penalty[irank[j+1]] == 0)) { if (fval[irank[j]] > fval[irank[j+1]]) { int irankj = irank[j]; irank[j] = irank[j+1]; irank[j+1] = irankj; swapped = 1; } } else if (penalty[irank[j]] > penalty[irank[j+1]]) { int irankj = irank[j]; irank[j] = irank[j+1]; irank[j+1] = irankj; swapped = 1; } } if (!swapped) break; } } /* evolve the population: differential evolution for the best survivors, and standard mutation of the best survivors for the rest: */ for (k = survivors; k < population; ++k) { /* standard mutation */ double taup_rand = taup * nlopt_nrand(0,1); int rk = irank[k], ri; i = k % survivors; ri = irank[i]; for (j = 0; j < n; ++j) { double sigmamax = (ub[j] - lb[j]) / sqrt((double) n); sigmas[rk*n+j] = sigmas[ri*n+j] * exp(taup_rand + tau*nlopt_nrand(0,1)); if (sigmas[rk*n+j] > sigmamax) sigmas[rk*n+j] = sigmamax; do { xs[rk*n+j] = xs[ri*n+j] + sigmas[rk*n+j] * nlopt_nrand(0,1); } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); sigmas[rk*n+j] = sigmas[ri*n+j] + ALPHA*(sigmas[rk*n+j] - sigmas[ri*n+j]); } } memcpy(x0, xs, n * sizeof(double)); for (k = 0; k < survivors; ++k) { /* differential variation */ double taup_rand = taup * nlopt_nrand(0,1); int rk = irank[k]; for (j = 0; j < n; ++j) { double xi = xs[rk*n+j]; if (k+1 < survivors) xs[rk*n+j] += GAMMA * (x0[j] - xs[(k+1)*n+j]); if (k+1 == survivors || xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]) { /* standard mutation for last survivor and for any survivor components that are now outside the bounds */ double sigmamax = (ub[j] - lb[j]) / sqrt((double) n); double sigi = sigmas[rk*n+j]; sigmas[rk*n+j] *= exp(taup_rand + tau*nlopt_nrand(0,1)); if (sigmas[rk*n+j] > sigmamax) sigmas[rk*n+j] = sigmamax; do { xs[rk*n+j] = xi + sigmas[rk*n+j] * nlopt_nrand(0,1); } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); sigmas[rk*n+j] = sigi + ALPHA * (sigmas[rk*n+j] - sigi); } } } } done: if (irank) free(irank); if (sigmas) free(sigmas); if (results) free(results); return ret; }
/* unlike nlopt_optimize() below, only handles minimization case */ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) { const double *lb, *ub; nlopt_algorithm algorithm; nlopt_func f; void *f_data; unsigned n, i; int ni; nlopt_stopping stop; if (!opt || !x || !minf || !opt->f || opt->maximize) return NLOPT_INVALID_ARGS; /* reset stopping flag */ nlopt_set_force_stop(opt, 0); opt->force_stop_child = NULL; /* copy a few params to local vars for convenience */ n = opt->n; ni = (int) n; /* most of the subroutines take "int" arg */ lb = opt->lb; ub = opt->ub; algorithm = opt->algorithm; f = opt->f; f_data = opt->f_data; if (n == 0) { /* trivial case: no degrees of freedom */ *minf = opt->f(n, x, NULL, opt->f_data); return NLOPT_SUCCESS; } *minf = HUGE_VAL; /* make sure rand generator is inited */ nlopt_srand_time_default(); /* default is non-deterministic */ /* 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; stop.n = n; stop.minf_max = opt->stopval; stop.ftol_rel = opt->ftol_rel; stop.ftol_abs = opt->ftol_abs; stop.xtol_rel = opt->xtol_rel; stop.xtol_abs = opt->xtol_abs; stop.nevals = 0; stop.maxeval = opt->maxeval; stop.maxtime = opt->maxtime; stop.start = nlopt_seconds(); stop.force_stop = &(opt->force_stop); 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; return cdirect(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); 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; return cdirect_unscaled(ni, f, f_data, lb, ub, x, minf, &stop, 0.0, (algorithm != NLOPT_GN_DIRECT) + 3 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 2 : (algorithm != NLOPT_GN_DIRECT)) + 9 * (algorithm == NLOPT_GN_DIRECT_L_RAND ? 1 : (algorithm != NLOPT_GN_DIRECT))); 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; opt->work = malloc(sizeof(double) * nlopt_max_constraint_dim(opt->m, opt->fc)); if (!opt->work) return NLOPT_OUT_OF_MEMORY; dret = direct_optimize(f_direct, opt, ni, lb, ub, x, minf, stop.maxeval, -1, stop.start, stop.maxtime, 0.0, 0.0, pow(stop.xtol_rel, (double) n), -1.0, stop.force_stop, stop.minf_max, 0.0, NULL, algorithm == NLOPT_GN_ORIG_DIRECT ? DIRECT_ORIGINAL : DIRECT_GABLONSKY); free(opt->work); opt->work = NULL; switch (dret) { case DIRECT_INVALID_BOUNDS: case DIRECT_MAXFEVAL_TOOBIG: case DIRECT_INVALID_ARGS: return NLOPT_INVALID_ARGS; case DIRECT_INIT_FAILED: case DIRECT_SAMPLEPOINTS_FAILED: case DIRECT_SAMPLE_FAILED: return NLOPT_FAILURE; case DIRECT_MAXFEVAL_EXCEEDED: case DIRECT_MAXITER_EXCEEDED: return NLOPT_MAXEVAL_REACHED; case DIRECT_MAXTIME_EXCEEDED: return NLOPT_MAXTIME_REACHED; case DIRECT_GLOBAL_FOUND: return NLOPT_MINF_MAX_REACHED; case DIRECT_VOLTOL: case DIRECT_SIGMATOL: return NLOPT_XTOL_REACHED; case DIRECT_OUT_OF_MEMORY: return NLOPT_OUT_OF_MEMORY; case DIRECT_FORCED_STOP: return NLOPT_FORCED_STOP; } break; } case NLOPT_GD_STOGO: case NLOPT_GD_STOGO_RAND: #ifdef WITH_CXX if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS; if (!stogo_minimize(ni, f, f_data, x, minf, lb, ub, &stop, algorithm == NLOPT_GD_STOGO ? 0 : (int) POP(2*n))) return NLOPT_FAILURE; break; #else return NLOPT_INVALID_ARGS; #endif #if 0 /* lacking a free/open-source license, we no longer use Rowan's code, and instead use by "sbplx" re-implementation */ case NLOPT_LN_SUBPLEX: { int iret, freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } iret = nlopt_subplex(f_bound, minf, x, n, opt, &stop, opt->dx); if (freedx) { free(opt->dx); opt->dx = NULL; } switch (iret) { case -2: return NLOPT_INVALID_ARGS; case -20: return NLOPT_FORCED_STOP; case -10: return NLOPT_MAXTIME_REACHED; case -1: return NLOPT_MAXEVAL_REACHED; case 0: return NLOPT_XTOL_REACHED; case 1: return NLOPT_SUCCESS; case 2: return NLOPT_MINF_MAX_REACHED; case 20: return NLOPT_FTOL_REACHED; case -200: return NLOPT_OUT_OF_MEMORY; default: return NLOPT_FAILURE; /* unknown return code */ } break; } #endif case NLOPT_LN_PRAXIS: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; return praxis_(0.0, DBL_EPSILON, step, ni, x, f_bound, opt, &stop, minf); } case NLOPT_LD_LBFGS: return luksan_plis(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage); case NLOPT_LD_VAR1: case NLOPT_LD_VAR2: return luksan_plip(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, algorithm == NLOPT_LD_VAR1 ? 1 : 2); case NLOPT_LD_TNEWTON: case NLOPT_LD_TNEWTON_RESTART: case NLOPT_LD_TNEWTON_PRECOND: case NLOPT_LD_TNEWTON_PRECOND_RESTART: return luksan_pnet(ni, f, f_data, lb, ub, x, minf, &stop, opt->vector_storage, 1 + (algorithm - NLOPT_LD_TNEWTON) % 2, 1 + (algorithm - NLOPT_LD_TNEWTON) / 2); case NLOPT_GN_CRS2_LM: if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS; return crs_minimize(ni, f, f_data, lb, ub, x, minf, &stop, (int) POP(0), 0); case NLOPT_G_MLSL: case NLOPT_G_MLSL_LDS: case NLOPT_GN_MLSL: case NLOPT_GD_MLSL: case NLOPT_GN_MLSL_LDS: 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 (!local_opt && (algorithm == NLOPT_G_MLSL || algorithm == NLOPT_G_MLSL_LDS)) return NLOPT_INVALID_ARGS; if (!local_opt) { /* default */ nlopt_algorithm local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) ? nlopt_local_search_alg_nonderiv : nlopt_local_search_alg_deriv; /* don't call MLSL recursively! */ if (local_alg >= NLOPT_GN_MLSL && local_alg <= NLOPT_GD_MLSL_LDS) local_alg = (algorithm == NLOPT_GN_MLSL || algorithm == NLOPT_GN_MLSL_LDS) ? NLOPT_LN_COBYLA : NLOPT_LD_MMA; local_opt = nlopt_create(local_alg, n); if (!local_opt) return NLOPT_FAILURE; 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); nlopt_set_xtol_abs(local_opt, opt->xtol_abs); nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); } if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); for (i = 0; i < n && stop.xtol_abs[i] > 0; ++i) ; if (local_opt->ftol_rel <= 0 && local_opt->ftol_abs <= 0 && local_opt->xtol_rel <= 0 && i < n) { /* it is not sensible to call MLSL without *some* nonzero tolerance for the local search */ nlopt_set_ftol_rel(local_opt, 1e-15); nlopt_set_xtol_rel(local_opt, 1e-7); } opt->force_stop_child = local_opt; ret = mlsl_minimize(ni, f, f_data, lb, ub, x, minf, &stop, local_opt, (int) POP(0), algorithm >= NLOPT_GN_MLSL_LDS && algorithm != NLOPT_G_MLSL); opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } case NLOPT_LD_MMA: case NLOPT_LD_CCSAQ: { nlopt_opt dual_opt; nlopt_result ret; #define LO(param, def) (opt->local_opt ? opt->local_opt->param : (def)) dual_opt = nlopt_create(LO(algorithm, nlopt_local_search_alg_deriv), nlopt_count_constraints(opt->m, opt->fc)); if (!dual_opt) return NLOPT_FAILURE; 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)); #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); else ret = ccsa_quadratic_minimize( n, f, f_data, opt->m, opt->fc, opt->pre, lb, ub, x, minf, &stop, dual_opt); nlopt_destroy(dual_opt); return ret; } case NLOPT_LN_COBYLA: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } return cobyla_minimize(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop, opt->dx); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_LN_NEWUOA: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; return newuoa(ni, 2*n+1, x, 0, 0, step, &stop, minf, f_noderiv, opt); } case NLOPT_LN_NEWUOA_BOUND: { double step; if (initial_step(opt, x, &step) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; return newuoa(ni, 2*n+1, x, lb, ub, step, &stop, minf, f_noderiv, opt); } case NLOPT_LN_BOBYQA: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } ret = bobyqa(ni, 2*n+1, x, lb, ub, opt->dx, &stop, minf, opt->f, opt->f_data); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_LN_NELDERMEAD: case NLOPT_LN_SBPLX: { nlopt_result ret; int freedx = 0; if (!opt->dx) { freedx = 1; if (nlopt_set_default_initial_step(opt, x) != NLOPT_SUCCESS) return NLOPT_OUT_OF_MEMORY; } if (algorithm == NLOPT_LN_NELDERMEAD) 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); if (freedx) { free(opt->dx); opt->dx = NULL; } return ret; } case NLOPT_AUGLAG: case NLOPT_AUGLAG_EQ: case NLOPT_LN_AUGLAG: case NLOPT_LN_AUGLAG_EQ: case NLOPT_LD_AUGLAG: case NLOPT_LD_AUGLAG_EQ: { nlopt_opt local_opt = opt->local_opt; nlopt_result ret; if ((algorithm == NLOPT_AUGLAG || algorithm == NLOPT_AUGLAG_EQ) && !local_opt) return NLOPT_INVALID_ARGS; 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; 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); nlopt_set_xtol_abs(local_opt, opt->xtol_abs); nlopt_set_maxeval(local_opt, nlopt_local_search_maxeval); } if (opt->dx) nlopt_set_initial_step(local_opt, opt->dx); opt->force_stop_child = local_opt; ret = auglag_minimize(ni, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop, local_opt, algorithm == NLOPT_AUGLAG_EQ || algorithm == NLOPT_LN_AUGLAG_EQ || algorithm == NLOPT_LD_AUGLAG_EQ); opt->force_stop_child = NULL; if (!opt->local_opt) nlopt_destroy(local_opt); return ret; } case NLOPT_GN_ISRES: if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS; return isres_minimize(ni, f, f_data, (int) (opt->m), opt->fc, (int) (opt->p), opt->h, lb, ub, x, minf, &stop, (int) POP(0)); // case NLOPT_GN_ESCH: // if (!finite_domain(n, lb, ub)) return NLOPT_INVALID_ARGS; // return chevolutionarystrategy(n, f, f_data, // lb, ub, x, minf, &stop, // (unsigned) POP(0), // (unsigned) (POP(0)*1.5)); case NLOPT_LD_SLSQP: return nlopt_slsqp(n, f, f_data, opt->m, opt->fc, opt->p, opt->h, lb, ub, x, minf, &stop); default: return NLOPT_INVALID_ARGS; } return NLOPT_SUCCESS; /* never reached */ }