#include "nlopt-internal.h"
+#define ERR(err, opt, msg) (nlopt_set_errmsg(opt, msg) ? err : err)
+
/*************************************************************************/
void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt)
void *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;
void *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 = 1;
nlopt_result
NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)
{
+ nlopt_unset_errmsg(opt);
if (opt && (opt->n == 0 || lb)) {
+ int i;
memcpy(opt->lb, lb, sizeof(double) * (opt->n));
+ for (i = 0; i < opt->n; ++i)
+ 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_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb)
{
+ nlopt_unset_errmsg(opt);
if (opt) {
unsigned i;
for (i = 0; i < opt->n; ++i)
- opt->lb[i] = lb;
+ 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_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb)
{
+ nlopt_unset_errmsg(opt);
if (opt && (opt->n == 0 || lb)) {
memcpy(lb, opt->lb, sizeof(double) * (opt->n));
return NLOPT_SUCCESS;
nlopt_result
NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub)
{
+ nlopt_unset_errmsg(opt);
if (opt && (opt->n == 0 || ub)) {
+ int i;
memcpy(opt->ub, ub, sizeof(double) * (opt->n));
+ for (i = 0; i < opt->n; ++i)
+ 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;
+ 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;
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;
return NLOPT_SUCCESS;
}
-static nlopt_result add_constraint(unsigned *m, unsigned *m_alloc,
+static nlopt_result add_constraint(nlopt_opt opt,
+ unsigned *m, unsigned *m_alloc,
nlopt_constraint **c,
unsigned fm, nlopt_func fc, nlopt_mfunc mfc,
nlopt_precond pre,
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 NLOPT_INVALID_ARGS;
-
+ 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)
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;
}
- if (!opt || !inequality_ok(opt->algorithm)) ret = NLOPT_INVALID_ARGS;
- else ret = add_constraint(&opt->m, &opt->m_alloc, &opt->fc,
+ 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);
double tol)
{
nlopt_result ret;
- if (!opt || !inequality_ok(opt->algorithm)) ret = NLOPT_INVALID_ARGS;
- else ret = add_constraint(&opt->m, &opt->m_alloc, &opt->fc,
+ 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);
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;
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;
}
- if (!opt || !equality_ok(opt->algorithm)
- || nlopt_count_constraints(opt->p, opt->h) + m > opt->n)
- ret = NLOPT_INVALID_ARGS;
- else ret = add_constraint(&opt->p, &opt->p_alloc, &opt->h,
+ 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);
double tol)
{
nlopt_result ret;
- if (!opt || !equality_ok(opt->algorithm)
- || nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n)
- ret = NLOPT_INVALID_ARGS;
- else ret = add_constraint(&opt->p, &opt->p_alloc, &opt->h,
+ 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);
nlopt_result NLOPT_STDCALL nlopt_set_##param(nlopt_opt opt, T arg) \
{ \
if (opt) { \
+ nlopt_unset_errmsg(opt); \
opt->arg = arg; \
return NLOPT_SUCCESS; \
} \
NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs)
{
if (opt) {
+ nlopt_unset_errmsg(opt);
memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double));
return NLOPT_SUCCESS;
}
{
if (opt) {
unsigned i;
+ nlopt_unset_errmsg(opt);
for (i = 0; i < opt->n; ++i)
opt->xtol_abs[i] = xtol_abs;
return NLOPT_SUCCESS;
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);
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_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx)
{
unsigned i;
- if (!opt || dx == 0) return NLOPT_INVALID_ARGS;
+ 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) * (opt->n));
if (!opt->dx) return NLOPT_OUT_OF_MEMORY;
{
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 NLOPT_INVALID_ARGS;
+ 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) * (opt->n));
double *dx)
{
if (!opt) return NLOPT_INVALID_ARGS;
+ nlopt_unset_errmsg(opt);
if (!opt->n) return NLOPT_SUCCESS;
if (!opt->dx) {
nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */
const double *lb, *ub;
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) {
+ 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_unset_errmsg(nlopt_opt opt)
{
- free(opt->errmsg);
- opt->errmsg = NULL;
+ if (opt) {
+ free(opt->errmsg);
+ opt->errmsg = NULL;
+ }
}
const char *nlopt_get_errmsg(nlopt_opt opt)
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#ifndef HAVE_ISNAN
-static int my_isnan(double x) { return x != x; }
-# define isnan my_isnan
-#endif
-
/* magic minimum value for rho in MMA ... the 2002 paper says it should
be a "fixed, strictly positive `small' number, e.g. 1e-5"
... grrr, I hate these magic numbers, which seem like they
val = d->gval = fval;
d->wval = 0;
for (i = 0; i < m; ++i)
- val += y[i] * (gcval[i] = isnan(fcval[i]) ? 0 : fcval[i]);
+ val += y[i] * (gcval[i] = nlopt_isnan(fcval[i]) ? 0 : fcval[i]);
for (j = 0; j < n; ++j) {
double u, v, dx, denominv, c, sigma2, dx2;
u = dfdx[j];
v = fabs(dfdx[j]) * sigma[j] + 0.5 * rho;
- for (i = 0; i < m; ++i) if (!isnan(fcval[i])) {
+ for (i = 0; i < m; ++i) if (!nlopt_isnan(fcval[i])) {
u += dfcdx[i*n + j] * y[i];
v += (fabs(dfcdx[i*n + j]) * sigma[j] + 0.5 * rhoc[i]) * y[i];
}
d->gval += (dfdx[j] * c + (fabs(dfdx[j])*sigma[j] + 0.5*rho) * dx2)
* denominv;
d->wval += 0.5 * dx2 * denominv;
- for (i = 0; i < m; ++i) if (!isnan(fcval[i]))
+ for (i = 0; i < m; ++i) if (!nlopt_isnan(fcval[i]))
gcval[i] += (dfcdx[i*n+j] * c + (fabs(dfcdx[i*n+j])*sigma[j]
+ 0.5*rhoc[i]) * dx2)
* denominv;
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]));
+ feasible = feasible && (fcval[i] <= 0 || nlopt_isnan(fcval[i]));
if (fcval[i] > infeasibility) infeasibility = fcval[i];
}
/* For non-feasible initial points, set a finite (large)
for (i = ifc = 0; ifc < mfc; ++ifc) {
unsigned i0 = i, inext = i + fc[ifc].m;
for (; i < inext; ++i)
- if (!isnan(fcval_cur[i])) {
+ if (!nlopt_isnan(fcval_cur[i])) {
feasible_cur = feasible_cur
&& (fcval_cur[i] <= fc[ifc].tol[i-i0]);
- if (!isnan(fcval[i]))
+ if (!nlopt_isnan(fcval[i]))
inner_done = inner_done &&
(dd.gcval[i] >= fcval_cur[i]);
else if (fcval_cur[i] > 0)
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])
+ if (!nlopt_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])