Esempio n. 1
0
static nlopt_result crs_trial(crs_data *d)
{
     rb_node *best = rb_tree_min(&d->t);
     rb_node *worst = rb_tree_max(&d->t);
     int mutation = NUM_MUTATION;
     int i, n = d->n;
     random_trial(d, d->p + 1, best);
     do {
     	  d->p[0] = d->f(n, d->p + 1, NULL, d->f_data);
	  d->stop->nevals++;
	  if (nlopt_stop_forced(d->stop)) return NLOPT_FORCED_STOP;
	  if (d->p[0] < worst->k[0]) break;
	  if (nlopt_stop_evals(d->stop)) return NLOPT_MAXEVAL_REACHED;
	  if (nlopt_stop_time(d->stop)) return NLOPT_MAXTIME_REACHED;
	  if (mutation) {
	       for (i = 0; i < n; ++i) {
		    double w = nlopt_urand(0.,1.);
		    d->p[1+i] = best->k[1+i] * (1 + w) - w * d->p[1+i];
		    if (d->p[1+i] > d->ub[i]) d->p[1+i] = d->ub[i];
		    else if (d->p[1+i] < d->lb[i]) d->p[1+i] = d->lb[i];
	       }
	       mutation--;
	  }
	  else {
	       random_trial(d, d->p + 1, best);
	       mutation = NUM_MUTATION;
	  }
     } while (1);
     memcpy(worst->k, d->p, sizeof(double) * (n+1));
     rb_tree_resort(&d->t, worst);
     return NLOPT_SUCCESS;
}
Esempio n. 2
0
nlopt_result nldrmd_minimize(int n, nlopt_func f, void *f_data,
			     const double *lb, const double *ub, /* bounds */
			     double *x, /* in: initial guess, out: minimizer */
			     double *minf,
			     const double *xstep, /* initial step sizes */
			     nlopt_stopping *stop)
{
     nlopt_result ret;
     double *scratch, fdiff;

     *minf = f(n, x, NULL, f_data);
     stop->nevals++;
     if (nlopt_stop_forced(stop)) return NLOPT_FORCED_STOP;
     if (*minf < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
     if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
     if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;

     scratch = (double*) malloc(sizeof(double) * ((n+1)*(n+1) + 2*n));
     if (!scratch) return NLOPT_OUT_OF_MEMORY;

     ret = nldrmd_minimize_(n, f, f_data, lb, ub, x, minf, xstep, stop,
			    0.0, scratch, &fdiff);
     free(scratch);
     return ret;
}
Esempio n. 3
0
nlopt_result crs_minimize(int n, nlopt_func f, void *f_data,
			  const double *lb, const double *ub, /* bounds */
			  double *x, /* in: initial guess, out: minimizer */
			  double *minf,
			  nlopt_stopping *stop,
			  int population, /* initial population (0=default) */
			  int lds) /* random or low-discrepancy seq. (lds) */
{
     nlopt_result ret;
     crs_data d;
     rb_node *best;

     ret = crs_init(&d, n, x, lb, ub, stop, f, f_data, population, lds);
     if (ret < 0) return ret;
     
     best = rb_tree_min(&d.t);
     *minf = best->k[0];
     memcpy(x, best->k + 1, sizeof(double) * n);

     while (ret == NLOPT_SUCCESS) {
	  if (NLOPT_SUCCESS == (ret = crs_trial(&d))) {
	       best = rb_tree_min(&d.t);
	       if (best->k[0] < *minf) {
		    if (best->k[0] < stop->minf_max)
			 ret = NLOPT_MINF_MAX_REACHED;
		    else if (nlopt_stop_f(stop, best->k[0], *minf))
			 ret = NLOPT_FTOL_REACHED;
		    else if (nlopt_stop_x(stop, best->k + 1, x))
			 ret = NLOPT_XTOL_REACHED;
		    *minf = best->k[0];
		    memcpy(x, best->k + 1, sizeof(double) * n);
	       }
	       if (ret != NLOPT_SUCCESS) {
		    if (nlopt_stop_evals(stop)) 
			 ret = NLOPT_MAXEVAL_REACHED;
		    else if (nlopt_stop_time(stop)) 
			 ret = NLOPT_MAXTIME_REACHED;
	       }
	  }
     }
     crs_destroy(&d);
     return ret;
}
Esempio n. 4
0
static nlopt_result crs_init(crs_data *d, int n, const double *x,
			     const double *lb, const double *ub,
			     nlopt_stopping *stop, nlopt_func f, void *f_data,
			     int population, int lds)
{
     int i;

     if (!population) {
	  /* TODO: how should we set the default population size? 
	     the Kaelo and Ali paper suggests 10*(n+1), but should
	     we add more random points if maxeval is large, or... ? */
	  d->N = 10 * (n + 1); /* heuristic initial population size */
     }
     else
	  d->N = population;
     if (d->N < n + 1) /* population must be big enough for a simplex */
	  return NLOPT_INVALID_ARGS;

     d->n = n;
     d->stop = stop;
     d->f = f; d->f_data = f_data;
     d->ub = ub; d->lb = lb;
     d->ps = (double *) malloc(sizeof(double) * (n + 1) * (d->N + 1));
     if (!d->ps) return NLOPT_OUT_OF_MEMORY;
     d->p = d->ps + d->N * (n+1);
     rb_tree_init(&d->t, crs_compare);

     /* we can either use pseudorandom points, as in the original CRS
	algorithm, or use a low-discrepancy Sobol' sequence ... I tried
	the latter, however, and it doesn't seem to help, probably
	because we are only generating a small number of random points
	to start with */
     d->s = lds ? nlopt_sobol_create((unsigned) n) : NULL;
     nlopt_sobol_skip(d->s, (unsigned) d->N, d->ps + 1);

     /* generate initial points randomly, plus starting guess x */
     memcpy(d->ps + 1, x, sizeof(double) * n);
     d->ps[0] = f(n, x, NULL, f_data);
     stop->nevals++;
     if (!rb_tree_insert(&d->t, d->ps)) return NLOPT_OUT_OF_MEMORY;
     if (d->ps[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
     if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
     if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
     for (i = 1; i < d->N; ++i) {
	  double *k = d->ps + i*(n+1);
	  if (d->s) 
	       nlopt_sobol_next(d->s, k + 1, lb, ub);
	  else {
	       int j;
	       for (j = 0; j < n; ++j) 
		    k[1 + j] = nlopt_urand(lb[j], ub[j]);
	  }
	  k[0] = f(n, k + 1, NULL, f_data);
	  stop->nevals++;
	  if (!rb_tree_insert(&d->t, k)) return NLOPT_OUT_OF_MEMORY;
	  if (k[0] < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
	  if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
	  if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;	  
     }

     return NLOPT_SUCCESS;;
}
Esempio n. 5
0
nlopt_result mma_minimize(unsigned n, nlopt_func f, void *f_data,
			  unsigned m, nlopt_constraint *fc,
			  const double *lb, const double *ub, /* bounds */
			  double *x, /* in: initial guess, out: minimizer */
			  double *minf,
			  nlopt_stopping *stop,
			  nlopt_opt dual_opt)
{
     nlopt_result ret = NLOPT_SUCCESS;
     double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur;
     double *dfcdx, *dfcdx_cur;
     double *fcval, *fcval_cur, *rhoc, *gcval, *y, *dual_lb, *dual_ub;
     unsigned i, ifc, j, k = 0;
     dual_data dd;
     int feasible;
     double infeasibility;
     unsigned mfc;

     m = nlopt_count_constraints(mfc = m, fc);
     if (nlopt_get_dimension(dual_opt) != m) return NLOPT_INVALID_ARGS;
     sigma = (double *) malloc(sizeof(double) * (6*n + 2*m*n + m*7));
     if (!sigma) return NLOPT_OUT_OF_MEMORY;
     dfdx = sigma + n;
     dfdx_cur = dfdx + n;
     xcur = dfdx_cur + n;
     xprev = xcur + n;
     xprevprev = xprev + n;
     fcval = xprevprev + n;
     fcval_cur = fcval + m;
     rhoc = fcval_cur + m;
     gcval = rhoc + m;
     dual_lb = gcval + m;
     dual_ub = dual_lb + m;
     y = dual_ub + m;
     dfcdx = y + m;
     dfcdx_cur = dfcdx + m*n;

     dd.n = n;
     dd.x = x;
     dd.lb = lb;
     dd.ub = ub;
     dd.sigma = sigma;
     dd.dfdx = dfdx;
     dd.dfcdx = dfcdx;
     dd.fcval = fcval;
     dd.rhoc = rhoc;
     dd.xcur = xcur;
     dd.gcval = gcval;

     for (j = 0; j < n; ++j) {
	  if (nlopt_isinf(ub[j]) || nlopt_isinf(lb[j]))
	       sigma[j] = 1.0; /* arbitrary default */
	  else
	       sigma[j] = 0.5 * (ub[j] - lb[j]);
     }
     rho = 1.0;
     for (i = 0; i < m; ++i) {
	  rhoc[i] = 1.0;
	  dual_lb[i] = y[i] = 0.0;
	  dual_ub[i] = HUGE_VAL;
     }

     dd.fval = fcur = *minf = f(n, x, dfdx, f_data);
     stop->nevals++;
     memcpy(xcur, x, sizeof(double) * n);
     if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; }

     feasible = 1; infeasibility = 0;
     for (i = ifc = 0; ifc < mfc; ++ifc) {
	  nlopt_eval_constraint(fcval + i, dfcdx + i*n,
				fc + ifc, n, x);
	  i += fc[ifc].m;
	  if (nlopt_stop_forced(stop)) { ret = NLOPT_FORCED_STOP; goto done; }
     }
     for (i = 0; i < m; ++i) {
	  feasible = feasible && (fcval[i] <= 0 || isnan(fcval[i]));
	  if (fcval[i] > infeasibility) infeasibility = fcval[i];
     }
     /* For non-feasible initial points, set a finite (large)
	upper-bound on the dual variables.  What this means is that,
	if no feasible solution is found from the dual problem, it
	will minimize the dual objective with the unfeasible
	constraint weighted by 1e40 -- basically, minimizing the
	unfeasible constraint until it becomes feasible or until we at
	least obtain a step towards a feasible point.
	
	Svanberg suggested a different approach in his 1987 paper, basically
	introducing additional penalty variables for unfeasible constraints,
	but this is easier to implement and at least as efficient. */
     if (!feasible)
	  for (i = 0; i < m; ++i) dual_ub[i] = 1e40;

     nlopt_set_min_objective(dual_opt, dual_func, &dd);
     nlopt_set_lower_bounds(dual_opt, dual_lb);
     nlopt_set_upper_bounds(dual_opt, dual_ub);
     nlopt_set_stopval(dual_opt, -HUGE_VAL);
     nlopt_remove_inequality_constraints(dual_opt);
     nlopt_remove_equality_constraints(dual_opt);

     while (1) { /* outer iterations */
	  double fprev = fcur;
	  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;
	  else if (feasible && *minf < stop->minf_max) 
	       ret = NLOPT_MINF_MAX_REACHED;
	  if (ret != NLOPT_SUCCESS) goto done;
	  if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n);
	  memcpy(xprev, xcur, sizeof(double) * n);

	  while (1) { /* inner iterations */
	       double min_dual, infeasibility_cur;
	       int feasible_cur, inner_done;
	       unsigned save_verbose;
	       int new_infeasible_constraint;
	       nlopt_result reti;

	       /* solve dual problem */
	       dd.rho = rho; dd.count = 0;
	       save_verbose = mma_verbose;
	       mma_verbose = 0; /* no recursive verbosity */
	       reti = nlopt_optimize_limited(dual_opt, y, &min_dual,
					     0,
					     stop->maxtime - (nlopt_seconds() 
							      - stop->start));
	       mma_verbose = save_verbose;
	       if (reti < 0 || reti == NLOPT_MAXTIME_REACHED) {
		    ret = reti;
		    goto done;
	       }

	       dual_func(m, y, NULL, &dd); /* evaluate final xcur etc. */
	       if (mma_verbose) {
		    printf("MMA dual converged in %d iterations to g=%g:\n",
			   dd.count, dd.gval);
		    for (i = 0; i < MIN(mma_verbose, m); ++i)
			 printf("    MMA y[%d]=%g, gc[%d]=%g\n",
				i, y[i], i, dd.gcval[i]);
	       }

	       fcur = f(n, xcur, dfdx_cur, f_data);
	       stop->nevals++;
	       if (nlopt_stop_forced(stop)) { 
		    ret = NLOPT_FORCED_STOP; goto done; }
	       feasible_cur = 1; infeasibility_cur = 0;
	       new_infeasible_constraint = 0;
	       inner_done = dd.gval >= fcur;
	       for (i = ifc = 0; ifc < mfc; ++ifc) {
		    nlopt_eval_constraint(fcval_cur + i, dfcdx_cur + i*n,
					  fc + ifc, n, xcur);
		    i += fc[ifc].m;
		    if (nlopt_stop_forced(stop)) { 
			 ret = NLOPT_FORCED_STOP; goto done; }
	       }
	       for (i = ifc = 0; ifc < mfc; ++ifc) {
		    unsigned i0 = i, inext = i + fc[ifc].m;
		    for (; i < inext; ++i)
			 if (!isnan(fcval_cur[i])) {
			      feasible_cur = feasible_cur 
				   && (fcval_cur[i] <= fc[ifc].tol[i-i0]);
			      if (!isnan(fcval[i]))
				   inner_done = inner_done && 
					(dd.gcval[i] >= fcval_cur[i]);
			      else if (fcval_cur[i] > 0)
				   new_infeasible_constraint = 1;
			      if (fcval_cur[i] > infeasibility_cur)
				   infeasibility_cur = fcval_cur[i];
			 }
	       }

	       if ((fcur < *minf && (inner_done || feasible_cur || !feasible))
		    || (!feasible && infeasibility_cur < infeasibility)) {
		    if (mma_verbose && !feasible_cur)
			 printf("MMA - using infeasible point?\n");
		    dd.fval = *minf = fcur;
		    infeasibility = infeasibility_cur;
		    memcpy(fcval, fcval_cur, sizeof(double)*m);
		    memcpy(x, xcur, sizeof(double)*n);
		    memcpy(dfdx, dfdx_cur, sizeof(double)*n);
		    memcpy(dfcdx, dfcdx_cur, sizeof(double)*n*m);
		    
		    /* once we have reached a feasible solution, the
		       algorithm should never make the solution infeasible
		       again (if inner_done), although the constraints may
		       be violated slightly by rounding errors etc. so we
		       must be a little careful about checking feasibility */
		    if (infeasibility_cur == 0) {
			 if (!feasible) { /* reset upper bounds to infin. */
			      for (i = 0; i < m; ++i) dual_ub[i] = HUGE_VAL;
			      nlopt_set_upper_bounds(dual_opt, dual_ub);
			 }
			 feasible = 1;
		    }
		    else if (new_infeasible_constraint) feasible = 0;

	       }
	       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;
	       else if (feasible && *minf < stop->minf_max) 
		    ret = NLOPT_MINF_MAX_REACHED;
	       if (ret != NLOPT_SUCCESS) goto done;

	       if (inner_done) break;

	       if (fcur > dd.gval)
		    rho = MIN(10*rho, 1.1 * (rho + (fcur-dd.gval) / dd.wval));
	       for (i = 0; i < m; ++i)
		    if (!isnan(fcval_cur[i]) && fcval_cur[i] > dd.gcval[i])
			 rhoc[i] = 
			      MIN(10*rhoc[i], 
				  1.1 * (rhoc[i] + (fcval_cur[i]-dd.gcval[i]) 
					 / dd.wval));
	       
	       if (mma_verbose)
		    printf("MMA inner iteration: rho -> %g\n", rho);
	       for (i = 0; i < MIN(mma_verbose, m); ++i)
		    printf("                 MMA rhoc[%d] -> %g\n", i,rhoc[i]);
	  }

	  if (nlopt_stop_ftol(stop, fcur, fprev))
	       ret = NLOPT_FTOL_REACHED;
	  if (nlopt_stop_x(stop, xcur, xprev))
	       ret = NLOPT_XTOL_REACHED;
	  if (ret != NLOPT_SUCCESS) goto done;
	       
	  /* update rho and sigma for iteration k+1 */
	  rho = MAX(0.1 * rho, MMA_RHOMIN);
	  if (mma_verbose)
	       printf("MMA outer iteration: rho -> %g\n", rho);
	  for (i = 0; i < m; ++i)
	       rhoc[i] = MAX(0.1 * rhoc[i], MMA_RHOMIN);
	  for (i = 0; i < MIN(mma_verbose, m); ++i)
	       printf("                 MMA rhoc[%d] -> %g\n", i, rhoc[i]);
	  if (k > 1) {
	       for (j = 0; j < n; ++j) {
		    double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]);
		    double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1);
		    sigma[j] *= gam;
		    if (!nlopt_isinf(ub[j]) && !nlopt_isinf(lb[j])) {
			 sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j]));
			 sigma[j] = MAX(sigma[j], 0.01*(ub[j]-lb[j]));
		    }
	       }
	       for (j = 0; j < MIN(mma_verbose, n); ++j)
		    printf("                 MMA sigma[%d] -> %g\n", 
			   j, sigma[j]);
	  }
     }

 done:
     free(sigma);
     return ret;
}
Esempio n. 6
0
nlopt_result chevolutionarystrategy(
     unsigned nparameters, /* Number of input parameters */
     nlopt_func f,	/* Recursive Objective Funtion Call */
     void * data_f,	/* Data to Objective Function */
     const double* lb,			/* Lower bound values */
     const double* ub,			/* Upper bound values */
     double* x,				/*in: initial guess, out: minimizer */
     double* minf,
     nlopt_stopping* stop, 		/* nlopt stop condition */
     unsigned np, 			/* Number of Parents */
     unsigned no) { 			/* Number of Offsprings */

     /* variables from nlopt */
     nlopt_result ret = NLOPT_SUCCESS;
     double vetor[8];
     unsigned  i, id, item;
     int  parent1, parent2;
     unsigned crosspoint;  /* crossover parameteres */
     int  contmutation, totalmutation;	/* mutation parameters */
     int  idoffmutation, paramoffmutation;	/* mutation parameters */
     Individual * esparents;			/* Parents population */
     Individual * esoffsprings;		/* Offsprings population */
     Individual * estotal;/* copy containing Parents and Offsprings pops */
     /* It is interesting to maintain the parents and offsprings
      * populations stablished and sorted; when the final iterations
      * is achieved, they are ranked and updated. */

     /*********************************
      * controling the population size
      *********************************/
     if (!np) np = 40;
     if (!no) no = 60;
     if ((np < 1)||(no<1)) {
         nlopt_stop_msg(stop, "populations %d, %d are too small", np, no);
         return NLOPT_INVALID_ARGS;
     }
     esparents    = (Individual*) malloc(sizeof(Individual) * np);
     esoffsprings = (Individual*) malloc(sizeof(Individual) * no);
     estotal 	 = (Individual*) malloc(sizeof(Individual) * (np+no));
     if ((!esparents)||(!esoffsprings)||(!estotal)) {
	  free(esparents); free(esoffsprings); free(estotal);
	  return NLOPT_OUT_OF_MEMORY;
     }
     for (id=0; id < np; id++) esparents[id].parameters = NULL;
     for (id=0; id < no; id++) esoffsprings[id].parameters = NULL;
     /* From here the population is initialized */
     /* we don't handle unbounded search regions;
	    this check is unnecessary since it is performed in nlopt_optimize.
	 for (j = 0; j < nparameters; ++j)
   	  if (nlopt_isinf(low[j]) || nlopt_isinf(up[j]))
	    return NLOPT_INVALID_ARGS;
     */
     /* main vector of parameters to randcauchy */
     vetor[0] = 4; /* ignored */
     vetor[3] = 0;
     vetor[4] = 1;
     vetor[5] = 10;
     vetor[6] = 1;
     vetor[7] = 0; /* ignored */
     /**************************************
      * Initializing parents population
      **************************************/
     for (id=0; id < np; id++) {
	  esparents[id].parameters =
	       (double*) malloc(sizeof(double) * nparameters);
	  if (!esparents[id].parameters) {
	       ret = NLOPT_OUT_OF_MEMORY;
	       goto done;
	  }
	  for (item=0; item<nparameters; item++) {
	       vetor[1] = lb[item];
	       vetor[2] = ub[item];
	       vetor[7]=vetor[7]+1;
	       esparents[id].parameters[item] = randcauchy(vetor);
	  }
     }
     memcpy(esparents[0].parameters, x, nparameters * sizeof(double));

     /**************************************
      * Initializing offsprings population
      **************************************/
     for (id=0; id < no; id++) {
	  esoffsprings[id].parameters =
	       (double*) malloc(sizeof(double) * nparameters);
	  if (!esoffsprings[id].parameters) {
	       ret = NLOPT_OUT_OF_MEMORY;
	       goto done;
	  }
	  for (item=0; item<nparameters; item++) {
	       vetor[1] = lb[item];
	       vetor[2] = ub[item];
	       vetor[7]=vetor[7]+1;
	       esoffsprings[id].parameters[item] = randcauchy(vetor);
	  }
     }
     /**************************************
      * Parents fitness evaluation
      **************************************/
     for (id=0; id < np; id++) {
	  esparents[id].fitness =
	       f(nparameters, esparents[id].parameters, NULL, data_f);
	  estotal[id].fitness = esparents[id].fitness;
	  stop->nevals++;
	  if (*minf > esparents[id].fitness) {
	       *minf = esparents[id].fitness;
	       memcpy(x, esparents[id].parameters,
		      nparameters * sizeof(double));
	  }
	  if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
	  else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
	  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;
     }
     /**************************************
      * Main Loop - Generations
      **************************************/
     while (1) {
	  /**************************************
	   * Crossover
	   **************************************/
	  for (id=0; id < no; id++)
	  {
	       parent1  = nlopt_iurand((int) np);
	       parent2  = nlopt_iurand((int) np);
	       crosspoint = (unsigned) nlopt_iurand((int) nparameters);
	       for (item=0; item < crosspoint; item++)
		    esoffsprings[id].parameters[item]
			 = esparents[parent1].parameters[item];
	       for (item=crosspoint; item < nparameters; item++)
		    esoffsprings[id].parameters[item]
			 = esparents[parent2].parameters[item];
	  }
	  /**************************************
	   * Gaussian Mutation
	   **************************************/
	  totalmutation = (int) ((no * nparameters) / 10);
	  if (totalmutation < 1) totalmutation = 1;
	  for (contmutation=0; contmutation < totalmutation;
	       contmutation++) {
	       idoffmutation = nlopt_iurand((int) no);
	       paramoffmutation = nlopt_iurand((int) nparameters);
	       vetor[1] = lb[paramoffmutation];
	       vetor[2] = ub[paramoffmutation];
	       vetor[7] = vetor[7]+contmutation;
	       esoffsprings[idoffmutation].parameters[paramoffmutation]
		    = randcauchy(vetor);
	  }
	  /**************************************
	   * Offsprings fitness evaluation
	   **************************************/
	  for (id=0; id < no; id++){
	       /*esoffsprings[id].fitness = (double)fitness(esoffsprings[id].parameters, nparameters,fittype);*/
	       esoffsprings[id].fitness = f(nparameters, esoffsprings[id].parameters, NULL, data_f);
	       estotal[id+np].fitness = esoffsprings[id].fitness;
	       stop->nevals++;
	       if (*minf > esoffsprings[id].fitness) {
		    *minf = esoffsprings[id].fitness;
		    memcpy(x, esoffsprings[id].parameters,
			   nparameters * sizeof(double));
	       }
	       if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
	       else if (*minf < stop->minf_max)
		    ret = NLOPT_MINF_MAX_REACHED;
	       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;
	  }
	  /**************************************
	   * Individual selection
	   **************************************/
	  /* all the individuals are copied to one vector to easily identify best solutions */
	  for (i=0; i < np; i++)
	       estotal[i] = esparents[i];
	  for (i=0; i < no; i++)
	       estotal[np+i] = esoffsprings[i];
	  /* Sorting */
	  nlopt_qsort_r(estotal, no+np, sizeof(Individual), NULL,
			CompareIndividuals);
	  /* copy after sorting: */
	  for (i=0; i < no+np; i++) {
	       if (i<np)
		    esparents[i] = estotal[i];
	       else
		    esoffsprings[i-np] = estotal[i];
	  }
     } /* generations loop */

done:
     for (id=0; id < np; id++) free(esparents[id].parameters);
     for (id=0; id < no; id++) free(esoffsprings[id].parameters);

     if (esparents) 	free(esparents);
     if (esoffsprings) 	free(esoffsprings);
     if (estotal) 		free(estotal);
     return ret;
}
Esempio n. 7
0
File: isres.c Progetto: 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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
int nlopt_stop_evalstime(const nlopt_stopping *stop)
{
     return nlopt_stop_evals(stop) || nlopt_stop_time(stop);
}
nlopt_result mlsl_minimize(int n, nlopt_func f, void *f_data,
			   const double *lb, const double *ub, /* bounds */
			   double *x, /* in: initial guess, out: minimizer */
			   double *minf,
			   nlopt_stopping *stop,
			   nlopt_opt local_opt,
			   int Nsamples, /* #samples/iteration (0=default) */
			   int lds) /* random or low-discrepancy seq. (lds) */
{
     nlopt_result ret = NLOPT_SUCCESS;
     mlsl_data d;
     int i;
     pt *p;

     if (!Nsamples)
	  d.N = 4; /* FIXME: what is good number of samples per iteration? */
     else
	  d.N = Nsamples;
     if (d.N < 1) return NLOPT_INVALID_ARGS;

     d.n = n;
     d.lb = lb; d.ub = ub;
     d.stop = stop;
     d.f = f; d.f_data = f_data;
     rb_tree_init(&d.pts, pt_compare);
     rb_tree_init(&d.lms, lm_compare);
     d.s = lds ? nlopt_sobol_create((unsigned) n) : NULL;

     nlopt_set_min_objective(local_opt, fcount, &d);
     nlopt_set_lower_bounds(local_opt, lb);
     nlopt_set_upper_bounds(local_opt, ub);
     nlopt_set_stopval(local_opt, stop->minf_max);

     d.gamma = MLSL_GAMMA;

     d.R_prefactor = sqrt(2./K2PI) * pow(gam(n) * MLSL_SIGMA, 1.0/n);
     for (i = 0; i < n; ++i)
	  d.R_prefactor *= pow(ub[i] - lb[i], 1.0/n);

     /* MLSL also suggests setting some minimum distance from points
	to previous local minimiza and to the boundaries; I don't know
	how to choose this as a fixed number, so I set it proportional
	to R; see also the comments at top.  dlm and dbound are the
	proportionality constants. */
     d.dlm = 1.0; /* min distance/R to local minima (FIXME: good value?) */
     d.dbound = 1e-6; /* min distance/R to ub/lb boundaries (good value?) */
     

     p = alloc_pt(n);
     if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; }

     /* FIXME: how many sobol points to skip, if any? */
     nlopt_sobol_skip(d.s, (unsigned) (10*n+d.N), p->x);

     memcpy(p->x, x, n * sizeof(double));
     p->f = f(n, x, NULL, f_data);
     stop->nevals++;
     if (!rb_tree_insert(&d.pts, (rb_key) p)) { 
	  free(p); ret = NLOPT_OUT_OF_MEMORY; 
     }
     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;
     else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;

     while (ret == NLOPT_SUCCESS) {
	  rb_node *node;
	  double R;

	  get_minf(&d, minf, x);

	  /* sampling phase: add random/quasi-random points */
	  for (i = 0; i < d.N && ret == NLOPT_SUCCESS; ++i) {
	       p = alloc_pt(n);
	       if (!p) { ret = NLOPT_OUT_OF_MEMORY; goto done; }
	       if (d.s) nlopt_sobol_next(d.s, p->x, lb, ub);
	       else { /* use random points instead of LDS */
		    int j;
		    for (j = 0; j < n; ++j) p->x[j] = nlopt_urand(lb[j],ub[j]);
	       }
	       p->f = f(n, p->x, NULL, f_data);
	       stop->nevals++;
	       if (!rb_tree_insert(&d.pts, (rb_key) p)) { 
		    free(p); ret = NLOPT_OUT_OF_MEMORY;
	       }
	       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;
	       else if (p->f < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
	       else {
		    find_closest_pt(n, &d.pts, p);
		    find_closest_lm(n, &d.lms, p);
		    pts_update_newpt(n, &d.pts, p);
	       }
	  }

	  /* distance threshhold parameter R in MLSL */
	  R = d.R_prefactor 
	       * pow(log((double) d.pts.N) / d.pts.N, 1.0 / n);

	  /* local search phase: do local opt. for promising points */
	  node = rb_tree_min(&d.pts);
	  for (i = (int) (ceil(d.gamma * d.pts.N) + 0.5); 
	       node && i > 0 && ret == NLOPT_SUCCESS; --i) {
	       p = (pt *) node->k;
	       if (is_potential_minimizer(&d, p, 
					  R, d.dlm*R, d.dbound*R)) {
		    nlopt_result lret;
		    double *lm;
		    double t = nlopt_seconds();

		    if (nlopt_stop_forced(stop)) {
			 ret = NLOPT_FORCED_STOP; break;
		    }
		    if (nlopt_stop_evals(stop)) {
                         ret = NLOPT_MAXEVAL_REACHED; break;
		    }
		    if (stop->maxtime > 0 &&
			t - stop->start >= stop->maxtime) {
			 ret = NLOPT_MAXTIME_REACHED; break;
		    }
		    lm = (double *) malloc(sizeof(double) * (n+1));
		    if (!lm) { ret = NLOPT_OUT_OF_MEMORY; goto done; }
		    memcpy(lm+1, p->x, sizeof(double) * n);
		    lret = nlopt_optimize_limited(local_opt, lm+1, lm,
						  stop->maxeval - stop->nevals,
						  stop->maxtime -
						  (t - stop->start));
		    p->minimized = 1;
		    if (lret < 0) { free(lm); ret = lret; goto done; }
		    if (!rb_tree_insert(&d.lms, lm)) { 
			 free(lm); ret = NLOPT_OUT_OF_MEMORY;
		    }
		    else if (nlopt_stop_forced(stop)) ret = NLOPT_FORCED_STOP;
		    else if (*lm < stop->minf_max) 
			 ret = NLOPT_MINF_MAX_REACHED;
		    else if (nlopt_stop_evals(stop))
			 ret = NLOPT_MAXEVAL_REACHED;
		    else if (nlopt_stop_time(stop))
			 ret = NLOPT_MAXTIME_REACHED;
		    else
			 pts_update_newlm(n, &d.pts, lm);
	       }

	       /* TODO: additional stopping criteria based
		  e.g. on improvement in function values, etc? */
	       
	       node = rb_tree_succ(node);
	  }
     }

     get_minf(&d, minf, x);

 done:
     nlopt_sobol_destroy(d.s);
     rb_tree_destroy_with_keys(&d.lms);
     rb_tree_destroy_with_keys(&d.pts);
     return ret;
}