chiark / gitweb /
put a few more functions into the C++ API
[nlopt.git] / api / nlopt-in.hpp
1 /* Copyright (c) 2007-2010 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 #include <nlopt.h>
27
28 #include <vector>
29 #include <stdexcept>
30 #include <new>
31
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);
35 }
36
37 namespace nlopt {
38
39   //////////////////////////////////////////////////////////////////////
40   // nlopt::* namespace versions of the C enumerated types
41   //          AUTOMATICALLY GENERATED, DO NOT EDIT
42   // GEN_ENUMS_HERE
43   //////////////////////////////////////////////////////////////////////
44
45   // virtual base class for objective function and constraints:
46   class func {
47   public:
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;
51
52     // should return function value (x is length n)
53     virtual double operator()(unsigned n, const double *x) = 0;
54   };
55
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.)
58
59   //////////////////////////////////////////////////////////////////////
60
61   class opt {
62   private:
63     nlopt_opt o;
64     
65     void mythrow(nlopt_result ret) const {
66       switch (ret) {
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");
71       default: break;
72       }
73     }
74
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);
79     }
80
81   public:
82     // Constructors etc.
83     opt() : o(NULL) {}
84     opt(nlopt_algorithm a, unsigned n) : o(nlopt_create(a, n)) {
85       if (!o) throw std::bad_alloc();
86     }
87     opt(algorithm a, unsigned n) : o(nlopt_create(nlopt_algorithm(a), n)) {
88       if (!o) throw std::bad_alloc();
89     }
90     opt(const nlopt_opt o0) : o(nlopt_copy(o0)) {
91       if (o0 && !o) throw std::bad_alloc();
92     }
93     ~opt() { nlopt_destroy(o); }
94     opt(const opt& from) : o(nlopt_copy(from.o)) {
95       if (from.o && !o) throw std::bad_alloc();
96     }
97     opt& operator=(opt const& f) {
98       if (this == &f) return *this; // self-assignment
99       nlopt_destroy(o);
100       o = nlopt_copy(f.o);
101       if (f.o && !o) throw std::bad_alloc();
102       return *this;
103     }
104
105     // Do the optimization:
106     result optimize(double *x, double &opt_f) {
107       nlopt_result ret = nlopt_optimize(o, x, &opt_f);
108       mythrow(ret);
109       return result(ret);
110     }
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);
115     }
116
117     // accessors:
118     algorithm get_algorithm() const {
119       if (!o) throw std::runtime_error("uninitialized nlopt::opt");
120       return algorithm(nlopt_get_algorithm(o));
121     }
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));
125     }
126     unsigned get_dimension() const {
127       if (!o) throw std::runtime_error("uninitialized nlopt::opt");
128       return nlopt_get_dimension(o);
129     }
130
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);
134       mythrow(ret);
135     }
136     void set_min_objective(func *f) {
137       set_min_objective(myfunc, f);
138     }
139     void set_max_objective(nlopt_func f, void *f_data) {
140       nlopt_result ret = nlopt_set_max_objective(o, f, f_data);
141       mythrow(ret);
142     }
143     void set_max_objective(func *f) {
144       set_max_objective(myfunc, f);
145     }
146
147     // Nonlinear constraints:
148
149     void remove_inequality_constraints(void) {
150       nlopt_result ret = nlopt_remove_inequality_constraints(o);
151       mythrow(ret);
152     }
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);
155       mythrow(ret);
156     }
157     void add_inequality_constraint(func *f, double tol=0) {
158       add_inequality_constraint(myfunc, f, tol);
159     }
160
161     void remove_equality_constraints(void) {
162       nlopt_result ret = nlopt_remove_equality_constraints(o);
163       mythrow(ret);
164     }
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);
167       mythrow(ret);
168     }
169     void add_equality_constraint(func *f, double tol=0) {
170       add_equality_constraint(myfunc, f, tol);
171     }
172
173 #define NLOPT_GETSET_VEC(name)                                          \
174     void get_##name(double *v) const {                                  \
175       nlopt_result ret = nlopt_get_##name(o, v);                        \
176       mythrow(ret);                                                     \
177     }                                                                   \
178     void set_##name(const double *v) {                                  \
179       nlopt_result ret = nlopt_set_##name(o, v);                        \
180       mythrow(ret);                                                     \
181     }                                                                   \
182     void set_##name(double val) {                                       \
183       nlopt_result ret = nlopt_set_##name##1(o, val);                   \
184       mythrow(ret);                                                     \
185     }                                                                   \
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]);                             \
190     }                                                                   \
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));                    \
194       get_##name(v);                                                    \
195       return v;                                                         \
196     }                                                                   \
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]);                             \
201     }
202
203     NLOPT_GETSET_VEC(lower_bounds)
204     NLOPT_GETSET_VEC(upper_bounds)
205
206     // stopping criteria:
207
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);                                       \
212     }                                                                   \
213     void set_##name(T name) {                                           \
214       nlopt_result ret = nlopt_set_##name(o, name);                     \
215       mythrow(ret);                                                     \
216     }
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)
224
225     // algorithm-specific parameters:
226
227     void set_local_optimizer(const nlopt_opt lo) {
228       nlopt_result ret = nlopt_set_local_optimizer(o, lo);
229       mythrow(ret);
230     }
231     void set_local_optimizer(const opt &lo) {
232       set_local_optimizer(lo.o);
233     }
234
235     NLOPT_GETSET(unsigned, population)
236     NLOPT_GETSET_VEC(initial_step)
237
238     void set_default_initial_step(const double *x) {
239       nlopt_result ret = nlopt_set_default_initial_step(o, x);
240       mythrow(ret);
241     }
242     void set_default_initial_step(const std::vector<double> &x) {
243       set_default_initial_step(x.empty() ? NULL : &x[0]);
244     }
245     void get_initial_step(const double *x, double *dx) const {
246       nlopt_result ret = nlopt_get_initial_step(o, x, dx);
247       mythrow(ret);
248     }
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]);
255     }
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);
260       return v;
261     }
262   };
263
264 #undef NLOPT_GETSET
265 #undef NLOPT_GETSET_VEC
266
267   //////////////////////////////////////////////////////////////////////
268
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);
273   }
274   inline const char *algorithm_name(nlopt_algorithm a) {
275     return nlopt_algorithm_name(a);
276   }
277   inline const char *algorithm_name(algorithm a) {
278     return algorithm_name(nlopt_algorithm(a));
279   }
280
281   //////////////////////////////////////////////////////////////////////
282
283 } // namespace nlopt