示例#1
0
void nlopt_qsort_r(void *base_, size_t nmemb, size_t size, void *thunk,
		   int (*compar)(void *, const void *, const void *))
{
#ifdef HAVE_QSORT_R_damn_it_use_my_own
     /* Even if we could detect glibc vs. BSD by appropriate
	macrology, there is no way to make the calls compatible
	without writing a wrapper for the compar function...screw
	this. */
     qsort_r(base_, nmemb, size, thunk, compar);
#else
     char *base = (char *) base_;
     if (nmemb < 10) { /* use O(nmemb^2) algorithm for small enough nmemb */
	  size_t i, j;
	  for (i = 0; i+1 < nmemb; ++i)
	       for (j = i+1; j < nmemb; ++j)
		    if (compar(thunk, base+i*size, base+j*size) > 0)
			 swap(base+i*size, base+j*size, size);
     }
     else {
	  size_t i, pivot, npart;
	  /* pick median of first/middle/last elements as pivot */
	  {
	       const char *a = base, *b = base + (nmemb/2)*size, 
		    *c = base + (nmemb-1)*size;
	       pivot = compar(thunk,a,b) < 0
		    ? (compar(thunk,b,c) < 0 ? nmemb/2 :
		       (compar(thunk,a,c) < 0 ? nmemb-1 : 0))
		    : (compar(thunk,a,c) < 0 ? 0 :
		       (compar(thunk,b,c) < 0 ? nmemb-1 : nmemb/2));
	  }
	  /* partition array */
	  swap(base + pivot*size, base + (nmemb-1) * size, size);
	  pivot = (nmemb - 1) * size;
	  for (i = npart = 0; i < nmemb-1; ++i)
	       if (compar(thunk, base+i*size, base+pivot) <= 0)
		    swap(base+i*size, base+(npart++)*size, size);
	  swap(base+npart*size, base+pivot, size);
	  /* recursive sort of two partitions */
	  nlopt_qsort_r(base, npart, size, thunk, compar);
	  npart++; /* don't need to sort pivot */
	  nlopt_qsort_r(base+npart*size, nmemb-npart, size, thunk, compar);
     }
#endif /* !HAVE_QSORT_R */
}
示例#2
0
文件: esch.c 项目: amroamroamro/nlopt
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;
}
示例#3
0
// Unified alpha-beta and quiescence search
int abq(board *b, int alpha, int beta, int ply, int centiply_extension, bool allow_extensions, bool side_to_move_in_check) {
	if (search_terminate_requested) return 0; // Check for search termination

	int alpha_orig = alpha; // For use in later TT storage

	// Retrieve the value from the transposition table, if appropriate
	evaluation stored;
	tt_get(b, &stored);
	if (!e_eq(stored, no_eval) && stored.depth >= ply && use_ttable) {
		if (stored.type == qexact || stored.type == exact) return stored.score;
		if (stored.type == qlowerbound || stored.type == lowerbound) alpha = max(alpha, stored.score);
		else if (stored.type == qupperbound || stored.type == upperbound) beta = min(beta, stored.score);
		if (alpha >= beta) return stored.score;
	}

	// Futility pruning: enter quiescence early if the node is futile
	if (use_futility_pruning && !side_to_move_in_check && ply == 1) {
		if (relative_evaluation(b) + frontier_futility_margin < alpha) ply = 0;
	} else if (use_futility_pruning && !side_to_move_in_check && ply == 2) {
		if (relative_evaluation(b) + prefrontier_futility_margin < alpha) ply = 0;
	}

	bool quiescence = (ply <= 0);

	// Generate all possible moves for the quiscence search or normal search, and compute the
	// static evaluation if applicable.
	move *moves = NULL;
	int num_available_moves = 0;
	if (quiescence) moves = board_moves(b, &num_available_moves, true); // Generate only captures
	else moves = board_moves(b, &num_available_moves, false); // Generate all moves
	if (quiescence && !use_qsearch) {
		free(moves);
		return relative_evaluation(b); // If qsearch is turned off
	}

	// Abort if the quiescence search is too deep (currently 45 plies)
	if (ply < -quiesce_ply_cutoff) { 
		sstats.qnode_aborts++;
		free(moves);
		return relative_evaluation(b);
	}

	int quiescence_stand_pat;
	// Allow the quiescence search to generate cutoffs
	if (quiescence) {
		quiescence_stand_pat = relative_evaluation(b);
		alpha = max(alpha, quiescence_stand_pat);
		if (alpha >= beta) {
			free(moves);
			return quiescence_stand_pat;
		}
	} else if (!e_eq(stored, no_eval) && use_tt_move_hueristic) {
		assert(is_legal_move(b, stored.best)); // TODO
		// For non-quiescence search, use the TT entry as a hueristic
		moves[num_available_moves] = stored.best;
		num_available_moves++;
	}

	// Update search stats
	if (quiescence) sstats.qnodes_searched++;
	else sstats.nodes_searched++;

	// Search hueristic: sort exchanges using MVV-LVA
	if (quiescence && mvvlva) nlopt_qsort_r(moves, num_available_moves, sizeof(move), b, &capture_move_comparator);

	// Search extensions
	bool no_more_extensions = false;

	// Extend the search if we are in check
	//coord king_loc = b->black_to_move ? b->black_king : b->white_king;
	bool currently_in_check = side_to_move_in_check; //in_check(b, king_loc.col, king_loc.row, b->black_to_move);
	if (check_extend && currently_in_check && ply <= check_extend_threshold && !quiescence && allow_extensions) { // only extend in shallow non-quiescence situations 
		centiply_extension += check_extension_centiply;
		no_more_extensions = true;
	}

	// Process any extensions
	if (allow_extensions && centiply_extension >= 100) {
		centiply_extension -= 100;
		ply += 1;
	} else if (allow_extensions && centiply_extension <= -100) {
		centiply_extension += 100;
		ply -= 1;
	}

	if (no_more_extensions) allow_extensions = false; // Only allow one check extension

	move best_move_yet = no_move;
	int best_score_yet = NEG_INFINITY; 
	int num_moves_actually_examined = 0; // We might end up in checkmate
	//for (int iterations = 0; iterations < 2; iterations++) { // ABDADA iterations
		for (int i = num_available_moves - 1; i >= 0; i--) { // Iterate backwards to match MVV-LVA sort order
			/*int claimed_node_id = -1;
			if (i != num_available_moves - 1 && iterations == 1) { // Skip redundant young brothers on the first pass
				if (!tt_try_to_claim_node(b, &claimed_node_id)) continue; // Skip the node if it is already being searched
			} else tt_always_claim_node(b, &claimed_node_id);*/
			apply(b, moves[i]);
			bool we_moved_into_check;
			// Choose the more efficient version if possible
			// If we were already in check, we need to do the expensive search
			if (side_to_move_in_check) {
				coord king_loc = b->black_to_move ? b->white_king : b->black_king; // for side that just moved
				we_moved_into_check = in_check(b, king_loc.col, king_loc.row, !(b->black_to_move));
			} else we_moved_into_check = puts_in_check(b, moves[i], !b->black_to_move);
			// Never move into check
			if (we_moved_into_check) {
				unapply(b, moves[i]);
				//tt_unclaim_node(claimed_node_id);
				continue;
			}
			bool opponent_in_check = puts_in_check(b, moves[i], b->black_to_move);
			/*coord opp_king_loc = b->black_to_move ? b->black_king : b->white_king;
			bool opponent_in_check = in_check(b, opp_king_loc.col, opp_king_loc.row, (b->black_to_move));*/
			int score = -abq(b, -beta, -alpha, ply - 1, centiply_extension, allow_extensions, opponent_in_check);
			num_moves_actually_examined++;
			unapply(b, moves[i]);
			if (score > best_score_yet) {
				best_score_yet = score;
				best_move_yet = moves[i];
			}
			alpha = max(alpha, best_score_yet);
			if (alpha >= beta) {
				//tt_unclaim_node(claimed_node_id);
				break;
			}
			//tt_unclaim_node(claimed_node_id);
		}
	//}
	free(moves); // We are done with the array

	// We have no available moves (or captures) that don't leave us in check
	// This means checkmate or stalemate in normal search
	// It might mean no captures are available in quiescence search
	if (num_moves_actually_examined == 0) {
		if (quiescence) return quiescence_stand_pat; // TODO: qsearch doesn't understand stalemate or checkmate
		// This seems paradoxical, but the +1 is necessary so we pick some move in case of checkmate
		if (currently_in_check) return NEG_INFINITY + 1; // checkmate
		else return 0; // stalemate
	}

	if (quiescence && best_score_yet < quiescence_stand_pat) return quiescence_stand_pat; // TODO experimental stand pat

	if (search_terminate_requested) return 0; // Search termination preempts tt_put

	// Record the selected move in the transposition table
	evaltype type;
	if (best_score_yet <= alpha_orig) type = (quiescence) ? qupperbound : upperbound;
	else if (best_score_yet >= beta) type = (quiescence) ? qlowerbound : lowerbound;
	else type = (quiescence) ? qexact : exact;
	evaluation eval = {.best = best_move_yet, .score = best_score_yet, .type = type, .depth = ply};
	tt_put(b, eval);
	return best_score_yet;
}
示例#4
0
文件: cdirect.c 项目: Decatf/nlopt
static void sort_fv(int n, double *fv, int *isort)
{
     int i;
     for (i = 0; i < n; ++i) isort[i] = i;
     nlopt_qsort_r(isort, (unsigned) n, sizeof(int), fv, sort_fv_compare);
}
示例#5
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;
}