chiark / gitweb /
version, copyright-year bump
[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       return optimize(x.empty() ? NULL : &x[0], opt_f);
113     }
114
115     // accessors:
116     algorithm get_algorithm() const {
117       if (!o) throw std::invalid_argument("uninitialized nlopt::opt");
118       return algorithm(nlopt_get_algorithm(o));
119     }
120     unsigned get_dimension() const {
121       if (!o) throw std::invalid_argument("uninitialized nlopt::opt");
122       return nlopt_get_dimension(o);
123     }
124
125     // Set the objective function
126     void set_min_objective(nlopt_func f, void *f_data) {
127       nlopt_result ret = nlopt_set_min_objective(o, f, f_data);
128       mythrow(ret);
129     }
130     void set_min_objective(func *f) {
131       set_min_objective(myfunc, f);
132     }
133
134     // Nonlinear constraints:
135
136     void remove_inequality_constraints(void) {
137       nlopt_result ret = nlopt_remove_inequality_constraints(o);
138       mythrow(ret);
139     }
140     void add_inequality_constraint(nlopt_func f, void *f_data, double tol=0) {
141       nlopt_result ret = nlopt_add_inequality_constraint(o, f, f_data, tol);
142       mythrow(ret);
143     }
144     void add_inequality_constraint(func *f, double tol=0) {
145       add_inequality_constraint(myfunc, f, tol);
146     }
147
148     void remove_equality_constraints(void) {
149       nlopt_result ret = nlopt_remove_equality_constraints(o);
150       mythrow(ret);
151     }
152     void add_equality_constraint(nlopt_func f, void *f_data, double tol=0) {
153       nlopt_result ret = nlopt_add_equality_constraint(o, f, f_data, tol);
154       mythrow(ret);
155     }
156     void add_equality_constraint(func *f, double tol=0) {
157       add_equality_constraint(myfunc, f, tol);
158     }
159
160 #define NLOPT_GETSET_VEC(name)                                          \
161     void get_##name(double *v) const {                                  \
162       nlopt_result ret = nlopt_get_##name(o, v);                        \
163       mythrow(ret);                                                     \
164     }                                                                   \
165     void set_##name(const double *v) {                                  \
166       nlopt_result ret = nlopt_set_##name(o, v);                        \
167       mythrow(ret);                                                     \
168     }                                                                   \
169     void set_##name(double val) {                                       \
170       nlopt_result ret = nlopt_set_##name##1(o, val);                   \
171       mythrow(ret);                                                     \
172     }                                                                   \
173     void get_##name(std::vector<double> &v) const {                     \
174       if (o && nlopt_get_dimension(o) != v.size())                      \
175         throw std::invalid_argument("dimension mismatch");              \
176       get_##name(v.empty() ? NULL : &v[0]);                             \
177     }                                                                   \
178     std::vector<double> get_##name(void) const {                        \
179       if (!o) throw std::invalid_argument("uninitialized nlopt::opt");  \
180       std::vector<double> v(nlopt_get_dimension(o));                    \
181       get_##name(v);                                                    \
182       return v;                                                         \
183     }                                                                   \
184     void set_##name(const std::vector<double> &v) {                     \
185       if (o && nlopt_get_dimension(o) != v.size())                      \
186         throw std::invalid_argument("dimension mismatch");              \
187       set_##name(v.empty() ? NULL : &v[0]);                             \
188     }
189
190     NLOPT_GETSET_VEC(lower_bounds)
191     NLOPT_GETSET_VEC(upper_bounds)
192
193     // stopping criteria:
194
195 #define NLOPT_GETSET(T, name)                                           \
196     T get_##name() const {                                              \
197       if (!o) throw std::invalid_argument("uninitialized nlopt::opt");  \
198       return nlopt_get_##name(o);                                       \
199     }                                                                   \
200     void set_##name(T name) {                                           \
201       nlopt_result ret = nlopt_set_##name(o, name);                     \
202       mythrow(ret);                                                     \
203     }
204     NLOPT_GETSET(double, stopval)
205     NLOPT_GETSET(double, ftol_rel)
206     NLOPT_GETSET(double, ftol_abs)
207     NLOPT_GETSET(double, xtol_rel)
208     NLOPT_GETSET_VEC(xtol_abs)
209     NLOPT_GETSET(int, maxeval)
210     NLOPT_GETSET(double, maxtime)
211
212     // algorithm-specific parameters:
213
214     void set_local_optimizer(const nlopt_opt lo) {
215       nlopt_result ret = nlopt_set_local_optimizer(o, lo);
216       mythrow(ret);
217     }
218     void set_local_optimizer(const opt &lo) {
219       set_local_optimizer(lo.o);
220     }
221
222     NLOPT_GETSET(unsigned, population)
223     NLOPT_GETSET_VEC(initial_step)
224
225     void set_default_initial_step(const double *x) {
226       nlopt_result ret = nlopt_set_default_initial_step(o, x);
227       mythrow(ret);
228     }
229     void set_default_initial_step(const std::vector<double> &x) {
230       set_default_initial_step(x.empty() ? NULL : &x[0]);
231     }
232     void get_initial_step(const double *x, double *dx) const {
233       nlopt_result ret = nlopt_get_initial_step(o, x, dx);
234       mythrow(ret);
235     }
236     void get_initial_step(const std::vector<double> &x, std::vector<double> &dx) const {
237       if (o && (nlopt_get_dimension(o) != x.size()
238                 || nlopt_get_dimension(o) != dx.size()))
239         throw std::invalid_argument("dimension mismatch");
240       get_initial_step(x.empty() ? NULL : &x[0],
241                        dx.empty() ? NULL : &dx[0]);
242     }
243     std::vector<double> get_initial_step(const std::vector<double> &x) const {
244       if (!o) throw std::invalid_argument("uninitialized nlopt::opt");
245       std::vector<double> v(nlopt_get_dimension(o));
246       get_initial_step(x, v);
247       return v;
248     }
249   };
250
251   //////////////////////////////////////////////////////////////////////
252
253 } // namespace nlopt