#include <vector>
#include <stdexcept>
#include <new>
+#include <cstdlib>
// convenience overloading for below (not in nlopt:: since has nlopt_ prefix)
inline nlopt_result nlopt_get_initial_step(const nlopt_opt opt, double *dx) {
// GEN_ENUMS_HERE
//////////////////////////////////////////////////////////////////////
- // virtual base class for objective function and constraints:
- class func {
- public:
- // should return function value, and set grad to gradient
- // (x and grad are length n)
- virtual double operator()(unsigned n, const double *x, double *grad) = 0;
-
- // should return function value (x is length n)
- virtual double operator()(unsigned n, const double *x) = 0;
- };
+ typedef nlopt_func func; // nlopt::func synoynm
- // (Note: it is inefficient to use std::vector<double> for the arguments,
- // since that would require a copy to be made of NLopt's double* data.)
+ // alternative to nlopt_func that takes std::vector<double>
+ // but no data pointer ... mostly for SWIG
+ typedef double (*vfunc)(const std::vector<double> &x,
+ std::vector<double> &grad);
//////////////////////////////////////////////////////////////////////
class opt {
private:
nlopt_opt o;
+ bool stopped_by_exception;
void mythrow(nlopt_result ret) const {
switch (ret) {
}
}
- // nlopt_func wrapper around C++ "functional"
- static double myfunc(unsigned n, const double *x, double *grad, void *f_) {
- func *f = reinterpret_cast<func*>(f_);
- return grad ? (*f)(n, x, grad) : (*f)(n, x);
+ typedef struct {
+ opt *o;
+ func f; void *f_data;
+ vfunc vf;
+ } myfunc_data;
+
+ // nlopt_func wrapper that catches exceptions
+ static double myfunc(unsigned n, const double *x, double *grad, void *d_) {
+ myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
+ try {
+ return d->f(n, x, grad, d->f_data);
+ }
+ catch (...) {
+ d->o->stopped_by_exception = true;
+ d->o->force_stop(); // stop gracefully, opt::optimize will re-throw
+ }
+ }
+
+ // nlopt_func wrapper, using std::vector<double>
+ static double myvfunc(unsigned n, const double *x, double *grad, void *d_){
+ myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
+ try {
+ std::vector<double> xv(n);
+ for (unsigned i = 0; i < n; ++i) xv[i] = x[i];
+ std::vector<double> gradv(grad ? n : 0);
+ double val = d->vf(xv, gradv);
+ if (grad) for (unsigned i = 0; i < n; ++i) grad[i] = gradv[i];
+ return val;
+ }
+ catch (...) {
+ d->o->stopped_by_exception = true;
+ d->o->force_stop(); // stop gracefully, opt::optimize will re-throw
+ }
}
public:
// Constructors etc.
- opt() : o(NULL) {}
- opt(nlopt_algorithm a, unsigned n) : o(nlopt_create(a, n)) {
+ opt() : o(NULL), stopped_by_exception(false) {}
+ ~opt() { nlopt_destroy(o); }
+ opt(algorithm a, unsigned n) :
+ o(nlopt_create(nlopt_algorithm(a), n)), stopped_by_exception(false) {
if (!o) throw std::bad_alloc();
+ nlopt_set_free_f_data(o, 1);
}
- opt(algorithm a, unsigned n) : o(nlopt_create(nlopt_algorithm(a), n)) {
+ void reinit(algorithm a, unsigned n) {
+ if (o) nlopt_destroy(o);
+ o = nlopt_create(nlopt_algorithm(a), n);
if (!o) throw std::bad_alloc();
+ nlopt_set_free_f_data(o, 1);
}
- opt(const nlopt_opt o0) : o(nlopt_copy(o0)) {
- if (o0 && !o) throw std::bad_alloc();
- }
- ~opt() { nlopt_destroy(o); }
opt(const opt& from) : o(nlopt_copy(from.o)) {
if (from.o && !o) throw std::bad_alloc();
+ mythrow(nlopt_dup_f_data(o, sizeof(myfunc_data)));
}
opt& operator=(opt const& f) {
if (this == &f) return *this; // self-assignment
nlopt_destroy(o);
o = nlopt_copy(f.o);
if (f.o && !o) throw std::bad_alloc();
+ mythrow(nlopt_dup_f_data(o, sizeof(myfunc_data)));
return *this;
}
// Do the optimization:
- result optimize(double *x, double &opt_f) {
- nlopt_result ret = nlopt_optimize(o, x, &opt_f);
- mythrow(ret);
- return result(ret);
- }
result optimize(std::vector<double> &x, double &opt_f) {
if (o && nlopt_get_dimension(o) != x.size())
throw std::invalid_argument("dimension mismatch");
- return optimize(x.empty() ? NULL : &x[0], opt_f);
+ stopped_by_exception = false;
+ nlopt_result ret = nlopt_optimize(o, x.empty() ? NULL : &x[0], &opt_f);
+ if (ret == NLOPT_FORCED_STOP && stopped_by_exception)
+ throw; // re-throw last-caught exception
+ mythrow(ret);
+ return result(ret);
}
// accessors:
}
// Set the objective function
- void set_min_objective(nlopt_func f, void *f_data) {
- nlopt_result ret = nlopt_set_min_objective(o, f, f_data);
- mythrow(ret);
+ void set_min_objective(func f, void *f_data) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = f; d->f_data = f_data; d->vf = NULL;
+ mythrow(nlopt_set_min_objective(o, myfunc, d)); // d freed via o
}
- void set_min_objective(func *f) {
- set_min_objective(myfunc, f);
+ void set_min_objective(vfunc vf) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = NULL; d->f_data = NULL; d->vf = vf;
+ mythrow(nlopt_set_min_objective(o, myvfunc, d)); // d freed via o
}
- void set_max_objective(nlopt_func f, void *f_data) {
- nlopt_result ret = nlopt_set_max_objective(o, f, f_data);
- mythrow(ret);
+ void set_max_objective(func f, void *f_data) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = f; d->f_data = f_data; d->vf = NULL;
+ mythrow(nlopt_set_max_objective(o, myfunc, d)); // d freed via o
}
- void set_max_objective(func *f) {
- set_max_objective(myfunc, f);
+ void set_max_objective(vfunc vf) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = NULL; d->f_data = NULL; d->vf = vf;
+ mythrow(nlopt_set_max_objective(o, myvfunc, d)); // d freed via o
}
// Nonlinear constraints:
nlopt_result ret = nlopt_remove_inequality_constraints(o);
mythrow(ret);
}
- void add_inequality_constraint(nlopt_func f, void *f_data, double tol=0) {
- nlopt_result ret = nlopt_add_inequality_constraint(o, f, f_data, tol);
- mythrow(ret);
+ void add_inequality_constraint(func f, void *f_data, double tol=0) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = f; d->f_data = f_data; d->vf = NULL;
+ mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol));
}
- void add_inequality_constraint(func *f, double tol=0) {
- add_inequality_constraint(myfunc, f, tol);
+ void add_inequality_constraint(vfunc vf, double tol=0) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = NULL; d->f_data = NULL; d->vf = vf;
+ mythrow(nlopt_add_inequality_constraint(o, myvfunc, d, tol));
}
void remove_equality_constraints(void) {
nlopt_result ret = nlopt_remove_equality_constraints(o);
mythrow(ret);
}
- void add_equality_constraint(nlopt_func f, void *f_data, double tol=0) {
- nlopt_result ret = nlopt_add_equality_constraint(o, f, f_data, tol);
- mythrow(ret);
+ void add_equality_constraint(func f, void *f_data, double tol=0) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = f; d->f_data = f_data; d->vf = NULL;
+ mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol));
}
- void add_equality_constraint(func *f, double tol=0) {
- add_equality_constraint(myfunc, f, tol);
+ void add_equality_constraint(vfunc vf, double tol=0) {
+ myfunc_data *d = (myfunc_data *) std::malloc(sizeof(myfunc_data));
+ if (!d) throw std::bad_alloc();
+ d->o = this; d->f = NULL; d->f_data = NULL; d->vf = vf;
+ mythrow(nlopt_add_equality_constraint(o, myvfunc, d, tol));
}
#define NLOPT_GETSET_VEC(name) \
- void get_##name(double *v) const { \
- nlopt_result ret = nlopt_get_##name(o, v); \
- mythrow(ret); \
- } \
- void set_##name(const double *v) { \
- nlopt_result ret = nlopt_set_##name(o, v); \
- mythrow(ret); \
- } \
void set_##name(double val) { \
nlopt_result ret = nlopt_set_##name##1(o, val); \
mythrow(ret); \
void get_##name(std::vector<double> &v) const { \
if (o && nlopt_get_dimension(o) != v.size()) \
throw std::invalid_argument("dimension mismatch"); \
- get_##name(v.empty() ? NULL : &v[0]); \
+ nlopt_result ret = nlopt_get_##name(o, v.empty() ? NULL : &v[0]); \
+ mythrow(ret); \
} \
std::vector<double> get_##name(void) const { \
if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
void set_##name(const std::vector<double> &v) { \
if (o && nlopt_get_dimension(o) != v.size()) \
throw std::invalid_argument("dimension mismatch"); \
- set_##name(v.empty() ? NULL : &v[0]); \
+ nlopt_result ret = nlopt_set_##name(o, v.empty() ? NULL : &v[0]); \
+ mythrow(ret); \
}
NLOPT_GETSET_VEC(lower_bounds)
// algorithm-specific parameters:
- void set_local_optimizer(const nlopt_opt lo) {
- nlopt_result ret = nlopt_set_local_optimizer(o, lo);
- mythrow(ret);
- }
void set_local_optimizer(const opt &lo) {
- set_local_optimizer(lo.o);
+ nlopt_result ret = nlopt_set_local_optimizer(o, lo.o);
+ mythrow(ret);
}
NLOPT_GETSET(unsigned, population)
NLOPT_GETSET_VEC(initial_step)
- void set_default_initial_step(const double *x) {
- nlopt_result ret = nlopt_set_default_initial_step(o, x);
- mythrow(ret);
- }
void set_default_initial_step(const std::vector<double> &x) {
- set_default_initial_step(x.empty() ? NULL : &x[0]);
- }
- void get_initial_step(const double *x, double *dx) const {
- nlopt_result ret = nlopt_get_initial_step(o, x, dx);
+ nlopt_result ret
+ = nlopt_set_default_initial_step(o, x.empty() ? NULL : &x[0]);
mythrow(ret);
}
void get_initial_step(const std::vector<double> &x, std::vector<double> &dx) const {
if (o && (nlopt_get_dimension(o) != x.size()
|| nlopt_get_dimension(o) != dx.size()))
throw std::invalid_argument("dimension mismatch");
- get_initial_step(x.empty() ? NULL : &x[0],
- dx.empty() ? NULL : &dx[0]);
+ nlopt_result ret = nlopt_get_initial_step(o, x.empty() ? NULL : &x[0],
+ dx.empty() ? NULL : &dx[0]);
+ mythrow(ret);
}
std::vector<double> get_initial_step(const std::vector<double> &x) const {
if (!o) throw std::runtime_error("uninitialized nlopt::opt");
inline void version(int &major, int &minor, int &bugfix) {
nlopt_version(&major, &minor, &bugfix);
}
- inline const char *algorithm_name(nlopt_algorithm a) {
- return nlopt_algorithm_name(a);
- }
inline const char *algorithm_name(algorithm a) {
- return algorithm_name(nlopt_algorithm(a));
+ return nlopt_algorithm_name(nlopt_algorithm(a));
}
//////////////////////////////////////////////////////////////////////
#ifndef NLOPT_H
#define NLOPT_H
-#include <stddef.h> /* for ptrdiff_t */
+#include <stddef.h> /* for ptrdiff_t and size_t */
/* use stdcall convention under Windows, since this seems to
be more standard there and is important for calling from .NET */
/* set to 1: nlopt_destroy should call free() on all of the f_data pointers
(for the objective, constraints, etcetera) ... mainly for internal use */
NLOPT_EXTERN nlopt_result nlopt_set_free_f_data(nlopt_opt opt, int val);
-NLOPT_EXTERN int nlopt_get_free_f_data(nlopt_opt opt);
+NLOPT_EXTERN int nlopt_get_free_f_data(const nlopt_opt opt);
+NLOPT_EXTERN nlopt_result nlopt_dup_f_data(nlopt_opt opt, size_t sz);
/*************************** DEPRECATED API **************************/
/* The new "object-oriented" API is preferred, since it allows us to
+++ /dev/null
-/* Copyright (c) 2007-2010 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
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-// C++ style wrapper around NLopt API
-// nlopt.hpp is AUTOMATICALLY GENERATED from nlopt-in.hpp - edit the latter!
-
-#include <nlopt.h>
-
-#include <vector>
-#include <stdexcept>
-#include <new>
-
-// convenience overloading for below (not in nlopt:: since has nlopt_ prefix)
-inline nlopt_result nlopt_get_initial_step(const nlopt_opt opt, double *dx) {
- return nlopt_get_initial_step(opt, (const double *) NULL, dx);
-}
-
-namespace nlopt {
-
- //////////////////////////////////////////////////////////////////////
- // nlopt::* namespace versions of the C enumerated types
- // AUTOMATICALLY GENERATED, DO NOT EDIT
- // GEN_ENUMS_HERE
- enum algorithm {
- GN_DIRECT = 0,
- GN_DIRECT_L,
- GN_DIRECT_L_RAND,
- GN_DIRECT_NOSCAL,
- GN_DIRECT_L_NOSCAL,
- GN_DIRECT_L_RAND_NOSCAL,
- GN_ORIG_DIRECT,
- GN_ORIG_DIRECT_L,
- GD_STOGO,
- GD_STOGO_RAND,
- LD_LBFGS_NOCEDAL,
- LD_LBFGS,
- LN_PRAXIS,
- LD_VAR1,
- LD_VAR2,
- LD_TNEWTON,
- LD_TNEWTON_RESTART,
- LD_TNEWTON_PRECOND,
- LD_TNEWTON_PRECOND_RESTART,
- GN_CRS2_LM,
- GN_MLSL,
- GD_MLSL,
- GN_MLSL_LDS,
- GD_MLSL_LDS,
- LD_MMA,
- LN_COBYLA,
- LN_NEWUOA,
- LN_NEWUOA_BOUND,
- LN_NELDERMEAD,
- LN_SBPLX,
- LN_AUGLAG,
- LD_AUGLAG,
- LN_AUGLAG_EQ,
- LD_AUGLAG_EQ,
- LN_BOBYQA,
- GN_ISRES,
- NUM_ALGORITHMS /* not an algorithm, just the number of them */
- };
- enum result {
- FAILURE = -1, /* generic failure code */
- INVALID_ARGS = -2,
- OUT_OF_MEMORY = -3,
- ROUNDOFF_LIMITED = -4,
- FORCED_STOP = -5,
- SUCCESS = 1, /* generic success code */
- STOPVAL_REACHED = 2,
- FTOL_REACHED = 3,
- XTOL_REACHED = 4,
- MAXEVAL_REACHED = 5,
- MAXTIME_REACHED = 6
- };
- // GEN_ENUMS_HERE
- //////////////////////////////////////////////////////////////////////
-
- // virtual base class for objective function and constraints:
- class func {
- public:
- // should return function value, and set grad to gradient
- // (x and grad are length n)
- virtual double operator()(unsigned n, const double *x, double *grad) = 0;
-
- // should return function value (x is length n)
- virtual double operator()(unsigned n, const double *x) = 0;
- };
-
- // alternative that uses std::vector<double> for the arguments; note
- // that this is less efficient as it requires a copy to be made
- class vfunc {
- public:
- // should return function value, and set grad to gradient
- // (x and grad are same length n, and length of grad must not be changed)
- virtual double operator()(const std::vector<double> &x,
- std::vector<double> &grad) = 0;
-
- // should return function value (x is length n)
- virtual double operator()(const std::vector<double> &x) = 0;
- };
-
- //////////////////////////////////////////////////////////////////////
-
- // NLopt-specific exceptions (corresponding to error codes):
- class roundoff_limited : public std::runtime_error {
- public:
- roundoff_limited() : std::runtime_error("nlopt roundoff-limited") {}
- };
-
- class forced_stop : public std::runtime_error {
- public:
- forced_stop() : std::runtime_error("nlopt forced stop") {}
- };
-
- //////////////////////////////////////////////////////////////////////
-
- class opt {
- private:
- nlopt_opt o;
-
- void mythrow(nlopt_result ret) const {
- switch (ret) {
- case NLOPT_FAILURE: throw std::runtime_error("nlopt failure");
- case NLOPT_OUT_OF_MEMORY: throw std::bad_alloc();
- case NLOPT_INVALID_ARGS: throw std::invalid_argument("nlopt invalid argument");
- case NLOPT_ROUNDOFF_LIMITED: throw roundoff_limited();
- case NLOPT_FORCED_STOP: throw forced_stop();
- default: break;
- }
- }
-
- // nlopt_func wrapper around C++ "functional"
- static double myfunc(unsigned n, const double *x, double *grad, void *f_) {
- func *f = reinterpret_cast<func*>(f_);
- return grad ? (*f)(n, x, grad) : (*f)(n, x);
- }
-
- // nlopt_func wrapper around C++ "functional", using std::vector<double>
- static double myvfunc(unsigned n, const double *x, double *grad, void *f_){
- func *f = reinterpret_cast<vfunc*>(f_);
- std::vector<double> xv(n);
- for (unsigned i = 0; i < n; ++i) xv[i] = x[i];
- if (grad) {
- std::vector<double> gradv(n);
- double val = (*f)(xv, gradv);
- for (unsigned i = 0; i < n; ++i) grad[i] = gradv[i];
- return val;
- }
- else
- return (*f)(xv);
- }
-
- public:
- // Constructors etc.
- opt() : o(NULL) {}
- opt(nlopt_algorithm a, unsigned n) : o(nlopt_create(a, n)) {
- if (!o) throw std::bad_alloc();
- }
- opt(algorithm a, unsigned n) : o(nlopt_create(nlopt_algorithm(a), n)) {
- if (!o) throw std::bad_alloc();
- }
- opt(const nlopt_opt o0) : o(nlopt_copy(o0)) {
- if (o0 && !o) throw std::bad_alloc();
- }
- ~opt() { nlopt_destroy(o); }
- opt(const opt& from) : o(nlopt_copy(from.o)) {
- if (from.o && !o) throw std::bad_alloc();
- }
- opt& operator=(opt const& f) {
- if (this == &f) return *this; // self-assignment
- nlopt_destroy(o);
- o = nlopt_copy(f.o);
- if (f.o && !o) throw std::bad_alloc();
- return *this;
- }
-
- // Do the optimization:
- result optimize(double *x, double &opt_f) {
- nlopt_result ret = nlopt_optimize(o, x, &opt_f);
- mythrow(ret);
- return result(ret);
- }
- result optimize(std::vector<double> &x, double &opt_f) {
- if (o && nlopt_get_dimension(o) != x.size())
- throw std::invalid_argument("dimension mismatch");
- return optimize(x.empty() ? NULL : &x[0], opt_f);
- }
-
- // accessors:
- algorithm get_algorithm() const {
- if (!o) throw std::runtime_error("uninitialized nlopt::opt");
- return algorithm(nlopt_get_algorithm(o));
- }
- const char *get_algorithm_name() const {
- if (!o) throw std::runtime_error("uninitialized nlopt::opt");
- return nlopt_algorithm_name(nlopt_get_algorithm(o));
- }
- unsigned get_dimension() const {
- if (!o) throw std::runtime_error("uninitialized nlopt::opt");
- return nlopt_get_dimension(o);
- }
-
- // Set the objective function
- void set_min_objective(nlopt_func f, void *f_data) {
- nlopt_result ret = nlopt_set_min_objective(o, f, f_data);
- mythrow(ret);
- }
- void set_min_objective(func *f) {
- set_min_objective(myfunc, f);
- }
- void set_min_objective(vfunc *f) {
- set_min_objective(myvfunc, f);
- }
- void set_max_objective(nlopt_func f, void *f_data) {
- nlopt_result ret = nlopt_set_max_objective(o, f, f_data);
- mythrow(ret);
- }
- void set_max_objective(func *f) {
- set_max_objective(myfunc, f);
- }
- void set_max_objective(vfunc *f) {
- set_max_objective(myvfunc, f);
- }
-
- // Nonlinear constraints:
-
- void remove_inequality_constraints(void) {
- nlopt_result ret = nlopt_remove_inequality_constraints(o);
- mythrow(ret);
- }
- void add_inequality_constraint(nlopt_func f, void *f_data, double tol=0) {
- nlopt_result ret = nlopt_add_inequality_constraint(o, f, f_data, tol);
- mythrow(ret);
- }
- void add_inequality_constraint(func *f, double tol=0) {
- add_inequality_constraint(myfunc, f, tol);
- }
-
- void remove_equality_constraints(void) {
- nlopt_result ret = nlopt_remove_equality_constraints(o);
- mythrow(ret);
- }
- void add_equality_constraint(nlopt_func f, void *f_data, double tol=0) {
- nlopt_result ret = nlopt_add_equality_constraint(o, f, f_data, tol);
- mythrow(ret);
- }
- void add_equality_constraint(func *f, double tol=0) {
- add_equality_constraint(myfunc, f, tol);
- }
-
-#define NLOPT_GETSET_VEC(name) \
- void get_##name(double *v) const { \
- nlopt_result ret = nlopt_get_##name(o, v); \
- mythrow(ret); \
- } \
- void set_##name(const double *v) { \
- nlopt_result ret = nlopt_set_##name(o, v); \
- mythrow(ret); \
- } \
- void set_##name(double val) { \
- nlopt_result ret = nlopt_set_##name##1(o, val); \
- mythrow(ret); \
- } \
- void get_##name(std::vector<double> &v) const { \
- if (o && nlopt_get_dimension(o) != v.size()) \
- throw std::invalid_argument("dimension mismatch"); \
- get_##name(v.empty() ? NULL : &v[0]); \
- } \
- std::vector<double> get_##name(void) const { \
- if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
- std::vector<double> v(nlopt_get_dimension(o)); \
- get_##name(v); \
- return v; \
- } \
- void set_##name(const std::vector<double> &v) { \
- if (o && nlopt_get_dimension(o) != v.size()) \
- throw std::invalid_argument("dimension mismatch"); \
- set_##name(v.empty() ? NULL : &v[0]); \
- }
-
- NLOPT_GETSET_VEC(lower_bounds)
- NLOPT_GETSET_VEC(upper_bounds)
-
- // stopping criteria:
-
-#define NLOPT_GETSET(T, name) \
- T get_##name() const { \
- if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
- return nlopt_get_##name(o); \
- } \
- void set_##name(T name) { \
- nlopt_result ret = nlopt_set_##name(o, name); \
- mythrow(ret); \
- }
- NLOPT_GETSET(double, stopval)
- NLOPT_GETSET(double, ftol_rel)
- NLOPT_GETSET(double, ftol_abs)
- NLOPT_GETSET(double, xtol_rel)
- NLOPT_GETSET_VEC(xtol_abs)
- NLOPT_GETSET(int, maxeval)
- NLOPT_GETSET(double, maxtime)
-
- NLOPT_GETSET(int, force_stop)
- void force_stop() { set_force_stop(1); }
-
- // algorithm-specific parameters:
-
- void set_local_optimizer(const nlopt_opt lo) {
- nlopt_result ret = nlopt_set_local_optimizer(o, lo);
- mythrow(ret);
- }
- void set_local_optimizer(const opt &lo) {
- set_local_optimizer(lo.o);
- }
-
- NLOPT_GETSET(unsigned, population)
- NLOPT_GETSET_VEC(initial_step)
-
- void set_default_initial_step(const double *x) {
- nlopt_result ret = nlopt_set_default_initial_step(o, x);
- mythrow(ret);
- }
- void set_default_initial_step(const std::vector<double> &x) {
- set_default_initial_step(x.empty() ? NULL : &x[0]);
- }
- void get_initial_step(const double *x, double *dx) const {
- nlopt_result ret = nlopt_get_initial_step(o, x, dx);
- mythrow(ret);
- }
- void get_initial_step(const std::vector<double> &x, std::vector<double> &dx) const {
- if (o && (nlopt_get_dimension(o) != x.size()
- || nlopt_get_dimension(o) != dx.size()))
- throw std::invalid_argument("dimension mismatch");
- get_initial_step(x.empty() ? NULL : &x[0],
- dx.empty() ? NULL : &dx[0]);
- }
- std::vector<double> get_initial_step(const std::vector<double> &x) const {
- if (!o) throw std::runtime_error("uninitialized nlopt::opt");
- std::vector<double> v(nlopt_get_dimension(o));
- get_initial_step(x, v);
- return v;
- }
- };
-
-#undef NLOPT_GETSET
-#undef NLOPT_GETSET_VEC
-
- //////////////////////////////////////////////////////////////////////
-
- inline void srand(unsigned long seed) { nlopt_srand(seed); }
- inline void srand_time(void) { nlopt_srand_time(); }
- inline void version(int &major, int &minor, int &bugfix) {
- nlopt_version(&major, &minor, &bugfix);
- }
- inline const char *algorithm_name(nlopt_algorithm a) {
- return nlopt_algorithm_name(a);
- }
- inline const char *algorithm_name(algorithm a) {
- return algorithm_name(nlopt_algorithm(a));
- }
-
- //////////////////////////////////////////////////////////////////////
-
-} // namespace nlopt
}
GET(force_stop, int, force_stop)
-nlopt_result nlopt_force_stop(nlopt_opt opt) { nlopt_set_force_stop(opt, 1); }
+nlopt_result nlopt_force_stop(nlopt_opt opt) {
+ return nlopt_set_force_stop(opt, 1);
+}
/*************************************************************************/
GETSET(free_f_data, int, free_f_data)
+/* the dup_f_data function replaces all f_data pointers with a new
+ pointer to a duplicate block of memory, assuming all non-NULL
+ f_data pointers point to a block of sz bytes... this is pretty
+ exclusively intended for internal use (e.g. it may lead to a
+ double-free if one subsequently calles add_inequality_constraint
+ etc.), e.g. in the C++ API */
+
+static int dup(void **p, size_t sz) {
+ if (*p) {
+ void *pdup = malloc(sz);
+ if (pdup) {
+ memcpy(pdup, *p, sz);
+ *p = pdup;
+ return 1;
+ }
+ else return 0;
+ }
+ else return 1;
+}
+
+nlopt_result nlopt_dup_f_data(nlopt_opt opt, size_t sz) {
+ if (opt) {
+ unsigned i;
+ if (!dup(&opt->f_data, sz)) return NLOPT_OUT_OF_MEMORY;
+ for (i = 0; i < opt->m; ++i)
+ if (!dup(&opt->fc[i].f_data, sz)) return NLOPT_OUT_OF_MEMORY;
+ for (i = 0; i < opt->p; ++i)
+ if (!dup(&opt->h[i].f_data, sz)) return NLOPT_OUT_OF_MEMORY;
+ nlopt_set_free_f_data(opt, 1); // nlopt_destroy must now free f_data!
+ return NLOPT_SUCCESS;
+ }
+ return NLOPT_INVALID_ARGS;
+}
+
/*************************************************************************/