1 /* Copyright (c) 2007-2010 Massachusetts Institute of Technology
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:
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
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.
23 // C++ style wrapper around NLopt API
24 // nlopt.hpp is AUTOMATICALLY GENERATED from nlopt-in.hpp - edit the latter!
32 // convenience overloading for below (not in nlopt:: since has nlopt_ prefix)
33 inline nlopt_result nlopt_get_initial_step(const nlopt_opt opt, double *dx) {
34 return nlopt_get_initial_step(opt, (const double *) NULL, dx);
39 //////////////////////////////////////////////////////////////////////
40 // nlopt::* namespace versions of the C enumerated types
41 // AUTOMATICALLY GENERATED, DO NOT EDIT
43 //////////////////////////////////////////////////////////////////////
45 // virtual base class for objective function and constraints:
48 // should return function value, and set grad to gradient
49 // (x and grad are length n)
50 virtual double operator()(unsigned n, const double *x, double *grad) = 0;
52 // should return function value (x is length n)
53 virtual double operator()(unsigned n, const double *x) = 0;
56 // (Note: it is inefficient to use std::vector<double> for the arguments,
57 // since that would require a copy to be made of NLopt's double* data.)
59 //////////////////////////////////////////////////////////////////////
65 void mythrow(nlopt_result ret) const {
67 case NLOPT_FAILURE: throw std::runtime_error("nlopt failure");
68 case NLOPT_OUT_OF_MEMORY: throw std::bad_alloc();
69 case NLOPT_INVALID_ARGS: throw std::invalid_argument("nlopt");
70 case NLOPT_ROUNDOFF_LIMITED: throw std::runtime_error("nlopt roundoff");
75 // nlopt_func wrapper around C++ "functional"
76 static double myfunc(unsigned n, const double *x, double *grad, void *f_) {
77 func *f = reinterpret_cast<func*>(f_);
78 return grad ? (*f)(n, x, grad) : (*f)(n, x);
84 opt(nlopt_algorithm a, unsigned n) : o(nlopt_create(a, n)) {
85 if (!o) throw std::bad_alloc();
87 opt(algorithm a, unsigned n) : o(nlopt_create(nlopt_algorithm(a), n)) {
88 if (!o) throw std::bad_alloc();
90 opt(const nlopt_opt o0) : o(nlopt_copy(o0)) {
91 if (o0 && !o) throw std::bad_alloc();
93 ~opt() { nlopt_destroy(o); }
94 opt(const opt& from) : o(nlopt_copy(from.o)) {
95 if (from.o && !o) throw std::bad_alloc();
97 opt& operator=(opt const& f) {
98 if (this == &f) return *this; // self-assignment
101 if (f.o && !o) throw std::bad_alloc();
105 // Do the optimization:
106 result optimize(double *x, double &opt_f) {
107 nlopt_result ret = nlopt_optimize(o, x, &opt_f);
111 result optimize(std::vector<double> &x, double &opt_f) {
112 if (o && nlopt_get_dimension(o) != x.size())
113 throw std::invalid_argument("dimension mismatch");
114 return optimize(x.empty() ? NULL : &x[0], opt_f);
118 algorithm get_algorithm() const {
119 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
120 return algorithm(nlopt_get_algorithm(o));
122 const char *get_algorithm_name() const {
123 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
124 return nlopt_algorithm_name(nlopt_get_algorithm(o));
126 unsigned get_dimension() const {
127 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
128 return nlopt_get_dimension(o);
131 // Set the objective function
132 void set_min_objective(nlopt_func f, void *f_data) {
133 nlopt_result ret = nlopt_set_min_objective(o, f, f_data);
136 void set_min_objective(func *f) {
137 set_min_objective(myfunc, f);
139 void set_max_objective(nlopt_func f, void *f_data) {
140 nlopt_result ret = nlopt_set_max_objective(o, f, f_data);
143 void set_max_objective(func *f) {
144 set_max_objective(myfunc, f);
147 // Nonlinear constraints:
149 void remove_inequality_constraints(void) {
150 nlopt_result ret = nlopt_remove_inequality_constraints(o);
153 void add_inequality_constraint(nlopt_func f, void *f_data, double tol=0) {
154 nlopt_result ret = nlopt_add_inequality_constraint(o, f, f_data, tol);
157 void add_inequality_constraint(func *f, double tol=0) {
158 add_inequality_constraint(myfunc, f, tol);
161 void remove_equality_constraints(void) {
162 nlopt_result ret = nlopt_remove_equality_constraints(o);
165 void add_equality_constraint(nlopt_func f, void *f_data, double tol=0) {
166 nlopt_result ret = nlopt_add_equality_constraint(o, f, f_data, tol);
169 void add_equality_constraint(func *f, double tol=0) {
170 add_equality_constraint(myfunc, f, tol);
173 #define NLOPT_GETSET_VEC(name) \
174 void get_##name(double *v) const { \
175 nlopt_result ret = nlopt_get_##name(o, v); \
178 void set_##name(const double *v) { \
179 nlopt_result ret = nlopt_set_##name(o, v); \
182 void set_##name(double val) { \
183 nlopt_result ret = nlopt_set_##name##1(o, val); \
186 void get_##name(std::vector<double> &v) const { \
187 if (o && nlopt_get_dimension(o) != v.size()) \
188 throw std::invalid_argument("dimension mismatch"); \
189 get_##name(v.empty() ? NULL : &v[0]); \
191 std::vector<double> get_##name(void) const { \
192 if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
193 std::vector<double> v(nlopt_get_dimension(o)); \
197 void set_##name(const std::vector<double> &v) { \
198 if (o && nlopt_get_dimension(o) != v.size()) \
199 throw std::invalid_argument("dimension mismatch"); \
200 set_##name(v.empty() ? NULL : &v[0]); \
203 NLOPT_GETSET_VEC(lower_bounds)
204 NLOPT_GETSET_VEC(upper_bounds)
206 // stopping criteria:
208 #define NLOPT_GETSET(T, name) \
209 T get_##name() const { \
210 if (!o) throw std::runtime_error("uninitialized nlopt::opt"); \
211 return nlopt_get_##name(o); \
213 void set_##name(T name) { \
214 nlopt_result ret = nlopt_set_##name(o, name); \
217 NLOPT_GETSET(double, stopval)
218 NLOPT_GETSET(double, ftol_rel)
219 NLOPT_GETSET(double, ftol_abs)
220 NLOPT_GETSET(double, xtol_rel)
221 NLOPT_GETSET_VEC(xtol_abs)
222 NLOPT_GETSET(int, maxeval)
223 NLOPT_GETSET(double, maxtime)
225 // algorithm-specific parameters:
227 void set_local_optimizer(const nlopt_opt lo) {
228 nlopt_result ret = nlopt_set_local_optimizer(o, lo);
231 void set_local_optimizer(const opt &lo) {
232 set_local_optimizer(lo.o);
235 NLOPT_GETSET(unsigned, population)
236 NLOPT_GETSET_VEC(initial_step)
238 void set_default_initial_step(const double *x) {
239 nlopt_result ret = nlopt_set_default_initial_step(o, x);
242 void set_default_initial_step(const std::vector<double> &x) {
243 set_default_initial_step(x.empty() ? NULL : &x[0]);
245 void get_initial_step(const double *x, double *dx) const {
246 nlopt_result ret = nlopt_get_initial_step(o, x, dx);
249 void get_initial_step(const std::vector<double> &x, std::vector<double> &dx) const {
250 if (o && (nlopt_get_dimension(o) != x.size()
251 || nlopt_get_dimension(o) != dx.size()))
252 throw std::invalid_argument("dimension mismatch");
253 get_initial_step(x.empty() ? NULL : &x[0],
254 dx.empty() ? NULL : &dx[0]);
256 std::vector<double> get_initial_step(const std::vector<double> &x) const {
257 if (!o) throw std::runtime_error("uninitialized nlopt::opt");
258 std::vector<double> v(nlopt_get_dimension(o));
259 get_initial_step(x, v);
265 #undef NLOPT_GETSET_VEC
267 //////////////////////////////////////////////////////////////////////
269 inline void srand(unsigned long seed) { nlopt_srand(seed); }
270 inline void srand_time(void) { nlopt_srand_time(); }
271 inline void version(int &major, int &minor, int &bugfix) {
272 nlopt_version(&major, &minor, &bugfix);
274 inline const char *algorithm_name(nlopt_algorithm a) {
275 return nlopt_algorithm_name(a);
277 inline const char *algorithm_name(algorithm a) {
278 return algorithm_name(nlopt_algorithm(a));
281 //////////////////////////////////////////////////////////////////////