-/* Copyright (c) 2007-2009 Massachusetts Institute of Technology
+/* Copyright (c) 2007-2014 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
#include <math.h>
#include <string.h>
#include <float.h>
+#include <stdarg.h>
#include "nlopt-internal.h"
-#include "nlopt-util.h"
-#define U(n) ((unsigned int) (n))
+#define ERR(err, opt, msg) (nlopt_set_errmsg(opt, msg) ? err : err)
/*************************************************************************/
-void nlopt_destroy(nlopt_opt opt)
+void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt)
{
if (opt) {
+ unsigned i;
+ if (opt->munge_on_destroy) {
+ nlopt_munge munge = opt->munge_on_destroy;
+ munge(opt->f_data);
+ for (i = 0; i < opt->m; ++i)
+ munge(opt->fc[i].f_data);
+ for (i = 0; i < opt->p; ++i)
+ munge(opt->h[i].f_data);
+ }
+ for (i = 0; i < opt->m; ++i)
+ free(opt->fc[i].tol);
+ for (i = 0; i < opt->p; ++i)
+ free(opt->h[i].tol);
free(opt->lb); free(opt->ub);
free(opt->xtol_abs);
free(opt->fc);
free(opt->h);
nlopt_destroy(opt->local_opt);
free(opt->dx);
+ free(opt->work);
+ free(opt->errmsg);
+ free(opt);
}
}
-nlopt_opt nlopt_create(nlopt_algorithm algorithm, int n)
+nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n)
{
nlopt_opt opt;
- if (n < 0 || algorithm < 0 || algorithm >= NLOPT_NUM_ALGORITHMS)
+ if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS)
return NULL;
opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
if (opt) {
opt->algorithm = algorithm;
opt->n = n;
- opt->f = NULL; opt->f_data = NULL;
+ opt->f = NULL; opt->f_data = NULL; opt->pre = NULL;
+ opt->maximize = 0;
+ opt->munge_on_destroy = opt->munge_on_copy = NULL;
opt->lb = opt->ub = NULL;
opt->m = opt->m_alloc = 0;
opt->p = opt->p_alloc = 0;
opt->h = NULL;
- opt->minf_max = -HUGE_VAL;
+ opt->stopval = -HUGE_VAL;
opt->ftol_rel = opt->ftol_abs = 0;
opt->xtol_rel = 0; opt->xtol_abs = NULL;
opt->maxeval = 0;
opt->maxtime = 0;
+ opt->force_stop = 0;
+ opt->force_stop_child = NULL;
opt->local_opt = NULL;
opt->stochastic_population = 0;
+ opt->vector_storage = 0;
opt->dx = NULL;
+ opt->work = NULL;
+ opt->errmsg = NULL;
if (n > 0) {
- opt->lb = (double *) malloc(sizeof(double) * U(n));
+ opt->lb = (double *) calloc(n, sizeof(double));
if (!opt->lb) goto oom;
- opt->ub = (double *) malloc(sizeof(double) * U(n));
+ opt->ub = (double *) calloc(n, sizeof(double));
if (!opt->ub) goto oom;
- opt->xtol_abs = (double *) malloc(sizeof(double) * U(n));
+ opt->xtol_abs = (double *) calloc(n, sizeof(double));
if (!opt->xtol_abs) goto oom;
nlopt_set_lower_bounds1(opt, -HUGE_VAL);
nlopt_set_upper_bounds1(opt, +HUGE_VAL);
return NULL;
}
-nlopt_opt nlopt_copy(const nlopt_opt opt)
+nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt)
{
nlopt_opt nopt = NULL;
+ unsigned i;
if (opt) {
+ nlopt_munge munge;
nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
*nopt = *opt;
nopt->lb = nopt->ub = nopt->xtol_abs = NULL;
nopt->m_alloc = nopt->p_alloc = 0;
nopt->local_opt = NULL;
nopt->dx = NULL;
+ nopt->work = NULL;
+ nopt->errmsg = NULL;
+ nopt->force_stop_child = NULL;
+
+ munge = nopt->munge_on_copy;
+ if (munge && nopt->f_data)
+ if (!(nopt->f_data = munge(nopt->f_data))) goto oom;
if (opt->n > 0) {
- nopt->lb = (double *) malloc(sizeof(double) * U(opt->n));
+ nopt->lb = (double *) malloc(sizeof(double) * (opt->n));
if (!opt->lb) goto oom;
- nopt->ub = (double *) malloc(sizeof(double) * U(opt->n));
+ nopt->ub = (double *) malloc(sizeof(double) * (opt->n));
if (!opt->ub) goto oom;
- nopt->xtol_abs = (double *) malloc(sizeof(double) * U(opt->n));
+ nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n));
if (!opt->xtol_abs) goto oom;
- memcpy(nopt->lb, opt->lb, sizeof(double) * U(opt->n));
- memcpy(nopt->ub, opt->ub, sizeof(double) * U(opt->n));
- memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * U(opt->n));
+ memcpy(nopt->lb, opt->lb, sizeof(double) * (opt->n));
+ memcpy(nopt->ub, opt->ub, sizeof(double) * (opt->n));
+ memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n));
}
if (opt->m) {
nopt->m_alloc = opt->m;
nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
- * U(opt->m));
+ * (opt->m));
if (!nopt->fc) goto oom;
- memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * U(opt->m));
+ memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m));
+ for (i = 0; i < opt->m; ++i) nopt->fc[i].tol = NULL;
+ if (munge)
+ for (i = 0; i < opt->m; ++i)
+ if (nopt->fc[i].f_data &&
+ !(nopt->fc[i].f_data
+ = munge(nopt->fc[i].f_data)))
+ goto oom;
+ for (i = 0; i < opt->m; ++i)
+ if (opt->fc[i].tol) {
+ nopt->fc[i].tol = (double *) malloc(sizeof(double)
+ * nopt->fc[i].m);
+ if (!nopt->fc[i].tol) goto oom;
+ memcpy(nopt->fc[i].tol, opt->fc[i].tol,
+ sizeof(double) * nopt->fc[i].m);
+ }
}
if (opt->p) {
nopt->p_alloc = opt->p;
nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
- * U(opt->p));
+ * (opt->p));
if (!nopt->h) goto oom;
- memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * U(opt->p));
+ memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p));
+ for (i = 0; i < opt->p; ++i) nopt->h[i].tol = NULL;
+ if (munge)
+ for (i = 0; i < opt->p; ++i)
+ if (nopt->h[i].f_data &&
+ !(nopt->h[i].f_data
+ = munge(nopt->h[i].f_data)))
+ goto oom;
+ for (i = 0; i < opt->p; ++i)
+ if (opt->h[i].tol) {
+ nopt->h[i].tol = (double *) malloc(sizeof(double)
+ * nopt->h[i].m);
+ if (!nopt->h[i].tol) goto oom;
+ memcpy(nopt->h[i].tol, opt->h[i].tol,
+ sizeof(double) * nopt->h[i].m);
+ }
}
if (opt->local_opt) {
}
if (opt->dx) {
- nopt->dx = (double *) malloc(sizeof(double) * U(opt->n));
+ nopt->dx = (double *) malloc(sizeof(double) * (opt->n));
if (!nopt->dx) goto oom;
- memcpy(nopt->dx, opt->dx, sizeof(double) * U(opt->n));
+ memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n));
}
}
return nopt;
oom:
+ nopt->munge_on_destroy = NULL; /* better to leak mem than crash */
nlopt_destroy(nopt);
return NULL;
}
/*************************************************************************/
-nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data)
+nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt,
+ nlopt_func f,
+ nlopt_precond pre,
+ void *f_data)
{
- if (opt && f) {
- opt->f = f; opt->f_data = f_data;
+ if (opt) {
+ nlopt_unset_errmsg(opt);
+ if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data);
+ opt->f = f; opt->f_data = f_data; opt->pre = pre;
+ opt->maximize = 0;
+ if (nlopt_isinf(opt->stopval) && opt->stopval > 0)
+ opt->stopval = -HUGE_VAL; /* switch default from max to min */
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
}
-/*************************************************************************/
+nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt,
+ nlopt_func f, void *f_data)
+{
+ return nlopt_set_precond_min_objective(opt, f, NULL, f_data);
+}
-nlopt_result nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)
+nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt,
+ nlopt_func f,
+ nlopt_precond pre,
+ void *f_data)
{
if (opt) {
- memcpy(opt->lb, lb, sizeof(double) * U(opt->n));
+ nlopt_unset_errmsg(opt);
+ if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data);
+ opt->f = f; opt->f_data = f_data; opt->pre = pre;
+ opt->maximize = 1;
+ if (nlopt_isinf(opt->stopval) && opt->stopval < 0)
+ opt->stopval = +HUGE_VAL; /* switch default from min to max */
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
}
-nlopt_result nlopt_set_lower_bounds1(nlopt_opt opt, double lb)
+nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt,
+ nlopt_func f, void *f_data)
{
- if (opt) {
- int i;
+ return nlopt_set_precond_max_objective(opt, f, NULL, f_data);
+}
+
+/*************************************************************************/
+
+nlopt_result
+NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)
+{
+ nlopt_unset_errmsg(opt);
+ if (opt && (opt->n == 0 || lb)) {
+ unsigned int i;
+ memcpy(opt->lb, lb, sizeof(double) * (opt->n));
for (i = 0; i < opt->n; ++i)
- opt->lb[i] = lb;
+ if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
+ opt->lb[i] = opt->ub[i];
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
}
-nlopt_result nlopt_set_upper_bounds(nlopt_opt opt, const double *ub)
+nlopt_result
+NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb)
{
+ nlopt_unset_errmsg(opt);
if (opt) {
- memcpy(opt->ub, ub, sizeof(double) * U(opt->n));
+ unsigned i;
+ for (i = 0; i < opt->n; ++i) {
+ opt->lb[i] = lb;
+ if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
+ opt->lb[i] = opt->ub[i];
+ }
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
}
-nlopt_result nlopt_set_upper_bounds1(nlopt_opt opt, double ub)
+nlopt_result
+NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb)
{
- if (opt) {
- int i;
+ nlopt_unset_errmsg(opt);
+ if (opt && (opt->n == 0 || lb)) {
+ memcpy(lb, opt->lb, sizeof(double) * (opt->n));
+ return NLOPT_SUCCESS;
+ }
+ return NLOPT_INVALID_ARGS;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub)
+{
+ nlopt_unset_errmsg(opt);
+ if (opt && (opt->n == 0 || ub)) {
+ unsigned int i;
+ memcpy(opt->ub, ub, sizeof(double) * (opt->n));
for (i = 0; i < opt->n; ++i)
- opt->ub[i] = ub;
+ if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
+ opt->ub[i] = opt->lb[i];
+ return NLOPT_SUCCESS;
+ }
+ return NLOPT_INVALID_ARGS;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub)
+{
+ nlopt_unset_errmsg(opt);
+ if (opt) {
+ unsigned i;
+ for (i = 0; i < opt->n; ++i) {
+ opt->ub[i] = ub;
+ if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
+ opt->ub[i] = opt->lb[i];
+ }
+ return NLOPT_SUCCESS;
+ }
+ return NLOPT_INVALID_ARGS;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub)
+{
+ nlopt_unset_errmsg(opt);
+ if (opt && (opt->n == 0 || ub)) {
+ memcpy(ub, opt->ub, sizeof(double) * (opt->n));
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
/*************************************************************************/
-#define AUGLAG_ALG(a) ((a) == NLOPT_LN_AUGLAG || \
+#define AUGLAG_ALG(a) ((a) == NLOPT_AUGLAG || \
+ (a) == NLOPT_AUGLAG_EQ || \
+ (a) == NLOPT_LN_AUGLAG || \
(a) == NLOPT_LN_AUGLAG_EQ || \
(a) == NLOPT_LD_AUGLAG || \
(a) == NLOPT_LD_AUGLAG_EQ)
-nlopt_result nlopt_remove_inequality_constraints(nlopt_opt opt)
+nlopt_result
+NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt)
{
+ unsigned i;
+ nlopt_unset_errmsg(opt);
+ if (!opt) return NLOPT_INVALID_ARGS;
+ if (opt->munge_on_destroy) {
+ nlopt_munge munge = opt->munge_on_destroy;
+ for (i = 0; i < opt->m; ++i)
+ munge(opt->fc[i].f_data);
+ }
+ for (i = 0; i < opt->m; ++i)
+ free(opt->fc[i].tol);
free(opt->fc);
opt->fc = NULL;
opt->m = opt->m_alloc = 0;
return NLOPT_SUCCESS;
}
-static nlopt_result add_constraint(int *m, int *m_alloc,
+static nlopt_result add_constraint(nlopt_opt opt,
+ unsigned *m, unsigned *m_alloc,
nlopt_constraint **c,
- nlopt_func fc, void *fc_data,
- double tol)
+ unsigned fm, nlopt_func fc, nlopt_mfunc mfc,
+ nlopt_precond pre,
+ void *fc_data,
+ const double *tol)
{
+ double *tolcopy;
+ unsigned i;
+
+ if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc))
+ return NLOPT_INVALID_ARGS;
+ if (tol)
+ for (i = 0; i < fm; ++i) if (tol[i] < 0)
+ return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance");
+
+ tolcopy = (double *) malloc(sizeof(double) * fm);
+ if (fm && !tolcopy) return NLOPT_OUT_OF_MEMORY;
+ if (tol)
+ memcpy(tolcopy, tol, sizeof(double) * fm);
+ else
+ for (i = 0; i < fm; ++i) tolcopy[i] = 0;
+
*m += 1;
if (*m > *m_alloc) {
/* allocate by repeated doubling so that
*m_alloc = 2 * (*m);
*c = (nlopt_constraint *) realloc(*c,
sizeof(nlopt_constraint)
- * U(*m_alloc));
+ * (*m_alloc));
if (!*c) {
*m_alloc = *m = 0;
+ free(tolcopy);
return NLOPT_OUT_OF_MEMORY;
}
}
+ (*c)[*m - 1].m = fm;
(*c)[*m - 1].f = fc;
+ (*c)[*m - 1].pre = pre;
+ (*c)[*m - 1].mf = mfc;
(*c)[*m - 1].f_data = fc_data;
- (*c)[*m - 1].tol = tol;
+ (*c)[*m - 1].tol = tolcopy;
return NLOPT_SUCCESS;
}
-nlopt_result nlopt_add_inequality_constraint(nlopt_opt opt,
- nlopt_func fc, void *fc_data,
- double tol)
-{
- if (opt && fc && tol >= 0) {
- /* nonlinear constraints are only supported with some algorithms */
- if (opt->algorithm != NLOPT_LD_MMA
- && opt->algorithm != NLOPT_LN_COBYLA
- && !AUGLAG_ALG(opt->algorithm)
- && opt->algorithm != NLOPT_GN_ISRES)
- return NLOPT_INVALID_ARGS;
+static int inequality_ok(nlopt_algorithm algorithm) {
+ /* nonlinear constraints are only supported with some algorithms */
+ return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ
+ || algorithm == NLOPT_LD_SLSQP
+ || algorithm == NLOPT_LN_COBYLA
+ || AUGLAG_ALG(algorithm)
+ || algorithm == NLOPT_GN_ISRES
+ || algorithm == NLOPT_GN_ORIG_DIRECT
+ || algorithm == NLOPT_GN_ORIG_DIRECT_L);
+}
- return add_constraint(&opt->m, &opt->m_alloc, &opt->fc,
- fc, fc_data, tol);
+nlopt_result
+NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m,
+ nlopt_mfunc fc, void *fc_data,
+ const double *tol)
+{
+ nlopt_result ret;
+ nlopt_unset_errmsg(opt);
+ if (!m) { /* empty constraints are always ok */
+ if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data);
+ return NLOPT_SUCCESS;
}
- return NLOPT_INVALID_ARGS;
+ if (!opt) ret = NLOPT_INVALID_ARGS;
+ else if (!inequality_ok(opt->algorithm))
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
+ else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc,
+ m, NULL, fc, NULL, fc_data, tol);
+ if (ret < 0 && opt && opt->munge_on_destroy)
+ opt->munge_on_destroy(fc_data);
+ return ret;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt,
+ nlopt_func fc,
+ nlopt_precond pre,
+ void *fc_data,
+ double tol)
+{
+ nlopt_result ret;
+ nlopt_unset_errmsg(opt);
+ if (!opt) ret = NLOPT_INVALID_ARGS;
+ else if (!inequality_ok(opt->algorithm))
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
+ else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc,
+ 1, fc, NULL, pre, fc_data, &tol);
+ if (ret < 0 && opt && opt->munge_on_destroy)
+ opt->munge_on_destroy(fc_data);
+ return ret;
}
-nlopt_result nlopt_remove_equality_constraints(nlopt_opt opt)
+nlopt_result
+NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt,
+ nlopt_func fc, void *fc_data,
+ double tol)
{
+ return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data,
+ tol);
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt)
+{
+ unsigned i;
+ nlopt_unset_errmsg(opt);
+ if (!opt) return NLOPT_INVALID_ARGS;
+ if (opt->munge_on_destroy) {
+ nlopt_munge munge = opt->munge_on_destroy;
+ for (i = 0; i < opt->p; ++i)
+ munge(opt->h[i].f_data);
+ }
+ for (i = 0; i < opt->p; ++i)
+ free(opt->h[i].tol);
free(opt->h);
opt->h = NULL;
opt->p = opt->p_alloc = 0;
return NLOPT_SUCCESS;
}
-nlopt_result nlopt_add_equality_constraint(nlopt_opt opt,
- nlopt_func h, void *h_data,
- double tol)
-{
- if (opt && h && tol >= 0) {
- /* equality constraints (h(x) = 0) only via some algorithms */
- if (!AUGLAG_ALG(opt->algorithm) && opt->algorithm != NLOPT_GN_ISRES)
- return NLOPT_INVALID_ARGS;
+static int equality_ok(nlopt_algorithm algorithm) {
+ /* equality constraints (h(x) = 0) only via some algorithms */
+ return (AUGLAG_ALG(algorithm)
+ || algorithm == NLOPT_LD_SLSQP
+ || algorithm == NLOPT_GN_ISRES
+ || algorithm == NLOPT_LN_COBYLA);
+}
- return add_constraint(&opt->p, &opt->p_alloc, &opt->h,
- h, h_data, tol);
+nlopt_result
+NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m,
+ nlopt_mfunc fc, void *fc_data,
+ const double *tol)
+{
+ nlopt_result ret;
+ nlopt_unset_errmsg(opt);
+ if (!m) { /* empty constraints are always ok */
+ if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data);
+ return NLOPT_SUCCESS;
}
- return NLOPT_INVALID_ARGS;
+ if (!opt) ret = NLOPT_INVALID_ARGS;
+ else if (!equality_ok(opt->algorithm))
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
+ else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n)
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
+ else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h,
+ m, NULL, fc, NULL, fc_data, tol);
+ if (ret < 0 && opt && opt->munge_on_destroy)
+ opt->munge_on_destroy(fc_data);
+ return ret;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt,
+ nlopt_func fc,
+ nlopt_precond pre,
+ void *fc_data,
+ double tol)
+{
+ nlopt_result ret;
+ nlopt_unset_errmsg(opt);
+ if (!opt) ret = NLOPT_INVALID_ARGS;
+ else if (!equality_ok(opt->algorithm))
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
+ else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n)
+ ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
+ else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h,
+ 1, fc, NULL, pre, fc_data, &tol);
+ if (ret < 0 && opt && opt->munge_on_destroy)
+ opt->munge_on_destroy(fc_data);
+ return ret;
+}
+
+nlopt_result
+NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt,
+ nlopt_func fc, void *fc_data,
+ double tol)
+{
+ return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol);
}
/*************************************************************************/
-#define SET(param, T, arg) \
- nlopt_result nlopt_set_##param(nlopt_opt opt, T arg) \
- { \
- if (opt) { \
- opt->arg = arg; \
- return NLOPT_SUCCESS; \
- } \
- return NLOPT_INVALID_ARGS; \
+#define SET(param, T, arg) \
+ nlopt_result NLOPT_STDCALL nlopt_set_##param(nlopt_opt opt, T arg) \
+ { \
+ if (opt) { \
+ nlopt_unset_errmsg(opt); \
+ opt->arg = arg; \
+ return NLOPT_SUCCESS; \
+ } \
+ return NLOPT_INVALID_ARGS; \
}
-#define GET(param, T, arg) T nlopt_get_##param(const nlopt_opt opt) { \
- return opt->arg; \
+#define GET(param, T, arg) T NLOPT_STDCALL \
+ nlopt_get_##param(const nlopt_opt opt) { \
+ return opt->arg; \
}
#define GETSET(param, T, arg) GET(param, T, arg) SET(param, T, arg)
-GETSET(stopval, double, minf_max)
+GETSET(stopval, double, stopval)
GETSET(ftol_rel, double, ftol_rel)
GETSET(ftol_abs, double, ftol_abs)
GETSET(xtol_rel, double, xtol_rel)
-nlopt_result nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs)
+nlopt_result
+NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs)
{
if (opt) {
- memcpy(opt->xtol_abs, xtol_abs, opt->n & sizeof(double));
+ nlopt_unset_errmsg(opt);
+ memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double));
return NLOPT_SUCCESS;
}
return NLOPT_INVALID_ARGS;
}
-nlopt_result nlopt_set_xtol_abs1(nlopt_opt opt, const double xtol_abs)
+nlopt_result
+NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs)
{
if (opt) {
- int i;
+ unsigned i;
+ nlopt_unset_errmsg(opt);
for (i = 0; i < opt->n; ++i)
opt->xtol_abs[i] = xtol_abs;
return NLOPT_SUCCESS;
return NLOPT_INVALID_ARGS;
}
-void nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs)
+nlopt_result
+NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs)
{
- memcpy(xtol_abs, opt->xtol_abs, opt->n & sizeof(double));
+ memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double));
+ return NLOPT_SUCCESS;
}
GETSET(maxeval, int, maxeval)
/*************************************************************************/
-nlopt_result nlopt_set_local_optimizer(nlopt_opt opt,
- const nlopt_opt local_opt)
+nlopt_result
+NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop)
+{
+ if (opt) {
+ nlopt_unset_errmsg(opt);
+ opt->force_stop = force_stop;
+ if (opt->force_stop_child)
+ return nlopt_set_force_stop(opt->force_stop_child, force_stop);
+ return NLOPT_SUCCESS;
+ }
+ return NLOPT_INVALID_ARGS;
+}
+
+GET(force_stop, int, force_stop)
+nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt) {
+ return nlopt_set_force_stop(opt, 1);
+}
+
+/*************************************************************************/
+
+GET(algorithm, nlopt_algorithm, algorithm)
+GET(dimension, unsigned, n)
+
+/*************************************************************************/
+
+nlopt_result
+NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt,
+ const nlopt_opt local_opt)
{
if (opt) {
- if (local_opt && local_opt->n != opt->n) return NLOPT_INVALID_ARGS;
+ nlopt_unset_errmsg(opt);
+ if (local_opt && local_opt->n != opt->n)
+ return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer");
nlopt_destroy(opt->local_opt);
opt->local_opt = nlopt_copy(local_opt);
if (local_opt) {
nlopt_set_upper_bounds(opt->local_opt, opt->ub);
nlopt_remove_inequality_constraints(opt->local_opt);
nlopt_remove_equality_constraints(opt->local_opt);
+ nlopt_set_min_objective(opt->local_opt, NULL, NULL);
+ nlopt_set_munge(opt->local_opt, NULL, NULL);
+ opt->local_opt->force_stop = 0;
}
return NLOPT_SUCCESS;
}
/*************************************************************************/
-GETSET(population, int, stochastic_population)
+GETSET(population, unsigned, stochastic_population)
+GETSET(vector_storage, unsigned, vector_storage)
/*************************************************************************/
-nlopt_result nlopt_set_initial_step1(nlopt_opt opt, double dx)
+nlopt_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx)
{
- int i;
- if (!opt || dx == 0) return NLOPT_INVALID_ARGS;
+ unsigned i;
+ if (!opt) return NLOPT_INVALID_ARGS;
+ nlopt_unset_errmsg(opt);
+ if (dx == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
if (!opt->dx && opt->n > 0) {
- opt->dx = (double *) malloc(sizeof(double) * U(opt->n));
+ opt->dx = (double *) malloc(sizeof(double) * (opt->n));
if (!opt->dx) return NLOPT_OUT_OF_MEMORY;
}
for (i = 0; i < opt->n; ++i) opt->dx[i] = dx;
return NLOPT_SUCCESS;
}
-nlopt_result nlopt_set_initial_step(nlopt_opt opt, const double *dx)
+nlopt_result
+NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx)
{
- int i;
- if (!opt || !dx) return NLOPT_INVALID_ARGS;
- for (i = 0; i < opt->n; ++i) if (dx[i] == 0) return NLOPT_INVALID_ARGS;
+ unsigned i;
+ if (!opt) return NLOPT_INVALID_ARGS;
+ nlopt_unset_errmsg(opt);
+ if (!dx) {
+ free(opt->dx); opt->dx = NULL;
+ return NLOPT_SUCCESS;
+ }
+ for (i = 0; i < opt->n; ++i)
+ if (dx[i] == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY)
return NLOPT_OUT_OF_MEMORY;
- memcpy(opt->dx, dx, sizeof(double) * U(opt->n));
+ memcpy(opt->dx, dx, sizeof(double) * (opt->n));
return NLOPT_SUCCESS;
}
-nlopt_result nlopt_get_initial_step(nlopt_opt opt, const double *x, double *dx)
+nlopt_result
+NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x,
+ double *dx)
{
if (!opt) return NLOPT_INVALID_ARGS;
+ nlopt_unset_errmsg(opt);
if (!opt->n) return NLOPT_SUCCESS;
if (!opt->dx) {
- nlopt_result ret = nlopt_set_default_initial_step(opt, x);
+ nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */
+ nlopt_result ret = nlopt_set_default_initial_step(o, x);
if (ret != NLOPT_SUCCESS) return ret;
- memcpy(dx, opt->dx, sizeof(double) * U(opt->n));
- free(opt->dx); opt->dx = NULL; /* don't save, since x-dependent */
+ memcpy(dx, o->dx, sizeof(double) * (opt->n));
+ free(o->dx); o->dx = NULL; /* don't save, since x-dependent */
}
else
- memcpy(dx, opt->dx, sizeof(double) * U(opt->n));
+ memcpy(dx, opt->dx, sizeof(double) * (opt->n));
return NLOPT_SUCCESS;
}
-nlopt_result nlopt_set_default_initial_step(nlopt_opt opt, const double *x)
+nlopt_result
+NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x)
{
const double *lb, *ub;
- int i;
+ unsigned i;
+ nlopt_unset_errmsg(opt);
if (!opt || !x) return NLOPT_INVALID_ARGS;
lb = opt->lb; ub = opt->ub;
&& fabs(x[i] - lb[i]) < fabs(step))
step = (x[i] - lb[i]) * 1.1;
}
- if (nlopt_isinf(step) || step == 0) {
- step = fabs(x[i]) * 0.25;
+ if (nlopt_isinf(step) || nlopt_istiny(step)) {
+ step = x[i];
}
- if (nlopt_isinf(step) || step == 0)
+ if (nlopt_isinf(step) || step == 0.0)
step = 1;
opt->dx[i] = step;
}
/*************************************************************************/
+
+void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt,
+ nlopt_munge munge_on_destroy,
+ nlopt_munge munge_on_copy) {
+ if (opt) {
+ opt->munge_on_destroy = munge_on_destroy;
+ opt->munge_on_copy = munge_on_copy;
+ }
+}
+
+void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt,
+ nlopt_munge2 munge, void *data) {
+ if (opt && munge) {
+ unsigned i;
+ opt->f_data = munge(opt->f_data, data);
+ for (i = 0; i < opt->m; ++i)
+ opt->fc[i].f_data = munge(opt->fc[i].f_data, data);
+ for (i = 0; i < opt->p; ++i)
+ opt->h[i].f_data = munge(opt->h[i].f_data, data);
+ }
+}
+
+/*************************************************************************/
+
+const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ opt->errmsg = nlopt_vsprintf(opt->errmsg, format, ap);
+ va_end(ap);
+ return opt->errmsg;
+}
+
+void nlopt_unset_errmsg(nlopt_opt opt)
+{
+ if (opt) {
+ free(opt->errmsg);
+ opt->errmsg = NULL;
+ }
+}
+
+const char *nlopt_get_errmsg(nlopt_opt opt)
+{
+ return opt->errmsg;
+}
+
+/*************************************************************************/