MUQ  0.4.3
NLoptOptimizer.cpp
Go to the documentation of this file.
2 
4 
5 namespace pt = boost::property_tree;
6 using namespace muq::Modeling;
7 using namespace muq::Optimization;
8 
25 
26 NLoptOptimizer::NLoptOptimizer(std::shared_ptr<ModPiece> const& cost,
27  pt::ptree const& pt) : Optimizer(cost, pt),
28  algorithm(NLOptAlgorithm(pt.get<std::string>("Algorithm"))),
29  minimize(pt.get<bool>("Minimize", true))
30 {
31 }
32 
33 
34 nlopt_algorithm NLoptOptimizer::NLOptAlgorithm(std::string const& alg) const {
35  if( alg.compare("DIRECT")==0 ) { return NLOPT_GN_DIRECT; }
36  if( alg.compare("DIRECTL")==0 ) { return NLOPT_GN_DIRECT_L; }
37  if( alg.compare("CRS")==0 ) { return NLOPT_GN_CRS2_LM; }
38  if( alg.compare("MLSL")==0 ) { return NLOPT_G_MLSL_LDS; }
39  if( alg.compare("ISRES")==0 ) { return NLOPT_GN_ISRES; }
40  if( alg.compare("COBYLA")==0 ) { return NLOPT_LN_COBYLA; }
41  if( alg.compare("BOBYQA")==0 ) { return NLOPT_LN_BOBYQA; }
42  if( alg.compare("NEWUOA")==0 ) { return NLOPT_LN_NEWUOA_BOUND; }
43  if( alg.compare("PRAXIS")==0 ) { return NLOPT_LN_PRAXIS; }
44  if( alg.compare("NM")==0 ) { return NLOPT_LN_NELDERMEAD; }
45  if( alg.compare("SBPLX")==0 ) { return NLOPT_LN_SBPLX; }
46  if( alg.compare("MMA")==0 ) { return NLOPT_LD_MMA; }
47  if( alg.compare("SLSQP")==0 ) { return NLOPT_LD_SLSQP; }
48  if( alg.compare("LBFGS")==0 ) { return NLOPT_LD_LBFGS; }
49  if( alg.compare("PreTN")==0 ) { return NLOPT_LD_TNEWTON_PRECOND_RESTART; }
50  if( alg.compare("LMVM")==0 ) { return NLOPT_LD_VAR2; }
51 
52  std::stringstream msg;
53  msg << "\nERROR: Invalid algorithm (" << alg << ") passed to NLOptAlgorithm.";
54  throw std::runtime_error(msg.str());
55 
56  return NLOPT_LN_COBYLA;
57 }
58 
59 void NLoptOptimizer::EvaluateImpl(ref_vector<boost::any> const& inputs) {
60 
61  // create the optimizer
62  auto solver = nlopt_create(algorithm, opt->inputSizes(0));
63  if( minimize )
64  nlopt_set_min_objective(solver, Cost, &opt);
65  else {
66  nlopt_set_max_objective(solver, Cost, &opt);
67  }
68 
69  if (!ineqConstraints.empty()) {
70 
71  for (int i; i<ineqConstraints.size(); ++i) {
72 
73  double ineqTol[ineqConstraints[i]->numOutputs];
74  Eigen::Map<const Eigen::VectorXd> ineqTolmap(ineqTol, ineqConstraints[i]->numOutputs);
75  const Eigen::VectorXd ineqTolEig = constraint_tol*Eigen::VectorXd::Ones(ineqConstraints[i]->numOutputs);
76 
77  nlopt_add_inequality_mconstraint(solver,
78  ineqConstraints[i]->numOutputs,
79  Constraint,
80  &ineqConstraints[i],
81  ineqTol);
82  }
83  }
84 
85  if (!eqConstraints.empty()) {
86 
87  for (int i; i<eqConstraints.size(); ++i) {
88 
89  double eqTol[eqConstraints[i]->numOutputs];
90  Eigen::Map<const Eigen::VectorXd> eqTolmap(eqTol, eqConstraints[i]->numOutputs);
91  const Eigen::VectorXd eqTolEig = constraint_tol*Eigen::VectorXd::Ones(eqConstraints[i]->numOutputs);
92 
93  nlopt_add_equality_mconstraint(solver,
94  eqConstraints[i]->numOutputs,
95  Constraint,
96  &eqConstraints[i],
97  eqTol);
98  }
99  }
100 
101  // set the tolerances
102  nlopt_set_ftol_rel(solver, ftol_rel);
103  nlopt_set_ftol_abs(solver, ftol_abs);
104  nlopt_set_xtol_rel(solver, xtol_rel);
105  nlopt_set_xtol_abs1(solver, xtol_abs);
106  nlopt_set_maxeval(solver, maxEvals);
107 
108  const Eigen::VectorXd& xinit = boost::any_cast<Eigen::VectorXd const&>(inputs.at(0));
109 
110  outputs.resize(2);
111  outputs[0] = xinit;
112  Eigen::VectorXd& xopt = boost::any_cast<Eigen::VectorXd&>(outputs.at(0));
113 
114  double minf;
115  const nlopt_result check = nlopt_optimize(solver, xopt.data(), &minf);
116 
117  if( check<0 )
118  muq::ExternalLibraryError("NLOPT has failed with flag " + std::to_string(check));
119 
120  outputs[1] = minf;
121 
122 }
123 
124 std::pair<Eigen::VectorXd, double>
125 NLoptOptimizer::Solve(std::vector<Eigen::VectorXd> const& input) {
126 
127  std::vector<boost::any> ins;
128  for (auto i : input)
129  ins.push_back(i);
130 
131  Evaluate(ins);
132 
133  return std::pair<Eigen::VectorXd, double>(boost::any_cast<Eigen::VectorXd const&>(outputs[0]),
134  boost::any_cast<double const>(outputs[1]));
135 
136 }
137 
138 double NLoptOptimizer::Cost(unsigned int n,
139  const double* x,
140  double* grad,
141  void* f_data) {
142 
143  // The constraint
144  std::shared_ptr<CostFunction> opt = *((std::shared_ptr<CostFunction>*) f_data);
145 
146  Eigen::VectorXd xeig = Eigen::Map<const Eigen::VectorXd>(x,n);
147 
148  opt->SetPoint(xeig);
149  if (grad) {
150  Eigen::Map<Eigen::VectorXd> gradmap(grad, n);
151  gradmap = opt->Gradient();
152  }
153 
154  return opt->Cost();
155 }
156 
157 
158 void NLoptOptimizer::Constraint(unsigned int m,
159  double* result,
160  unsigned int n,
161  const double* x,
162  double* grad,
163  void* f_data) {
164  // The constraint
165  std::shared_ptr<ModPiece> opt = *((std::shared_ptr<ModPiece>*) f_data);
166 
167  Eigen::Map<const Eigen::VectorXd> xmap(x, n);
168  const Eigen::VectorXd& xeig = xmap;
169 
170  if( grad ) {
171 
172  Eigen::Map<Eigen::MatrixXd> gradmap(grad, n, m);
173  const Eigen::MatrixXd& gradeig =
174  opt->Jacobian(0, 0, xeig);
175 
176  gradmap = gradeig;
177 
178  }
179 
180  Eigen::Map<Eigen::VectorXd> resultmap(result, m);
181  std::vector<Eigen::VectorXd> resulteig = opt->Evaluate(xeig);
182  resultmap = resulteig.at(0);
183 }
REGISTER_OPTIMIZER(DIRECT, NLoptOptimizer) REGISTER_OPTIMIZER(DIRECTL
A MUQ dependency has failed.
Definition: Exceptions.h:48
Provides an abstract interface for defining vector-valued model components.
Definition: ModPiece.h:148
Solve an optimization problem.
Definition: Optimizer.h:21
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
Definition: WorkPiece.h:37
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.h:3956
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25172