1 /* Copyright (c) 2007-2011 Massachusetts Institute of Technology
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 // C++ style wrapper around NLopt API
24 // nlopt.hpp is AUTOMATICALLY GENERATED from nlopt-in.hpp - edit the latter!
25
26 #ifndef NLOPT_HPP
27 #define NLOPT_HPP
28
29 #include <nlopt.h>
30
31 #include <vector>
32 #include <stdexcept>
33 #include <new>
34 #include <cstdlib>
35 #include <cstring>
36 #include <cmath>
37
38 // convenience overloading for below (not in nlopt:: since has nlopt_ prefix)
nlopt_get_initial_step(const nlopt_opt opt,double * dx)39 inline nlopt_result nlopt_get_initial_step(const nlopt_opt opt, double *dx) {
40 return nlopt_get_initial_step(opt, (const double *) NULL, dx);
41 }
42
43 namespace nlopt {
44
45 //////////////////////////////////////////////////////////////////////
46 // nlopt::* namespace versions of the C enumerated types
47 // AUTOMATICALLY GENERATED, DO NOT EDIT
48 // GEN_ENUMS_HERE
49 enum algorithm {
50 GN_DIRECT = 0,
51 GN_DIRECT_L,
52 GN_DIRECT_L_RAND,
53 GN_DIRECT_NOSCAL,
54 GN_DIRECT_L_NOSCAL,
55 GN_DIRECT_L_RAND_NOSCAL,
56 GN_ORIG_DIRECT,
57 GN_ORIG_DIRECT_L,
58 GD_STOGO,
59 GD_STOGO_RAND,
60 LD_LBFGS_NOCEDAL,
61 LD_LBFGS,
62 LN_PRAXIS,
63 LD_VAR1,
64 LD_VAR2,
65 LD_TNEWTON,
66 LD_TNEWTON_RESTART,
67 LD_TNEWTON_PRECOND,
68 LD_TNEWTON_PRECOND_RESTART,
69 GN_CRS2_LM,
70 GN_MLSL,
71 GD_MLSL,
72 GN_MLSL_LDS,
73 GD_MLSL_LDS,
74 LD_MMA,
75 LN_COBYLA,
76 LN_NEWUOA,
77 LN_NEWUOA_BOUND,
78 LN_NELDERMEAD,
79 LN_SBPLX,
80 LN_AUGLAG,
81 LD_AUGLAG,
82 LN_AUGLAG_EQ,
83 LD_AUGLAG_EQ,
84 LN_BOBYQA,
85 GN_ISRES,
86 AUGLAG,
87 AUGLAG_EQ,
88 G_MLSL,
89 G_MLSL_LDS,
90 LD_SLSQP,
91 LD_CCSAQ,
92 GN_ESCH,
93 NUM_ALGORITHMS /* not an algorithm, just the number of them */
94 };
95 enum result {
96 FAILURE = -1, /* generic failure code */
97 INVALID_ARGS = -2,
98 OUT_OF_MEMORY = -3,
99 ROUNDOFF_LIMITED = -4,
100 FORCED_STOP = -5,
101 SUCCESS = 1, /* generic success code */
102 STOPVAL_REACHED = 2,
103 FTOL_REACHED = 3,
104 XTOL_REACHED = 4,
105 MAXEVAL_REACHED = 5,
106 MAXTIME_REACHED = 6
107 };
108 // GEN_ENUMS_HERE
109 //////////////////////////////////////////////////////////////////////
110
111 typedef nlopt_func func; // nlopt::func synoynm
112 typedef nlopt_mfunc mfunc; // nlopt::mfunc synoynm
113
114 // alternative to nlopt_func that takes std::vector<double>
115 // ... unfortunately requires a data copy
116 typedef double (*vfunc)(const std::vector<double> &x,
117 std::vector<double> &grad, void *data);
118
119 //////////////////////////////////////////////////////////////////////
120
121 // NLopt-specific exceptions (corresponding to error codes):
122 class roundoff_limited : public std::runtime_error {
123 public:
roundoff_limited()124 roundoff_limited() : std::runtime_error("nlopt roundoff-limited") {}
125 };
126
127 class forced_stop : public std::runtime_error {
128 public:
forced_stop()129 forced_stop() : std::runtime_error("nlopt forced stop") {}
130 };
131
132 //////////////////////////////////////////////////////////////////////
133
134 class opt {
135 private:
136 nlopt_opt o;
137
mythrow(nlopt_result ret) const138 void mythrow(nlopt_result ret) const {
139 switch (ret) {
140 case NLOPT_FAILURE: throw std::runtime_error("nlopt failure");
141 case NLOPT_OUT_OF_MEMORY: throw std::bad_alloc();
142 case NLOPT_INVALID_ARGS: throw std::invalid_argument("nlopt invalid argument");
143 case NLOPT_ROUNDOFF_LIMITED: throw roundoff_limited();
144 case NLOPT_FORCED_STOP: throw forced_stop();
145 default: break;
146 }
147 }
148
149 typedef struct {
150 opt *o;
151 mfunc mf; func f; void *f_data;
152 vfunc vf;
153 nlopt_munge munge_destroy, munge_copy; // non-NULL for SWIG wrappers
154 } myfunc_data;
155
156 // free/destroy f_data in nlopt_destroy and nlopt_copy, respectively
free_myfunc_data(void * p)157 static void *free_myfunc_data(void *p) {
158 myfunc_data *d = (myfunc_data *) p;
159 if (d) {
160 if (d->f_data && d->munge_destroy) d->munge_destroy(d->f_data);
161 delete d;
162 }
163 return NULL;
164 }
dup_myfunc_data(void * p)165 static void *dup_myfunc_data(void *p) {
166 myfunc_data *d = (myfunc_data *) p;
167 if (d) {
168 void *f_data;
169 if (d->f_data && d->munge_copy) {
170 f_data = d->munge_copy(d->f_data);
171 if (!f_data) return NULL;
172 }
173 else
174 f_data = d->f_data;
175 myfunc_data *dnew = new myfunc_data;
176 if (dnew) {
177 *dnew = *d;
178 dnew->f_data = f_data;
179 }
180 return (void*) dnew;
181 }
182 else return NULL;
183 }
184
185 // nlopt_func wrapper that catches exceptions
myfunc(unsigned n,const double * x,double * grad,void * d_)186 static double myfunc(unsigned n, const double *x, double *grad, void *d_) {
187 myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
188 try {
189 return d->f(n, x, grad, d->f_data);
190 }
191 catch (std::bad_alloc&)
192 { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; }
193 catch (std::invalid_argument&)
194 { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; }
195 catch (roundoff_limited&)
196 { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; }
197 catch (forced_stop&)
198 { d->o->forced_stop_reason = NLOPT_FORCED_STOP; }
199 catch (...)
200 { d->o->forced_stop_reason = NLOPT_FAILURE; }
201 d->o->force_stop(); // stop gracefully, opt::optimize will re-throw
202 return HUGE_VAL;
203 }
204
205 // nlopt_mfunc wrapper that catches exceptions
mymfunc(unsigned m,double * result,unsigned n,const double * x,double * grad,void * d_)206 static void mymfunc(unsigned m, double *result,
207 unsigned n, const double *x, double *grad, void *d_) {
208 myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
209 try {
210 d->mf(m, result, n, x, grad, d->f_data);
211 return;
212 }
213 catch (std::bad_alloc&)
214 { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; }
215 catch (std::invalid_argument&)
216 { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; }
217 catch (roundoff_limited&)
218 { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; }
219 catch (forced_stop&)
220 { d->o->forced_stop_reason = NLOPT_FORCED_STOP; }
221 catch (...)
222 { d->o->forced_stop_reason = NLOPT_FAILURE; }
223 d->o->force_stop(); // stop gracefully, opt::optimize will re-throw
224 for (unsigned i = 0; i < m; ++i) result[i] = HUGE_VAL;
225 }
226
227 std::vector<double> xtmp, gradtmp, gradtmp0; // scratch for myvfunc
228
229 // nlopt_func wrapper, using std::vector<double>
myvfunc(unsigned n,const double * x,double * grad,void * d_)230 static double myvfunc(unsigned n, const double *x, double *grad, void *d_){
231 myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
232 try {
233 std::vector<double> &xv = d->o->xtmp;
234 if (n) std::memcpy(&xv[0], x, n * sizeof(double));
235 double val=d->vf(xv, grad ? d->o->gradtmp : d->o->gradtmp0, d->f_data);
236 if (grad && n) {
237 std::vector<double> &gradv = d->o->gradtmp;
238 std::memcpy(grad, &gradv[0], n * sizeof(double));
239 }
240 return val;
241 }
242 catch (std::bad_alloc&)
243 { d->o->forced_stop_reason = NLOPT_OUT_OF_MEMORY; }
244 catch (std::invalid_argument&)
245 { d->o->forced_stop_reason = NLOPT_INVALID_ARGS; }
246 catch (roundoff_limited&)
247 { d->o->forced_stop_reason = NLOPT_ROUNDOFF_LIMITED; }
248 catch (forced_stop&)
249 { d->o->forced_stop_reason = NLOPT_FORCED_STOP; }
250 catch (...)
251 { d->o->forced_stop_reason = NLOPT_FAILURE; }
252 d->o->force_stop(); // stop gracefully, opt::optimize will re-throw
253 return HUGE_VAL;
254 }
255
alloc_tmp()256 void alloc_tmp() {
257 if (xtmp.size() != nlopt_get_dimension(o)) {
258 xtmp = std::vector<double>(nlopt_get_dimension(o));
259 gradtmp = std::vector<double>(nlopt_get_dimension(o));
260 }
261 }
262
263 result last_result;
264 double last_optf;
265 nlopt_result forced_stop_reason;
266
267 public:
268 // Constructors etc.
opt()269 opt() : o(NULL), xtmp(0), gradtmp(0), gradtmp0(0),
270 last_result(nlopt::FAILURE), last_optf(HUGE_VAL),
271 forced_stop_reason(NLOPT_FORCED_STOP) {}
~opt()272 ~opt() { nlopt_destroy(o); }
opt(algorithm a,unsigned n)273 opt(algorithm a, unsigned n) :
274 o(nlopt_create(nlopt_algorithm(a), n)),
275 xtmp(0), gradtmp(0), gradtmp0(0),
276 last_result(nlopt::FAILURE), last_optf(HUGE_VAL),
277 forced_stop_reason(NLOPT_FORCED_STOP) {
278 if (!o) throw std::bad_alloc();
279 nlopt_set_munge(o, free_myfunc_data, dup_myfunc_data);
280 }
opt(const opt & f)281 opt(const opt& f) : o(nlopt_copy(f.o)),
282 xtmp(f.xtmp), gradtmp(f.gradtmp), gradtmp0(0),
283 last_result(f.last_result), last_optf(f.last_optf),
284 forced_stop_reason(f.forced_stop_reason) {
285 if (f.o && !o) throw std::bad_alloc();
286 }
operator =(opt const & f)287 opt& operator=(opt const& f) {
288 if (this == &f) return *this; // self-assignment
289 nlopt_destroy(o);
290 o = nlopt_copy(f.o);
291 if (f.o && !o) throw std::bad_alloc();
292 xtmp = f.xtmp; gradtmp = f.gradtmp;
293 last_result = f.last_result; last_optf = f.last_optf;
294 forced_stop_reason = f.forced_stop_reason;
295 return *this;
296 }
297
298 // Do the optimization:
optimize(std::vector<double> & x,double & opt_f)299 result optimize(std::vector<double> &x, double &opt_f) {
300 if (o && nlopt_get_dimension(o) != x.size())
301 throw std::invalid_argument("dimension mismatch");
302 forced_stop_reason = NLOPT_FORCED_STOP;
303 nlopt_result ret = nlopt_optimize(o, x.empty() ? NULL : &x[0], &opt_f);
304 last_result = result(ret);
305 last_optf = opt_f;
306 if (ret == NLOPT_FORCED_STOP)
307 mythrow(forced_stop_reason);
308 mythrow(ret);
309 return last_result;
310 }
311
312 // variant mainly useful for SWIG wrappers:
optimize(const std::vector<double> & x0)313 std::vector<double> optimize(const std::vector<double> &x0) {
314 std::vector<double> x(x0);
315 last_result = optimize(x, last_optf);
316 return x;
317 }
last_optimize_result() const318 result last_optimize_result() const { return last_result; }
last_optimum_value() const319 double last_optimum_value() const { return last_optf; }
320
321 // accessors:
get_algorithm() const322 algorithm get_algorithm() const {
323 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
324 return algorithm(nlopt_get_algorithm(o));
325 }
get_algorithm_name() const326 const char *get_algorithm_name() const {
327 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
328 return nlopt_algorithm_name(nlopt_get_algorithm(o));
329 }
get_dimension() const330 unsigned get_dimension() const {
331 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
332 return nlopt_get_dimension(o);
333 }
334
335 // Set the objective function
set_min_objective(func f,void * f_data)336 void set_min_objective(func f, void *f_data) {
337 myfunc_data *d = new myfunc_data;
338 if (!d) throw std::bad_alloc();
339 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
340 d->munge_destroy = d->munge_copy = NULL;
341 mythrow(nlopt_set_min_objective(o, myfunc, d)); // d freed via o
342 }
set_min_objective(vfunc vf,void * f_data)343 void set_min_objective(vfunc vf, void *f_data) {
344 myfunc_data *d = new myfunc_data;
345 if (!d) throw std::bad_alloc();
346 d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf;
347 d->munge_destroy = d->munge_copy = NULL;
348 mythrow(nlopt_set_min_objective(o, myvfunc, d)); // d freed via o
349 alloc_tmp();
350 }
set_max_objective(func f,void * f_data)351 void set_max_objective(func f, void *f_data) {
352 myfunc_data *d = new myfunc_data;
353 if (!d) throw std::bad_alloc();
354 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
355 d->munge_destroy = d->munge_copy = NULL;
356 mythrow(nlopt_set_max_objective(o, myfunc, d)); // d freed via o
357 }
set_max_objective(vfunc vf,void * f_data)358 void set_max_objective(vfunc vf, void *f_data) {
359 myfunc_data *d = new myfunc_data;
360 if (!d) throw std::bad_alloc();
361 d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf;
362 d->munge_destroy = d->munge_copy = NULL;
363 mythrow(nlopt_set_max_objective(o, myvfunc, d)); // d freed via o
364 alloc_tmp();
365 }
366
367 // for internal use in SWIG wrappers -- variant that
368 // takes ownership of f_data, with munging for destroy/copy
set_min_objective(func f,void * f_data,nlopt_munge md,nlopt_munge mc)369 void set_min_objective(func f, void *f_data,
370 nlopt_munge md, nlopt_munge mc) {
371 myfunc_data *d = new myfunc_data;
372 if (!d) throw std::bad_alloc();
373 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
374 d->munge_destroy = md; d->munge_copy = mc;
375 mythrow(nlopt_set_min_objective(o, myfunc, d)); // d freed via o
376 }
set_max_objective(func f,void * f_data,nlopt_munge md,nlopt_munge mc)377 void set_max_objective(func f, void *f_data,
378 nlopt_munge md, nlopt_munge mc) {
379 myfunc_data *d = new myfunc_data;
380 if (!d) throw std::bad_alloc();
381 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
382 d->munge_destroy = md; d->munge_copy = mc;
383 mythrow(nlopt_set_max_objective(o, myfunc, d)); // d freed via o
384 }
385
386 // Nonlinear constraints:
387
remove_inequality_constraints()388 void remove_inequality_constraints() {
389 nlopt_result ret = nlopt_remove_inequality_constraints(o);
390 mythrow(ret);
391 }
add_inequality_constraint(func f,void * f_data,double tol=0)392 void add_inequality_constraint(func f, void *f_data, double tol=0) {
393 myfunc_data *d = new myfunc_data;
394 if (!d) throw std::bad_alloc();
395 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
396 d->munge_destroy = d->munge_copy = NULL;
397 mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol));
398 }
add_inequality_constraint(vfunc vf,void * f_data,double tol=0)399 void add_inequality_constraint(vfunc vf, void *f_data, double tol=0) {
400 myfunc_data *d = new myfunc_data;
401 if (!d) throw std::bad_alloc();
402 d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf;
403 d->munge_destroy = d->munge_copy = NULL;
404 mythrow(nlopt_add_inequality_constraint(o, myvfunc, d, tol));
405 alloc_tmp();
406 }
add_inequality_mconstraint(mfunc mf,void * f_data,const std::vector<double> & tol)407 void add_inequality_mconstraint(mfunc mf, void *f_data,
408 const std::vector<double> &tol) {
409 myfunc_data *d = new myfunc_data;
410 if (!d) throw std::bad_alloc();
411 d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL;
412 d->munge_destroy = d->munge_copy = NULL;
413 mythrow(nlopt_add_inequality_mconstraint(o, tol.size(), mymfunc, d,
414 tol.empty() ? NULL : &tol[0]));
415 }
416
remove_equality_constraints()417 void remove_equality_constraints() {
418 nlopt_result ret = nlopt_remove_equality_constraints(o);
419 mythrow(ret);
420 }
add_equality_constraint(func f,void * f_data,double tol=0)421 void add_equality_constraint(func f, void *f_data, double tol=0) {
422 myfunc_data *d = new myfunc_data;
423 if (!d) throw std::bad_alloc();
424 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
425 d->munge_destroy = d->munge_copy = NULL;
426 mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol));
427 }
add_equality_constraint(vfunc vf,void * f_data,double tol=0)428 void add_equality_constraint(vfunc vf, void *f_data, double tol=0) {
429 myfunc_data *d = new myfunc_data;
430 if (!d) throw std::bad_alloc();
431 d->o = this; d->f = NULL; d->f_data = f_data; d->mf = NULL; d->vf = vf;
432 d->munge_destroy = d->munge_copy = NULL;
433 mythrow(nlopt_add_equality_constraint(o, myvfunc, d, tol));
434 alloc_tmp();
435 }
add_equality_mconstraint(mfunc mf,void * f_data,const std::vector<double> & tol)436 void add_equality_mconstraint(mfunc mf, void *f_data,
437 const std::vector<double> &tol) {
438 myfunc_data *d = new myfunc_data;
439 if (!d) throw std::bad_alloc();
440 d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL;
441 d->munge_destroy = d->munge_copy = NULL;
442 mythrow(nlopt_add_equality_mconstraint(o, tol.size(), mymfunc, d,
443 tol.empty() ? NULL : &tol[0]));
444 }
445
446 // For internal use in SWIG wrappers (see also above)
add_inequality_constraint(func f,void * f_data,nlopt_munge md,nlopt_munge mc,double tol=0)447 void add_inequality_constraint(func f, void *f_data,
448 nlopt_munge md, nlopt_munge mc,
449 double tol=0) {
450 myfunc_data *d = new myfunc_data;
451 if (!d) throw std::bad_alloc();
452 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
453 d->munge_destroy = md; d->munge_copy = mc;
454 mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol));
455 }
add_equality_constraint(func f,void * f_data,nlopt_munge md,nlopt_munge mc,double tol=0)456 void add_equality_constraint(func f, void *f_data,
457 nlopt_munge md, nlopt_munge mc,
458 double tol=0) {
459 myfunc_data *d = new myfunc_data;
460 if (!d) throw std::bad_alloc();
461 d->o = this; d->f = f; d->f_data = f_data; d->mf = NULL; d->vf = NULL;
462 d->munge_destroy = md; d->munge_copy = mc;
463 mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol));
464 }
add_inequality_mconstraint(mfunc mf,void * f_data,nlopt_munge md,nlopt_munge mc,const std::vector<double> & tol)465 void add_inequality_mconstraint(mfunc mf, void *f_data,
466 nlopt_munge md, nlopt_munge mc,
467 const std::vector<double> &tol) {
468 myfunc_data *d = new myfunc_data;
469 if (!d) throw std::bad_alloc();
470 d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL;
471 d->munge_destroy = md; d->munge_copy = mc;
472 mythrow(nlopt_add_inequality_mconstraint(o, tol.size(), mymfunc, d,
473 tol.empty() ? NULL : &tol[0]));
474 }
add_equality_mconstraint(mfunc mf,void * f_data,nlopt_munge md,nlopt_munge mc,const std::vector<double> & tol)475 void add_equality_mconstraint(mfunc mf, void *f_data,
476 nlopt_munge md, nlopt_munge mc,
477 const std::vector<double> &tol) {
478 myfunc_data *d = new myfunc_data;
479 if (!d) throw std::bad_alloc();
480 d->o = this; d->mf = mf; d->f_data = f_data; d->f = NULL; d->vf = NULL;
481 d->munge_destroy = md; d->munge_copy = mc;
482 mythrow(nlopt_add_equality_mconstraint(o, tol.size(), mymfunc, d,
483 tol.empty() ? NULL : &tol[0]));
484 }
485
486 #define NLOPT_GETSET_VEC(name) \
487 void set_##name(double val) { \
488 mythrow(nlopt_set_##name##1(o, val)); \
489 } \
490 void get_##name(std::vector<double> &v) const { \
491 if (o && nlopt_get_dimension(o) != v.size()) \
492 throw std::invalid_argument("dimension mismatch"); \
493 mythrow(nlopt_get_##name(o, v.empty() ? NULL : &v[0])); \
494 } \
495 std::vector<double> get_##name() const { \
496 if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
497 std::vector<double> v(nlopt_get_dimension(o)); \
498 get_##name(v); \
499 return v; \
500 } \
501 void set_##name(const std::vector<double> &v) { \
502 if (o && nlopt_get_dimension(o) != v.size()) \
503 throw std::invalid_argument("dimension mismatch"); \
504 mythrow(nlopt_set_##name(o, v.empty() ? NULL : &v[0])); \
505 }
506
507 NLOPT_GETSET_VEC(lower_bounds)
NLOPT_GETSET_VEC(upper_bounds)508 NLOPT_GETSET_VEC(upper_bounds)
509
510 // stopping criteria:
511
512 #define NLOPT_GETSET(T, name) \
513 T get_##name() const { \
514 if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
515 return nlopt_get_##name(o); \
516 } \
517 void set_##name(T name) { \
518 mythrow(nlopt_set_##name(o, name)); \
519 }
520 NLOPT_GETSET(double, stopval)
521 NLOPT_GETSET(double, ftol_rel)
522 NLOPT_GETSET(double, ftol_abs)
523 NLOPT_GETSET(double, xtol_rel)
524 NLOPT_GETSET_VEC(xtol_abs)
525 NLOPT_GETSET(int, maxeval)
526 NLOPT_GETSET(double, maxtime)
527
528 NLOPT_GETSET(int, force_stop)
529 void force_stop() { set_force_stop(1); }
530
531 // algorithm-specific parameters:
532
set_local_optimizer(const opt & lo)533 void set_local_optimizer(const opt &lo) {
534 nlopt_result ret = nlopt_set_local_optimizer(o, lo.o);
535 mythrow(ret);
536 }
537
NLOPT_GETSET(unsigned,population)538 NLOPT_GETSET(unsigned, population)
539 NLOPT_GETSET(unsigned, vector_storage)
540 NLOPT_GETSET_VEC(initial_step)
541
542 void set_default_initial_step(const std::vector<double> &x) {
543 nlopt_result ret
544 = nlopt_set_default_initial_step(o, x.empty() ? NULL : &x[0]);
545 mythrow(ret);
546 }
get_initial_step(const std::vector<double> & x,std::vector<double> & dx) const547 void get_initial_step(const std::vector<double> &x, std::vector<double> &dx) const {
548 if (o && (nlopt_get_dimension(o) != x.size()
549 || nlopt_get_dimension(o) != dx.size()))
550 throw std::invalid_argument("dimension mismatch");
551 nlopt_result ret = nlopt_get_initial_step(o, x.empty() ? NULL : &x[0],
552 dx.empty() ? NULL : &dx[0]);
553 mythrow(ret);
554 }
get_initial_step_(const std::vector<double> & x) const555 std::vector<double> get_initial_step_(const std::vector<double> &x) const {
556 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
557 std::vector<double> v(nlopt_get_dimension(o));
558 get_initial_step(x, v);
559 return v;
560 }
561 };
562
563 #undef NLOPT_GETSET
564 #undef NLOPT_GETSET_VEC
565
566 //////////////////////////////////////////////////////////////////////
567
srand(unsigned long seed)568 inline void srand(unsigned long seed) { nlopt_srand(seed); }
srand_time()569 inline void srand_time() { nlopt_srand_time(); }
version(int & major,int & minor,int & bugfix)570 inline void version(int &major, int &minor, int &bugfix) {
571 nlopt_version(&major, &minor, &bugfix);
572 }
version_major()573 inline int version_major() {
574 int major, minor, bugfix;
575 nlopt_version(&major, &minor, &bugfix);
576 return major;
577 }
version_minor()578 inline int version_minor() {
579 int major, minor, bugfix;
580 nlopt_version(&major, &minor, &bugfix);
581 return minor;
582 }
version_bugfix()583 inline int version_bugfix() {
584 int major, minor, bugfix;
585 nlopt_version(&major, &minor, &bugfix);
586 return bugfix;
587 }
algorithm_name(algorithm a)588 inline const char *algorithm_name(algorithm a) {
589 return nlopt_algorithm_name(nlopt_algorithm(a));
590 }
591
592 //////////////////////////////////////////////////////////////////////
593
594 } // namespace nlopt
595
596 #endif /* NLOPT_HPP */
597