Beispiel #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;
}
Beispiel #2
0
static nlopt_result divide_largest(params *p)
{
     int L = p->L;
     int n = p->n;
     rb_node *node = rb_tree_max(&p->rtree); /* just using it as a heap */
     double minf_start = p->minf;
     double *r = node->k, *rnew = NULL;
     double *x = r + 3, *c = x + n, *w = c + n;
     const double *lb = p->lb, *ub = p->ub;
     int i, idiv;
     double wmax;
     nlopt_result ret;

     /* printf("rect:, %d, %g, %g, %g, %g\n", p->stop->nevals, c[0], c[1], w[0], w[1]); */

     /* check xtol */
     for (i = 0; i < n; ++i)
	  if (w[i] > p->stop->xtol_rel * (ub[i] - lb[i])
	      && w[i] > p->stop->xtol_abs[i])
	       break;
     if (i == n) return NLOPT_XTOL_REACHED;

     if (p->randomized_div) { /* randomly pick among ~largest sides */
	  int nlongest = 0;
	  wmax = longest(n, w);
	  for (i = 0; i < n; ++i)
	       if (wmax - w[i] < EQUAL_SIDE_TOL * wmax) ++nlongest;
	  i = 1 + nlopt_iurand(nlongest);
	  for (idiv = 0; idiv < n; ++idiv) {
	       if (wmax - w[idiv] < EQUAL_SIDE_TOL * wmax) --i;
	       if (!i) break;
	  }
     }
     else { /* just pick first largest side */
	  wmax = w[idiv = 0];
	  for (i = 1; i < n; ++i) if (w[i] > wmax) wmax = w[idiv = i];
     }

     if (fabs(x[idiv] - c[idiv]) > (0.5 * THIRD) * w[idiv]) { /* bisect */
	  double deltac = (x[idiv] > c[idiv] ? 0.25 : -0.25) * w[idiv];
	  w[idiv] *= 0.5;
	  c[idiv] += deltac;
	  r[0] = longest(n, w); /* new diameter */
	  /* r[1] unchanged since still contains local optimum x */
	  r[2] = p->age--;
	  node = rb_tree_resort(&p->rtree, node);

	  rnew = (double *) malloc(sizeof(double) * L);
	  if (!rnew) return NLOPT_OUT_OF_MEMORY;
	  memcpy(rnew, r, sizeof(double) * L);
	  rnew[2] = p->age--;
	  rnew[3+n+idiv] -= deltac*2;
	  if (p->randomized_div)
	       randomize_x(n, rnew);
	  else
	       memcpy(rnew+3, rnew+3+n, sizeof(double) * n); /* x = c */
	  ret = optimize_rect(rnew, p);
	  if (ret != NLOPT_SUCCESS) { free(rnew); return ret; }
	  if (!rb_tree_insert(&p->rtree, rnew)) {
	       free(rnew); return NLOPT_OUT_OF_MEMORY;
	  }
     }
     else { /* trisect */
	  w[idiv] *= THIRD;
	  r[0] = longest(n, w);
	  /* r[1] unchanged since still contains local optimum x */
	  r[2] = p->age--;
	  node = rb_tree_resort(&p->rtree, node);

	  for (i = -1; i <= +1; i += 2) {
	       rnew = (double *) malloc(sizeof(double) * L);
	       if (!rnew) return NLOPT_OUT_OF_MEMORY;
	       memcpy(rnew, r, sizeof(double) * L);
	       rnew[2] = p->age--;
	       rnew[3+n+idiv] += w[i] * i;
	       if (p->randomized_div)
		    randomize_x(n, rnew);
	       else
		    memcpy(rnew+3, rnew+3+n, sizeof(double) * n); /* x = c */
	       ret = optimize_rect(rnew, p);
	       if (ret != NLOPT_SUCCESS) { free(rnew); return ret; }
	       if (!rb_tree_insert(&p->rtree, rnew)) {
		    free(rnew); return NLOPT_OUT_OF_MEMORY;
	       }
	  }
     }
     if (p->minf < minf_start && nlopt_stop_f(p->stop, p->minf, minf_start))
	  return NLOPT_FTOL_REACHED;
     return NLOPT_SUCCESS;
}
Beispiel #3
0
/* Internal version of nldrmd_minimize, intended to be used as
   a subroutine for the subplex method.  Three differences compared
   to nldrmd_minimize:

   *minf should contain the value of f(x)  (so that we don't have to
   re-evaluate f at the starting x).

   if psi > 0, then it *replaces* xtol and ftol in stop with the condition
   that the simplex diameter |xl - xh| must be reduced by a factor of psi 
   ... this is for when nldrmd is used within the subplex method; for
   ordinary termination tests, set psi = 0. 

   scratch should contain an array of length >= (n+1)*(n+1) + 2*n,
   used as scratch workspace. 

   On output, *fdiff will contain the difference between the high
   and low function values of the last simplex. */
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,
			     double psi, double *scratch,
			     double *fdiff)
{
     double *pts; /* (n+1) x (n+1) array of n+1 points plus function val [0] */
     double *c; /* centroid * n */
     double *xcur; /* current point */
     rb_tree t; /* red-black tree of simplex, sorted by f(x) */
     int i, j;
     double ninv = 1.0 / n;
     nlopt_result ret = NLOPT_SUCCESS;
     double init_diam = 0;

     pts = scratch;
     c = scratch + (n+1)*(n+1);
     xcur = c + n;

     rb_tree_init(&t, simplex_compare);

     *fdiff = HUGE_VAL;

     /* initialize the simplex based on the starting xstep */
     memcpy(pts+1, x, sizeof(double)*n);
     pts[0] = *minf;
     if (*minf < stop->minf_max) { ret=NLOPT_MINF_MAX_REACHED; goto done; }
     for (i = 0; i < n; ++i) {
	  double *pt = pts + (i+1)*(n+1);
	  memcpy(pt+1, x, sizeof(double)*n);
	  pt[1+i] += xstep[i];
	  if (pt[1+i] > ub[i]) {
	       if (ub[i] - x[i] > fabs(xstep[i]) * 0.1)
		    pt[1+i] = ub[i];
	       else /* ub is too close to pt, go in other direction */
		    pt[1+i] = x[i] - fabs(xstep[i]);
	  }
	  if (pt[1+i] < lb[i]) {
	       if (x[i] - lb[i] > fabs(xstep[i]) * 0.1)
		    pt[1+i] = lb[i];
	       else {/* lb is too close to pt, go in other direction */
		    pt[1+i] = x[i] + fabs(xstep[i]);
		    if (pt[1+i] > ub[i]) /* go towards further of lb, ub */
			 pt[1+i] = 0.5 * ((ub[i] - x[i] > x[i] - lb[i] ?
					   ub[i] : lb[i]) + x[i]);
	       }
	  }
	  if (close(pt[1+i], x[i])) { ret=NLOPT_FAILURE; goto done; }
	  pt[0] = f(n, pt+1, NULL, f_data);
	  CHECK_EVAL(pt+1, pt[0]);
     }

 restart:
     for (i = 0; i < n + 1; ++i)
	  if (!rb_tree_insert(&t, pts + i*(n+1))) {
	       ret = NLOPT_OUT_OF_MEMORY;
	       goto done;
	  }

     while (1) {
	  rb_node *low = rb_tree_min(&t);
	  rb_node *high = rb_tree_max(&t);
	  double fl = low->k[0], *xl = low->k + 1;
	  double fh = high->k[0], *xh = high->k + 1;
	  double fr;

	  *fdiff = fh - fl;

	  if (init_diam == 0) /* initialize diam. for psi convergence test */
	       for (i = 0; i < n; ++i) init_diam += fabs(xl[i] - xh[i]);

	  if (psi <= 0 && nlopt_stop_ftol(stop, fl, fh)) {
	       ret = NLOPT_FTOL_REACHED;
	       goto done;
	  }

	  /* compute centroid ... if we cared about the perfomance of this,
	     we could do it iteratively by updating the centroid on
	     each step, but then we would have to be more careful about
	     accumulation of rounding errors... anyway n is unlikely to
	     be very large for Nelder-Mead in practical cases */
	  memset(c, 0, sizeof(double)*n);
	  for (i = 0; i < n + 1; ++i) {
	       double *xi = pts + i*(n+1) + 1;
	       if (xi != xh)
		    for (j = 0; j < n; ++j)
			 c[j] += xi[j];
	  }
	  for (i = 0; i < n; ++i) c[i] *= ninv;

	  /* x convergence check: find xcur = max radius from centroid */
	  memset(xcur, 0, sizeof(double)*n);
	  for (i = 0; i < n + 1; ++i) {
               double *xi = pts + i*(n+1) + 1;
	       for (j = 0; j < n; ++j) {
		    double dx = fabs(xi[j] - c[j]);
		    if (dx > xcur[j]) xcur[j] = dx;
	       }
	  }
	  for (i = 0; i < n; ++i) xcur[i] += c[i];
	  if (psi > 0) {
	       double diam = 0;
	       for (i = 0; i < n; ++i) diam += fabs(xl[i] - xh[i]);
	       if (diam < psi * init_diam) {
		    ret = NLOPT_XTOL_REACHED;
		    goto done;
	       }
	  }
	  else if (nlopt_stop_x(stop, c, xcur)) {
	       ret = NLOPT_XTOL_REACHED;
	       goto done;
	  }

	  /* reflection */
	  if (!reflectpt(n, xcur, c, alpha, xh, lb, ub)) { 
	       ret=NLOPT_XTOL_REACHED; goto done; 
	  }
	  fr = f(n, xcur, NULL, f_data);
	  CHECK_EVAL(xcur, fr);

	  if (fr < fl) { /* new best point, expand simplex */
	       if (!reflectpt(n, xh, c, gamm, xh, lb, ub)) {
		    ret=NLOPT_XTOL_REACHED; goto done; 
	       }
	       fh = f(n, xh, NULL, f_data);
	       CHECK_EVAL(xh, fh);
	       if (fh >= fr) { /* expanding didn't improve */
		    fh = fr;
		    memcpy(xh, xcur, sizeof(double)*n);
	       }
	  }
	  else if (fr < rb_tree_pred(high)->k[0]) { /* accept new point */
	       memcpy(xh, xcur, sizeof(double)*n);
	       fh = fr;
	  }
	  else { /* new worst point, contract */
	       double fc;
	       if (!reflectpt(n,xcur,c, fh <= fr ? -beta : beta, xh, lb,ub)) {
		    ret=NLOPT_XTOL_REACHED; goto done; 
	       }
	       fc = f(n, xcur, NULL, f_data);
	       CHECK_EVAL(xcur, fc);
	       if (fc < fr && fc < fh) { /* successful contraction */
		    memcpy(xh, xcur, sizeof(double)*n);
		    fh = fc;
	       }
	       else { /* failed contraction, shrink simplex */
		    rb_tree_destroy(&t);
		    rb_tree_init(&t, simplex_compare);
		    for (i = 0; i < n+1; ++i) {
			 double *pt = pts + i * (n+1);
			 if (pt+1 != xl) {
			      if (!reflectpt(n,pt+1, xl,-delta,pt+1, lb,ub)) {
				   ret = NLOPT_XTOL_REACHED;
				   goto done;
			      }
			      pt[0] = f(n, pt+1, NULL, f_data);
			      CHECK_EVAL(pt+1, pt[0]);
			 }
		    }
		    goto restart;
	       }
	  }

	  high->k[0] = fh;
	  rb_tree_resort(&t, high);
     }
     
done:
     rb_tree_destroy(&t);
     return ret;
}
Beispiel #4
0
/* divide rectangle idiv in the list p->rects */
static nlopt_result divide_rect(double *rdiv, params *p)
{
     int i;
     const int n = p->n;
     const int L = p->L;
     double *c = rdiv + 3; /* center of rect to divide */
     double *w = c + n; /* widths of rect to divide */
     double wmax = w[0];
     int imax = 0, nlongest = 0;
     rb_node *node;

     for (i = 1; i < n; ++i)
	  if (w[i] > wmax)
	       wmax = w[imax = i];
     for (i = 0; i < n; ++i)
	  if (wmax - w[i] <= wmax * EQUAL_SIDE_TOL)
	       ++nlongest;
     if (p->which_div == 1 || (p->which_div == 0 && nlongest == n)) {
	  /* trisect all longest sides, in increasing order of the average
	     function value along that direction */
	  double *fv = p->work;
	  int *isort = p->iwork;
	  for (i = 0; i < n; ++i) {
	       if (wmax - w[i] <= wmax * EQUAL_SIDE_TOL) {
		    double csave = c[i];
		    c[i] = csave - w[i] * THIRD;
		    FUNCTION_EVAL(fv[2*i], c, p, 0);
		    c[i] = csave + w[i] * THIRD;
		    FUNCTION_EVAL(fv[2*i+1], c, p, 0);
		    c[i] = csave;
	       }
	       else {
		    fv[2*i] = fv[2*i+1] = HUGE_VAL;
	       }
	  }
	  sort_fv(n, fv, isort);
	  if (!(node = rb_tree_find(&p->rtree, rdiv)))
	       return NLOPT_FAILURE;
	  for (i = 0; i < nlongest; ++i) {
	       int k;
	       w[isort[i]] *= THIRD;
	       rdiv[0] = rect_diameter(n, w, p);
	       rdiv[2] = p->age++;
	       node = rb_tree_resort(&p->rtree, node);
	       for (k = 0; k <= 1; ++k) {
		    double *rnew;
		    ALLOC_RECT(rnew, L);
		    memcpy(rnew, rdiv, sizeof(double) * L);
		    rnew[3 + isort[i]] += w[isort[i]] * (2*k-1);
		    rnew[1] = fv[2*isort[i]+k];
		    rnew[2] = p->age++;
		    if (!rb_tree_insert(&p->rtree, rnew)) {
			 free(rnew);
			 return NLOPT_OUT_OF_MEMORY;
		    }
	       }
	  }
     }
     else {
	  int k;
	  if (nlongest > 1 && p->which_div == 2) { 
               /* randomly choose longest side */
	       i = nlopt_iurand(nlongest);
	       for (k = 0; k < n; ++k)
		    if (wmax - w[k] <= wmax * EQUAL_SIDE_TOL) {
			 if (!i) { i = k; break; }
			 --i;
		    }
	  }
	  else
	       i = imax; /* trisect longest side */
	  if (!(node = rb_tree_find(&p->rtree, rdiv)))
	       return NLOPT_FAILURE;
	  w[i] *= THIRD;
	  rdiv[0] = rect_diameter(n, w, p);
	  rdiv[2] = p->age++;
	  node = rb_tree_resort(&p->rtree, node);
	  for (k = 0; k <= 1; ++k) {
	       double *rnew;
	       ALLOC_RECT(rnew, L);
	       memcpy(rnew, rdiv, sizeof(double) * L);
	       rnew[3 + i] += w[i] * (2*k-1);
	       FUNCTION_EVAL(rnew[1], rnew + 3, p, rnew);
	       rnew[2] = p->age++;
	       if (!rb_tree_insert(&p->rtree, rnew)) {
		    free(rnew);
		    return NLOPT_OUT_OF_MEMORY;
	       }
	  }
     }
     return NLOPT_SUCCESS;
}
Beispiel #5
0
int main(int argc, char **argv)
{
    int N, M;
    int *k;
    double kd;
    rb_tree t;
    rb_node *n;
    int i, j;

    if (argc < 2) {
        fprintf(stderr, "Usage: redblack_test Ntest [rand seed]\n");
        return 1;
    }

    N = atoi(argv[1]);
    k = (int *) malloc(N * sizeof(int));
    rb_tree_init(&t, comp);

    srand((unsigned) (argc > 2 ? atoi(argv[2]) : time(NULL)));
    for (i = 0; i < N; ++i) {
        double *newk = (double *) malloc(sizeof(double));
        *newk = (k[i] = rand() % N);
        if (!rb_tree_insert(&t, newk)) {
            fprintf(stderr, "error in rb_tree_insert\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after insert!\n");
            return 1;
        }
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i) {
        kd = k[i];
        if (!rb_tree_find(&t, &kd)) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
    }

    n = rb_tree_min(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough successors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_succ(n);
    }
    if (n) {
        fprintf(stderr, "too many successors!\n");
        return 1;
    }

    n = rb_tree_max(&t);
    for (i = 0; i < N; ++i) {
        if (!n) {
            fprintf(stderr, "not enough predecessors %d\n!", i);
            return 1;
        }
        printf("%d: %g\n", i, n->k[0]);
        n = rb_tree_pred(n);
    }
    if (n) {
        fprintf(stderr, "too many predecessors!\n");
        return 1;
    }

    for (M = N; M > 0; --M) {
        int knew = rand() % N;  /* random new key */
        j = rand() % M;         /* random original key to replace */
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n->k[0] = knew;
        if (!rb_tree_resort(&t, n)) {
            fprintf(stderr, "error in rb_tree_resort\n");
            return 1;
        }
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after change %d!\n", N - M + 1);
            return 1;
        }
        k[i] = -1 - knew;
    }

    if (t.N != N) {
        fprintf(stderr, "incorrect N (%d) in tree (vs. %d)\n", t.N, N);
        return 1;
    }

    for (i = 0; i < N; ++i)
        k[i] = -1 - k[i];       /* undo negation above */

    for (i = 0; i < N; ++i) {
        rb_node *le, *gt;
        double lek, gtk;
        kd = 0.01 * (rand() % (N * 150) - N * 25);
        le = rb_tree_find_le(&t, &kd);
        gt = rb_tree_find_gt(&t, &kd);
        n = rb_tree_min(&t);
        lek = le ? le->k[0] : -HUGE_VAL;
        gtk = gt ? gt->k[0] : +HUGE_VAL;
        printf("%g <= %g < %g\n", lek, kd, gtk);
        if (n->k[0] > kd) {
            if (le) {
                fprintf(stderr, "found invalid le %g for %g\n", lek, kd);
                return 1;
            }
            if (gt != n) {
                fprintf(stderr, "gt is not first node for k=%g\n", kd);
                return 1;
            }
        } else {
            rb_node *succ = n;
            do {
                n = succ;
                succ = rb_tree_succ(n);
            } while (succ && succ->k[0] <= kd);
            if (n != le) {
                fprintf(stderr, "rb_tree_find_le gave wrong result for k=%g\n", kd);
                return 1;
            }
            if (succ != gt) {
                fprintf(stderr, "rb_tree_find_gt gave wrong result for k=%g\n", kd);
                return 1;
            }
        }
    }

    for (M = N; M > 0; --M) {
        j = rand() % M;
        for (i = 0; i < N; ++i)
            if (k[i] >= 0)
                if (j-- == 0)
                    break;
        if (i >= N)
            abort();
        kd = k[i];
        if (!(n = rb_tree_find(&t, &kd))) {
            fprintf(stderr, "rb_tree_find lost %d!\n", k[i]);
            return 1;
        }
        n = rb_tree_remove(&t, n);
        free(n->k);
        free(n);
        if (!rb_tree_check(&t)) {
            fprintf(stderr, "rb_tree_check_failed after remove!\n");
            return 1;
        }
        k[i] = -1 - k[i];
    }

    if (t.N != 0) {
        fprintf(stderr, "nonzero N (%d) in tree at end\n", t.N);
        return 1;
    }

    rb_tree_destroy(&t);
    free(k);

    printf("SUCCESS.\n");
    return 0;
}