optimize_nlopt.cpp
Go to the documentation of this file.
1 // Copyright 2019, University of Maryland and the MANGO development team.
2 //
3 // This file is part of MANGO.
4 //
5 // MANGO is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // MANGO is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with MANGO. If not, see
17 // <https://www.gnu.org/licenses/>.
18 
19 #include <iostream>
20 #include "mango.hpp"
21 #include "Solver.hpp"
22 #include "Package_nlopt.hpp"
23 
24 #ifdef MANGO_NLOPT_AVAILABLE
25 #include "nlopt.hpp"
26 #endif
27 
28 //double nlopt_objective_function(unsigned, const double*, double*, void*);
29 
30 
32 #ifdef MANGO_NLOPT_AVAILABLE
33 
34  /* int* f_data = NULL;
35  nlopt::opt opt_instance(nlopt::LN_NELDERMEAD, N_parameters); */
36 
37  /* opt_instance.set_min_objective(&nlopt_objective_function, (void*)this); */
38  /* opt_instance.set_min_objective(&nlopt_objective_function, NULL); */
39 
40  /* double f;
41  std::vector<double> vectorized_state_vector = std::vector<double>(state_vector, &state_vector[N_parameters]); */
42  /* std::cout << "Here comes vectorized_state_vector:" << vectorized_state_vector; */
43  /* nlopt::result nlopt_result = opt_instance.optimize(vectorized_state_vector, &f); */
44  /* nlopt::result nlopt_result = opt_instance.optimize(state_vector, &f); */
45 
46  nlopt::algorithm mango_nlopt_algorithm;
47  switch (solver->algorithm) {
48  // <nlopt_algorithms>
49  // This section was automatically generated by ./update_algorithms
51  mango_nlopt_algorithm = nlopt::GN_DIRECT;
52  break;
54  mango_nlopt_algorithm = nlopt::GN_DIRECT_L;
55  break;
57  mango_nlopt_algorithm = nlopt::GN_DIRECT_L_RAND;
58  break;
60  mango_nlopt_algorithm = nlopt::GN_DIRECT_NOSCAL;
61  break;
63  mango_nlopt_algorithm = nlopt::GN_DIRECT_L_NOSCAL;
64  break;
66  mango_nlopt_algorithm = nlopt::GN_DIRECT_L_RAND_NOSCAL;
67  break;
69  mango_nlopt_algorithm = nlopt::GN_ORIG_DIRECT;
70  break;
72  mango_nlopt_algorithm = nlopt::GN_ORIG_DIRECT_L;
73  break;
75  mango_nlopt_algorithm = nlopt::GN_CRS2_LM;
76  break;
78  mango_nlopt_algorithm = nlopt::LN_COBYLA;
79  break;
81  mango_nlopt_algorithm = nlopt::LN_BOBYQA;
82  break;
84  mango_nlopt_algorithm = nlopt::LN_PRAXIS;
85  break;
87  mango_nlopt_algorithm = nlopt::LN_NELDERMEAD;
88  break;
90  mango_nlopt_algorithm = nlopt::LN_SBPLX;
91  break;
93  mango_nlopt_algorithm = nlopt::LD_MMA;
94  break;
96  mango_nlopt_algorithm = nlopt::LD_CCSAQ;
97  break;
99  mango_nlopt_algorithm = nlopt::LD_SLSQP;
100  break;
102  mango_nlopt_algorithm = nlopt::LD_LBFGS;
103  break;
105  mango_nlopt_algorithm = nlopt::LD_TNEWTON_PRECOND_RESTART;
106  break;
108  mango_nlopt_algorithm = nlopt::LD_TNEWTON_PRECOND;
109  break;
111  mango_nlopt_algorithm = nlopt::LD_TNEWTON_RESTART;
112  break;
114  mango_nlopt_algorithm = nlopt::LD_TNEWTON;
115  break;
117  mango_nlopt_algorithm = nlopt::LD_VAR1;
118  break;
120  mango_nlopt_algorithm = nlopt::LD_VAR2;
121  break;
122  // </nlopt_algorithms>
123 
124  default:
125  throw std::runtime_error("Error in optimize_nlopt. Unexpected algorithm!");
126  }
127 
128  // I'll use the C interface of nlopt rather than the C++ interface, because the C++ interface requires
129  // converting things back and forth between double[] and std::vector<double>.
130  // However, some nlopt constants like NLOPT_LN_NELDERMEAD conflict with mango's constants.
131  // We can get around the latter issue by using the C++ nlopt:: constants and casting them
132  // from nlopt::algorithm to nlopt_algorithm.
133  nlopt_opt opt = nlopt_create((nlopt_algorithm)mango_nlopt_algorithm, solver->N_parameters);
134  // nlopt_set_min_objective(opt, (nlopt_func) &mango::problem::nlopt_objective_function, (void*)this);
135  nlopt_set_min_objective(opt, (nlopt_func) &mango::Package_nlopt::nlopt_objective_function, (void*)solver);
136 
137  nlopt_set_maxeval(opt, solver->max_function_and_gradient_evaluations);
138 
139  if (solver->bound_constraints_set) {
140  nlopt_set_lower_bounds(opt, solver->lower_bounds);
141  nlopt_set_upper_bounds(opt, solver->upper_bounds);
142  }
143 
144  double final_objective_function;
145  nlopt_result result = nlopt_optimize(opt, solver->state_vector, &final_objective_function);
146 
147  switch (result) {
148  case nlopt::SUCCESS:
149  if (solver->verbose > 0) std::cout << "nlopt generic success" << std::endl;
150  break;
151  case nlopt::STOPVAL_REACHED:
152  if (solver->verbose > 0) std::cout << "nlopt success: stopval reached." << std::endl;
153  break;
154  case nlopt::FTOL_REACHED:
155  if (solver->verbose > 0) std::cout << "nlopt success: ftol reached." << std::endl;
156  break;
157  case nlopt::XTOL_REACHED:
158  if (solver->verbose > 0) std::cout << "nlopt success: xtol reached." << std::endl;
159  break;
160  case nlopt::MAXEVAL_REACHED:
161  if (solver->verbose > 0) std::cout << "nlopt: maxeval reached" << std::endl;
162  break;
163  case nlopt::MAXTIME_REACHED:
164  if (solver->verbose > 0) std::cout << "nlopt: maxtime reached." << std::endl;
165  break;
166  case nlopt::FAILURE:
167  if (solver->verbose > 0) std::cerr << "WARNING!!! NLOPT reported a generic failure. Results may or may not make sense." << std::endl;
168  break;
169  case nlopt::INVALID_ARGS:
170  throw std::runtime_error("nlopt failure: invalid arguments!");
171  break;
172  case nlopt::OUT_OF_MEMORY:
173  throw std::runtime_error("nlopt out of memory!");
174  break;
175  case nlopt::ROUNDOFF_LIMITED:
176  if (solver->verbose > 0) std::cerr << "nlopt: WARNING! Limited by roundoff. Results may or may not make sense." << std::endl;
177  break;
178  case nlopt::FORCED_STOP:
179  throw std::runtime_error("nlopt forced stop!");
180  break;
181  default:
182  throw std::runtime_error("nlopt unexpected return value!");
183  }
184 
185  nlopt_destroy(opt);
186 
187 #else
188  throw std::runtime_error("Error! A NLOPT algorithm was requested, but Mango was compiled without NLOPT support.");
189 #endif
190 }
191 
192 
193 double mango::Package_nlopt::nlopt_objective_function(unsigned n, const double* x, double* grad, void* f_data) {
194  mango::Solver* solver = (mango::Solver*) f_data;
195  bool failed;
196  double f;
197 
198  if (solver->verbose > 0) std::cout << "Hello from nlopt_objective_function" << std::endl << std::flush;
199 
200  if (grad == NULL) {
201  // Gradient is not required.
202  solver->objective_function_wrapper(x, &f, &failed);
203  } else {
204  // Gradient is required.
205  solver->finite_difference_gradient(x, &f, grad);
206  }
207 
208  if (failed) f = mango::NUMBER_FOR_FAILED;
209 
210  if (solver->verbose > 0) std::cout << "Good-bye from nlopt_objective_function" << std::endl << std::flush;
211 
212  return f;
213 }
214 
215 
217  throw std::runtime_error("Error! mango somehow got to Package_nlopt::optimize_least_squares. This should never happen.");
218 }
mango::NLOPT_LD_CCSAQ
@ NLOPT_LD_CCSAQ
Definition: mango.hpp:98
mango::NLOPT_LN_NELDERMEAD
@ NLOPT_LN_NELDERMEAD
Definition: mango.hpp:95
mango::Solver::finite_difference_gradient
virtual void finite_difference_gradient(const double *, double *, double *)
Definition: Solver.cpp:82
mango::NLOPT_LD_MMA
@ NLOPT_LD_MMA
Definition: mango.hpp:97
mango::NLOPT_GN_DIRECT_L_NOSCAL
@ NLOPT_GN_DIRECT_L_NOSCAL
Definition: mango.hpp:87
mango::NLOPT_LN_PRAXIS
@ NLOPT_LN_PRAXIS
Definition: mango.hpp:94
mango::Solver::verbose
int verbose
Definition: Solver.hpp:63
mango::NLOPT_LD_VAR1
@ NLOPT_LD_VAR1
Definition: mango.hpp:105
mango::NLOPT_LD_SLSQP
@ NLOPT_LD_SLSQP
Definition: mango.hpp:99
mango::Solver::objective_function_wrapper
virtual void objective_function_wrapper(const double *, double *, bool *)
Definition: objective_function_wrapper.cpp:27
mango::NLOPT_LD_TNEWTON_RESTART
@ NLOPT_LD_TNEWTON_RESTART
Definition: mango.hpp:103
mango::Least_squares_solver
Definition: Least_squares_solver.hpp:28
mango::NLOPT_LD_TNEWTON
@ NLOPT_LD_TNEWTON
Definition: mango.hpp:104
mango::NLOPT_GN_CRS2_LM
@ NLOPT_GN_CRS2_LM
Definition: mango.hpp:91
Solver.hpp
mango::NLOPT_GN_DIRECT_L
@ NLOPT_GN_DIRECT_L
Definition: mango.hpp:84
mango::NLOPT_GN_DIRECT_NOSCAL
@ NLOPT_GN_DIRECT_NOSCAL
Definition: mango.hpp:86
mango::NLOPT_LN_SBPLX
@ NLOPT_LN_SBPLX
Definition: mango.hpp:96
mango::NLOPT_LN_COBYLA
@ NLOPT_LN_COBYLA
Definition: mango.hpp:92
mango.hpp
mango::NLOPT_LN_BOBYQA
@ NLOPT_LN_BOBYQA
Definition: mango.hpp:93
mango::Solver::N_parameters
int N_parameters
Definition: Solver.hpp:43
mango::NLOPT_LD_LBFGS
@ NLOPT_LD_LBFGS
Definition: mango.hpp:100
mango::NLOPT_GN_ORIG_DIRECT
@ NLOPT_GN_ORIG_DIRECT
Definition: mango.hpp:89
mango::NUMBER_FOR_FAILED
const double NUMBER_FOR_FAILED
A large finite number.
Definition: mango.hpp:52
mango::Solver::algorithm
algorithm_type algorithm
Definition: Solver.hpp:42
mango::Package_nlopt::optimize_least_squares
void optimize_least_squares(Least_squares_solver *)
Definition: optimize_nlopt.cpp:216
mango::Package_nlopt::optimize
void optimize(Solver *)
Definition: optimize_nlopt.cpp:31
mango::NLOPT_LD_TNEWTON_PRECOND_RESTART
@ NLOPT_LD_TNEWTON_PRECOND_RESTART
Definition: mango.hpp:101
mango::NLOPT_GN_DIRECT
@ NLOPT_GN_DIRECT
Definition: mango.hpp:83
mango::Solver
Definition: Solver.hpp:31
mango::NLOPT_GN_DIRECT_L_RAND_NOSCAL
@ NLOPT_GN_DIRECT_L_RAND_NOSCAL
Definition: mango.hpp:88
Package_nlopt.hpp
mango::NLOPT_LD_VAR2
@ NLOPT_LD_VAR2
Definition: mango.hpp:106
mango::NLOPT_GN_DIRECT_L_RAND
@ NLOPT_GN_DIRECT_L_RAND
Definition: mango.hpp:85
mango::NLOPT_GN_ORIG_DIRECT_L
@ NLOPT_GN_ORIG_DIRECT_L
Definition: mango.hpp:90
mango::NLOPT_LD_TNEWTON_PRECOND
@ NLOPT_LD_TNEWTON_PRECOND
Definition: mango.hpp:102