From dad58ecdf18d31ad40c66c47ef4bd9b8917c3ac4 Mon Sep 17 00:00:00 2001 From: stevenj Date: Thu, 24 Jun 2010 19:29:26 -0400 Subject: [PATCH] support equality constraints in COBYLA (internally, just a pair of inequality constraints: since COBYLA solves a sequence of LPs, and LPs have no problem with such pairs, it seems to converge just fine) darcs-hash:20100624232926-c8de0-6baa8f1caf2967dca27635be396fd510701580ab.gz --- api/nlopt.3 | 12 ++++++------ api/optimize.c | 1 + api/options.c | 3 ++- cobyla/cobyla.c | 13 +++++++++++++ cobyla/cobyla.h | 1 + 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/api/nlopt.3 b/api/nlopt.3 index c3c943e..8e13e69 100644 --- a/api/nlopt.3 +++ b/api/nlopt.3 @@ -200,9 +200,9 @@ constant (so that you don't have to fill an array with a constant value): .BI " double " "ub" ); .sp .SH NONLINEAR CONSTRAINTS -Several of the algorithms in NLopt (MMA, COBYLA, and ORIG_DIRECT) also -support arbitrary nonlinear inequality constraints, and some also -allow nonlinear equality constraints (ISRES and AUGLAG). For these +Several of the algorithms in NLopt (MMA and ORIG_DIRECT) also support +arbitrary nonlinear inequality constraints, and some also allow +nonlinear equality constraints (COBYLA, ISRES, and AUGLAG). For these algorithms, you can specify as many nonlinear constraints as you wish by calling the following functions multiple times. .sp @@ -450,9 +450,9 @@ Local (L) derivative-free (N) optimization using the COBYLA algorithm of Powell (Constrained Optimization BY Linear Approximations). The .B NLOPT_LN_COBYLA -algorithm supports both bound-constrained and unconstrained optimization, -and also supports an arbitrary number (\fIm\fR) of nonlinear constraints -as described above. +algorithm supports both bound-constrained and unconstrained +optimization, and also supports an arbitrary number (\fIm\fR) of +nonlinear inequality/equality constraints as described above. .TP .B NLOPT_LN_NEWUOA Local (L) derivative-free (N) optimization using a variant of the diff --git a/api/optimize.c b/api/optimize.c index 2c169b1..fe2164f 100644 --- a/api/optimize.c +++ b/api/optimize.c @@ -423,6 +423,7 @@ static nlopt_result nlopt_optimize_(nlopt_opt opt, double *x, double *minf) return NLOPT_OUT_OF_MEMORY; return cobyla_minimize(ni, f, f_data, opt->m, opt->fc, + opt->p, opt->h, lb, ub, x, minf, &stop, step); } diff --git a/api/options.c b/api/options.c index c3ae1b4..50a376e 100644 --- a/api/options.c +++ b/api/options.c @@ -367,7 +367,8 @@ NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, { if (opt && h && tol >= 0) { /* equality constraints (h(x) = 0) only via some algorithms */ - if (!AUGLAG_ALG(opt->algorithm) && opt->algorithm != NLOPT_GN_ISRES) + if (!AUGLAG_ALG(opt->algorithm) && opt->algorithm != NLOPT_GN_ISRES + && opt->algorithm != NLOPT_LN_COBYLA) return NLOPT_INVALID_ARGS; return add_constraint(&opt->p, &opt->p_alloc, &opt->h, h, h_data, tol); diff --git a/cobyla/cobyla.c b/cobyla/cobyla.c index f24c5af..fe705be 100644 --- a/cobyla/cobyla.c +++ b/cobyla/cobyla.c @@ -66,6 +66,8 @@ typedef struct { void *f_data; int m_orig; nlopt_constraint *fc; + int p; + nlopt_constraint *h; double *xtmp; const double *lb, *ub; } func_wrap_state; @@ -91,6 +93,11 @@ static int func_wrap(int n, int m, double *x, double *f, double *con, *f = s->f(n, xtmp, NULL, s->f_data); for (i = 0; i < s->m_orig; ++i) con[i] = -s->fc[i].f(n, xtmp, NULL, s->fc[i].f_data); + for (j = 0; j < s->p; ++j) { + double h = s->h[j].f(n, xtmp, NULL, s->h[j].f_data); + con[i++] = h; + con[i++] = -h; + } for (j = 0; j < n; ++j) { if (!nlopt_isinf(lb[j])) con[i++] = x[j] - lb[j]; @@ -154,6 +161,7 @@ extern nlopt_result cobyla(int n, int m, double *x, double *minf, double rhobeg, nlopt_result cobyla_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, @@ -167,10 +175,15 @@ nlopt_result cobyla_minimize(int n, nlopt_func f, void *f_data, s.f = f; s.f_data = f_data; s.m_orig = m; s.fc = fc; + s.p = p; + s.h = h; s.lb = lb; s.ub = ub; s.xtmp = (double *) malloc(sizeof(double) * n); if (!s.xtmp) return NLOPT_OUT_OF_MEMORY; + /* each equality constraint gives two inequality constraints */ + m += 2*p; + /* add constraints for lower/upper bounds (if any) */ for (j = 0; j < n; ++j) { if (!nlopt_isinf(lb[j])) diff --git a/cobyla/cobyla.h b/cobyla/cobyla.h index d1980f8..824c3bd 100644 --- a/cobyla/cobyla.h +++ b/cobyla/cobyla.h @@ -48,6 +48,7 @@ extern "C" /* NLopt-style interface function */ nlopt_result cobyla_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, -- 2.30.2