예제 #1
0
파일: auglag.c 프로젝트: feelpp/nlopt
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;
}
예제 #2
0
파일: isres.c 프로젝트: cran/nloptr
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 */
}