ipopt_interface.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 
27 #include "ipopt_interface.hpp"
28 #include "ipopt_nlp.hpp"
29 #include "casadi/core/casadi_misc.hpp"
30 #include "../../core/global_options.hpp"
31 #include "../../core/casadi_interrupt.hpp"
32 #include "../../core/convexify.hpp"
33 
34 #include <ctime>
35 #include <stdlib.h>
36 #include <iostream>
37 #include <iomanip>
38 #include <chrono>
39 
40 #include <IpIpoptApplication.hpp>
41 
42 #include <ipopt_runtime_str.h>
43 
44 namespace casadi {
45  extern "C"
46  int CASADI_NLPSOL_IPOPT_EXPORT
47  casadi_register_nlpsol_ipopt(Nlpsol::Plugin* plugin) {
48  plugin->creator = IpoptInterface::creator;
49  plugin->name = "ipopt";
50  plugin->doc = IpoptInterface::meta_doc.c_str();
51  plugin->version = CASADI_VERSION;
52  plugin->options = &IpoptInterface::options_;
53  plugin->deserialize = &IpoptInterface::deserialize;
54  return 0;
55  }
56 
57  extern "C"
58  void CASADI_NLPSOL_IPOPT_EXPORT casadi_load_nlpsol_ipopt() {
60  }
61 
62  IpoptInterface::IpoptInterface(const std::string& name, const Function& nlp)
63  : Nlpsol(name, nlp) {
64  }
65 
67  clear_mem();
68  }
69 
71  = {{&Nlpsol::options_},
72  {{"pass_nonlinear_variables",
73  {OT_BOOL,
74  "Pass list of variables entering nonlinearly to IPOPT"}},
75  {"ipopt",
76  {OT_DICT,
77  "Options to be passed to IPOPT"}},
78  {"var_string_md",
79  {OT_DICT,
80  "String metadata (a dictionary with lists of strings) "
81  "about variables to be passed to IPOPT"}},
82  {"var_integer_md",
83  {OT_DICT,
84  "Integer metadata (a dictionary with lists of integers) "
85  "about variables to be passed to IPOPT"}},
86  {"var_numeric_md",
87  {OT_DICT,
88  "Numeric metadata (a dictionary with lists of reals) about "
89  "variables to be passed to IPOPT"}},
90  {"con_string_md",
91  {OT_DICT,
92  "String metadata (a dictionary with lists of strings) about "
93  "constraints to be passed to IPOPT"}},
94  {"con_integer_md",
95  {OT_DICT,
96  "Integer metadata (a dictionary with lists of integers) "
97  "about constraints to be passed to IPOPT"}},
98  {"con_numeric_md",
99  {OT_DICT,
100  "Numeric metadata (a dictionary with lists of reals) about "
101  "constraints to be passed to IPOPT"}},
102  {"hess_lag",
103  {OT_FUNCTION,
104  "Function for calculating the Hessian of the Lagrangian (autogenerated by default)"}},
105  {"jac_g",
106  {OT_FUNCTION,
107  "Function for calculating the Jacobian of the constraints "
108  "(autogenerated by default)"}},
109  {"grad_f",
110  {OT_FUNCTION,
111  "Function for calculating the gradient of the objective "
112  "(column, autogenerated by default)"}},
113  {"convexify_strategy",
114  {OT_STRING,
115  "NONE|regularize|eigen-reflect|eigen-clip. "
116  "Strategy to convexify the Lagrange Hessian before passing it to the solver."}},
117  {"convexify_margin",
118  {OT_DOUBLE,
119  "When using a convexification strategy, make sure that "
120  "the smallest eigenvalue is at least this (default: 1e-7)."}},
121  {"max_iter_eig",
122  {OT_DOUBLE,
123  "Maximum number of iterations to compute an eigenvalue decomposition (default: 50)."}},
124  {"clip_inactive_lam",
125  {OT_BOOL,
126  "Explicitly set Lagrange multipliers to 0 when bound is deemed inactive "
127  "(default: false)."}},
128  {"inactive_lam_strategy",
129  {OT_STRING,
130  "Strategy to detect if a bound is inactive. "
131  "RELTOL: use solver-defined constraint tolerance * inactive_lam_value|"
132  "abstol: use inactive_lam_value"}},
133  {"inactive_lam_value",
134  {OT_DOUBLE,
135  "Value used in inactive_lam_strategy (default: 10)."}}
136  }
137  };
138 
139  void IpoptInterface::init(const Dict& opts) {
140  // Call the init method of the base class
141  Nlpsol::init(opts);
142 
143  // Default options
145 
146  std::string convexify_strategy = "none";
147  double convexify_margin = 1e-7;
148  casadi_int max_iter_eig = 200;
149 
150  clip_inactive_lam_ = false;
151  inactive_lam_strategy_ = "reltol";
152  inactive_lam_value_ = 10;
153 
154  // Read user options
155  for (auto&& op : opts) {
156  if (op.first=="ipopt") {
157  opts_ = op.second;
158  } else if (op.first=="pass_nonlinear_variables") {
159  pass_nonlinear_variables_ = op.second;
160  } else if (op.first=="var_string_md") {
161  var_string_md_ = op.second;
162  } else if (op.first=="var_integer_md") {
163  var_integer_md_ = op.second;
164  } else if (op.first=="var_numeric_md") {
165  var_numeric_md_ = op.second;
166  } else if (op.first=="con_string_md") {
167  con_string_md_ = op.second;
168  } else if (op.first=="con_integer_md") {
169  con_integer_md_ = op.second;
170  } else if (op.first=="con_numeric_md") {
171  con_numeric_md_ = op.second;
172  } else if (op.first=="hess_lag") {
173  Function f = op.second;
174  casadi_assert_dev(f.n_in()==4);
175  casadi_assert_dev(f.n_out()==1);
176  set_function(f, "nlp_hess_l");
177  } else if (op.first=="jac_g") {
178  Function f = op.second;
179  casadi_assert_dev(f.n_in()==2);
180  casadi_assert_dev(f.n_out()==2);
181  set_function(f, "nlp_jac_g");
182  } else if (op.first=="grad_f") {
183  Function f = op.second;
184  casadi_assert_dev(f.n_in()==2);
185  casadi_assert_dev(f.n_out()==2);
186  set_function(f, "nlp_grad_f");
187  } else if (op.first=="convexify_strategy") {
188  convexify_strategy = op.second.to_string();
189  } else if (op.first=="convexify_margin") {
190  convexify_margin = op.second;
191  } else if (op.first=="max_iter_eig") {
192  max_iter_eig = op.second;
193  } else if (op.first=="clip_inactive_lam") {
194  clip_inactive_lam_ = op.second;
195  } else if (op.first=="inactive_lam_strategy") {
196  inactive_lam_strategy_ = op.second.to_string();
197  } else if (op.first=="inactive_lam_value") {
198  inactive_lam_value_ = op.second;
199  }
200  }
201 
202  // Do we need second order derivatives?
203  exact_hessian_ = true;
204  auto hessian_approximation = opts_.find("hessian_approximation");
205  if (hessian_approximation!=opts_.end()) {
206  exact_hessian_ = hessian_approximation->second == "exact";
207  }
208 
209  // Setup NLP functions
210  create_function("nlp_f", {"x", "p"}, {"f"});
211  create_function("nlp_g", {"x", "p"}, {"g"});
212  if (!has_function("nlp_grad_f")) {
213  create_function("nlp_grad_f", {"x", "p"}, {"f", "grad:f:x"});
214  }
215  if (!has_function("nlp_jac_g")) {
216  create_function("nlp_jac_g", {"x", "p"}, {"g", "jac:g:x"});
217  }
218  jacg_sp_ = get_function("nlp_jac_g").sparsity_out(1);
219  casadi_assert(jacg_sp_.size1()==ng_, "nlp_jac_g must have " + str(ng_) +
220  " rows, but has " + str(jacg_sp_.size1()) + " instead.");
221  casadi_assert(jacg_sp_.size2()==nx_, "nlp_jac_g must have " + str(nx_) +
222  " columns, but has " + str(jacg_sp_.size2()) + " instead.");
223 
224  convexify_ = false;
225 
226  // Allocate temporary work vectors
227  if (exact_hessian_) {
228  if (!has_function("nlp_hess_l")) {
229  create_function("nlp_hess_l", {"x", "p", "lam:f", "lam:g"},
230  {"triu:hess:gamma:x:x"}, {{"gamma", {"f", "g"}}});
231  }
232  hesslag_sp_ = get_function("nlp_hess_l").sparsity_out(0);
233  casadi_assert(hesslag_sp_.is_triu(), "Hessian must be upper triangular");
234  if (convexify_strategy!="none") {
235  convexify_ = true;
236  Dict opts;
237  opts["strategy"] = convexify_strategy;
238  opts["margin"] = convexify_margin;
239  opts["max_iter_eig"] = max_iter_eig;
240  opts["verbose"] = verbose_;
242  }
243  } else if (pass_nonlinear_variables_) {
244  nl_ex_ = oracle_.which_depends("x", {"f", "g"}, 2, false);
245  }
246 
247  // Allocate work vectors
248  alloc_w(ng_, true); // gk_
249  alloc_w(nx_, true); // grad_fk_
250  alloc_w(jacg_sp_.nnz(), true); // jac_gk_
251  if (exact_hessian_) {
252  alloc_w(hesslag_sp_.nnz(), true); // hess_lk_
253  }
254  if (convexify_) {
257  }
258  }
259 
260  int IpoptInterface::init_mem(void* mem) const {
261  if (Nlpsol::init_mem(mem)) return 1;
262  auto m = static_cast<IpoptMemory*>(mem);
263 
264  // Start an IPOPT application
265  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app = new Ipopt::SmartPtr<Ipopt::IpoptApplication>();
266  m->app = static_cast<void*>(app);
267  *app = new Ipopt::IpoptApplication(false);
268 
269  // Direct output through casadi::uout()
270  StreamJournal* jrnl_raw = new StreamJournal("console", J_ITERSUMMARY);
271  jrnl_raw->SetOutputStream(&casadi::uout());
272  jrnl_raw->SetPrintLevel(J_DBG, J_NONE);
273  SmartPtr<Journal> jrnl = jrnl_raw;
274  (*app)->Jnlst()->AddJournal(jrnl);
275 
276  // Create an Ipopt user class -- need to use Ipopts spart pointer class
277  Ipopt::SmartPtr<Ipopt::TNLP> *userclass = new Ipopt::SmartPtr<Ipopt::TNLP>();
278  m->userclass = static_cast<void*>(userclass);
279  *userclass = new IpoptUserClass(*this, m);
280 
281  if (verbose_) {
282  uout() << "There are " << nx_ << " variables and " << ng_ << " constraints." << std::endl;
283  if (exact_hessian_) uout() << "Using exact Hessian" << std::endl;
284  else uout() << "Using limited memory Hessian approximation" << std::endl;
285  }
286 
287  // Get all options available in (s)IPOPT
288  auto regops = (*app)->RegOptions()->RegisteredOptionsList();
289 
290  Dict options = Options::sanitize(opts_);
291  // Replace resto group with prefixes
292  auto it = options.find("resto");
293  if (it!=options.end()) {
294  Dict resto_options = it->second;
295  options.erase(it);
296  for (auto&& op : resto_options) {
297  options["resto." + op.first] = op.second;
298  }
299  }
300 
301  // Pass all the options to ipopt
302  for (auto&& op : options) {
303 
304  // There might be options with a resto prefix.
305  std::string option_name = op.first;
306  if (startswith(option_name, "resto.")) {
307  option_name = option_name.substr(6);
308  }
309 
310  // Find the option
311  auto regops_it = regops.find(option_name);
312  if (regops_it==regops.end()) {
313  casadi_error("No such IPOPT option: " + op.first);
314  }
315 
316  // Get the type
317  Ipopt::RegisteredOptionType ipopt_type = regops_it->second->Type();
318 
319  // Pass to IPOPT
320  bool ret;
321  switch (ipopt_type) {
322  case Ipopt::OT_Number:
323  ret = (*app)->Options()->SetNumericValue(op.first, op.second.to_double(), false);
324  break;
325  case Ipopt::OT_Integer:
326  ret = (*app)->Options()->SetIntegerValue(op.first, op.second.to_int(), false);
327  break;
328  case Ipopt::OT_String:
329  ret = (*app)->Options()->SetStringValue(op.first, op.second.to_string(), false);
330  break;
331  case Ipopt::OT_Unknown:
332  default:
333  casadi_warning("Cannot handle option \"" + op.first + "\", ignored");
334  continue;
335  }
336  if (!ret) casadi_error("Invalid options were detected by Ipopt.");
337  }
338 
339  // Override IPOPT's default linear solver
340  if (opts_.find("linear_solver") == opts_.end()) {
341  char * default_solver = getenv("IPOPT_DEFAULT_LINEAR_SOLVER");
342  if (default_solver) {
343  bool ret = (*app)->Options()->SetStringValue("linear_solver", default_solver, false);
344  casadi_assert(ret, "Corrupted IPOPT_DEFAULT_LINEAR_SOLVER environmental variable");
345  } else {
346  // Fall back to MUMPS (avoid user issues after SPRAL was added to binaries and
347  // chosen default by Ipopt)
348  bool ret = (*app)->Options()->SetStringValue("linear_solver", "mumps", false);
349  casadi_assert_dev(ret);
350  }
351 
352  }
353 
354  // Intialize the IpoptApplication and process the options
355  Ipopt::ApplicationReturnStatus status = (*app)->Initialize();
356  casadi_assert(status == Solve_Succeeded, "Error during IPOPT initialization");
357 
358  if (convexify_) m->add_stat("convexify");
359  return 0;
360  }
361 
362  void IpoptInterface::set_work(void* mem, const double**& arg, double**& res,
363  casadi_int*& iw, double*& w) const {
364  auto m = static_cast<IpoptMemory*>(mem);
365 
366  // Set work in base classes
367  Nlpsol::set_work(mem, arg, res, iw, w);
368 
369  // Work vectors
370  m->gk = w; w += ng_;
371  m->grad_fk = w; w += nx_;
372  m->jac_gk = w; w += jacg_sp_.nnz();
373  if (exact_hessian_) {
374  m->hess_lk = w; w += hesslag_sp_.nnz();
375  }
376  }
377 
378  inline const char* return_status_string(Ipopt::ApplicationReturnStatus status) {
379  switch (status) {
380  case Solve_Succeeded:
381  return "Solve_Succeeded";
382  case Solved_To_Acceptable_Level:
383  return "Solved_To_Acceptable_Level";
384  case Infeasible_Problem_Detected:
385  return "Infeasible_Problem_Detected";
386  case Search_Direction_Becomes_Too_Small:
387  return "Search_Direction_Becomes_Too_Small";
388  case Diverging_Iterates:
389  return "Diverging_Iterates";
390  case User_Requested_Stop:
391  return "User_Requested_Stop";
392  case Maximum_Iterations_Exceeded:
393  return "Maximum_Iterations_Exceeded";
394  case Restoration_Failed:
395  return "Restoration_Failed";
396  case Error_In_Step_Computation:
397  return "Error_In_Step_Computation";
398  case Not_Enough_Degrees_Of_Freedom:
399  return "Not_Enough_Degrees_Of_Freedom";
400  case Invalid_Problem_Definition:
401  return "Invalid_Problem_Definition";
402  case Invalid_Option:
403  return "Invalid_Option";
404  case Invalid_Number_Detected:
405  return "Invalid_Number_Detected";
406  case Unrecoverable_Exception:
407  return "Unrecoverable_Exception";
408  case NonIpopt_Exception_Thrown:
409  return "NonIpopt_Exception_Thrown";
410  case Insufficient_Memory:
411  return "Insufficient_Memory";
412  case Internal_Error:
413  return "Internal_Error";
414  case Maximum_CpuTime_Exceeded:
415  return "Maximum_CpuTime_Exceeded";
416  case Feasible_Point_Found:
417  return "Feasible_Point_Found";
418 #if (IPOPT_VERSION_MAJOR > 3) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR >= 14)
419  case Maximum_WallTime_Exceeded:
420  return "Maximum_WallTime_Exceeded";
421 #endif
422  }
423  return "Unknown";
424  }
425 
426  int IpoptInterface::solve(void* mem) const {
427  auto m = static_cast<IpoptMemory*>(mem);
428  auto d_nlp = &m->d_nlp;
429 
430  // Reset statistics
431  m->inf_pr.clear();
432  m->inf_du.clear();
433  m->mu.clear();
434  m->d_norm.clear();
435  m->regularization_size.clear();
436  m->alpha_pr.clear();
437  m->alpha_du.clear();
438  m->obj.clear();
439  m->ls_trials.clear();
440 
441  // Reset number of iterations
442  m->n_iter = 0;
443 
444  // Get back the smart pointers
445  Ipopt::SmartPtr<Ipopt::TNLP> *userclass =
446  static_cast<Ipopt::SmartPtr<Ipopt::TNLP>*>(m->userclass);
447  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app =
448  static_cast<Ipopt::SmartPtr<Ipopt::IpoptApplication>*>(m->app);
449 
450  // Ask Ipopt to solve the problem
451  Ipopt::ApplicationReturnStatus status = (*app)->OptimizeTNLP(*userclass);
452  m->return_status = return_status_string(status);
453  m->success = status==Solve_Succeeded || status==Solved_To_Acceptable_Level
454  || status==Feasible_Point_Found;
455  if (status==Maximum_Iterations_Exceeded ||
456  status==Maximum_CpuTime_Exceeded) m->unified_return_status = SOLVER_RET_LIMITED;
457 
458 #if (IPOPT_VERSION_MAJOR > 3) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR >= 14)
459  if (status==Maximum_WallTime_Exceeded) m->unified_return_status = SOLVER_RET_LIMITED;
460 #endif
461 
462  // Save results to outputs
463  casadi_copy(m->gk, ng_, d_nlp->z + nx_);
464 
465  if (clip_inactive_lam_) {
466  // Compute a margin
467  double margin;
468  if (inactive_lam_strategy_=="abstol") {
469  margin = inactive_lam_value_;
470  } else if (inactive_lam_strategy_=="reltol") {
471  double constr_viol_tol;
472  (*app)->Options()->GetNumericValue("constr_viol_tol", constr_viol_tol, "");
473  if (status==Solved_To_Acceptable_Level) {
474  (*app)->Options()->GetNumericValue("acceptable_constr_viol_tol", constr_viol_tol, "");
475  }
476  margin = inactive_lam_value_*constr_viol_tol;
477  } else {
478  casadi_error("inactive_lam_strategy '" + inactive_lam_strategy_ +
479  "' unknown. Use 'abstol' or reltol'.");
480  }
481 
482  for (casadi_int i=0; i<nx_ + ng_; ++i) {
483  // Sufficiently inactive -> make multiplier exactly zero
484  if (d_nlp->lam[i]>0 && d_nlp->ubz[i] - d_nlp->z[i] > margin) d_nlp->lam[i]=0;
485  if (d_nlp->lam[i]<0 && d_nlp->z[i] - d_nlp->lbz[i] > margin) d_nlp->lam[i]=0;
486  }
487  }
488 
489  return 0;
490  }
491 
493  intermediate_callback(IpoptMemory* m, const double* x, const double* z_L, const double* z_U,
494  const double* g, const double* lambda, double obj_value, int iter,
495  double inf_pr, double inf_du, double mu, double d_norm,
496  double regularization_size, double alpha_du, double alpha_pr,
497  int ls_trials, bool full_callback) const {
498  auto d_nlp = &m->d_nlp;
499  m->n_iter += 1;
500  try {
501  m->inf_pr.push_back(inf_pr);
502  m->inf_du.push_back(inf_du);
503  m->mu.push_back(mu);
504  m->d_norm.push_back(d_norm);
505  m->regularization_size.push_back(regularization_size);
506  m->alpha_pr.push_back(alpha_pr);
507  m->alpha_du.push_back(alpha_du);
508  m->ls_trials.push_back(ls_trials);
509  m->obj.push_back(obj_value);
510  if (!fcallback_.is_null()) {
511  ScopedTiming tic(m->fstats.at("callback_fun"));
512  if (full_callback) {
513  casadi_copy(x, nx_, d_nlp->z);
514  for (casadi_int i=0; i<nx_; ++i) {
515  d_nlp->lam[i] = z_U[i]-z_L[i];
516  }
517  casadi_copy(lambda, ng_, d_nlp->lam + nx_);
518  casadi_copy(g, ng_, m->gk);
519  } else {
520  if (iter==0) {
521  uerr()
522  << "Warning: intermediate_callback is disfunctional in your installation. "
523  "You will only be able to use stats(). "
524  "See https://github.com/casadi/casadi/wiki/enableIpoptCallback to enable it."
525  << std::endl;
526  }
527  }
528 
529  // Inputs
530  std::fill_n(m->arg, fcallback_.n_in(), nullptr);
531  if (full_callback) {
532  // The values used below are meaningless
533  // when not doing a full_callback
534  m->arg[NLPSOL_X] = x;
535  m->arg[NLPSOL_F] = &obj_value;
536  m->arg[NLPSOL_G] = g;
537  m->arg[NLPSOL_LAM_P] = nullptr;
538  m->arg[NLPSOL_LAM_X] = d_nlp->lam;
539  m->arg[NLPSOL_LAM_G] = d_nlp->lam + nx_;
540  }
541 
542  // Outputs
543  std::fill_n(m->res, fcallback_.n_out(), nullptr);
544  double ret_double;
545  m->res[0] = &ret_double;
546 
547  fcallback_(m->arg, m->res, m->iw, m->w, 0);
548  casadi_int ret = static_cast<casadi_int>(ret_double);
549 
550  return !ret;
551  } else {
552  return 1;
553  }
554 
555  } catch(KeyboardInterruptException& ex) {
556  return 0;
557  } catch(std::exception& ex) {
558  casadi_warning("intermediate_callback: " + std::string(ex.what()));
559  if (iteration_callback_ignore_errors_) return 1;
560  return 0;
561  }
562  }
563 
565  finalize_solution(IpoptMemory* m, const double* x, const double* z_L, const double* z_U,
566  const double* g, const double* lambda, double obj_value,
567  int iter_count) const {
568  auto d_nlp = &m->d_nlp;
569  try {
570  // Get primal solution
571  casadi_copy(x, nx_, d_nlp->z);
572 
573  // Get optimal cost
574  d_nlp->objective = obj_value;
575 
576  // Get dual solution (simple bounds)
577  for (casadi_int i=0; i<nx_; ++i) {
578  d_nlp->lam[i] = z_U[i]-z_L[i];
579  }
580 
581  // Get dual solution (nonlinear bounds)
582  casadi_copy(lambda, ng_, d_nlp->lam + nx_);
583 
584  // Get the constraints
585  casadi_copy(g, ng_, m->gk);
586 
587  // Get statistics
588  m->iter_count = iter_count;
589 
590  } catch(std::exception& ex) {
591  uerr() << "finalize_solution failed: " << ex.what() << std::endl;
592  }
593  }
594 
596  get_bounds_info(IpoptMemory* m, double* x_l, double* x_u,
597  double* g_l, double* g_u) const {
598  auto d_nlp = &m->d_nlp;
599  try {
600  casadi_copy(d_nlp->lbz, nx_, x_l);
601  casadi_copy(d_nlp->ubz, nx_, x_u);
602  casadi_copy(d_nlp->lbz+nx_, ng_, g_l);
603  casadi_copy(d_nlp->ubz+nx_, ng_, g_u);
604  return true;
605  } catch(std::exception& ex) {
606  uerr() << "get_bounds_info failed: " << ex.what() << std::endl;
607  return false;
608  }
609  }
610 
612  get_starting_point(IpoptMemory* m, bool init_x, double* x,
613  bool init_z, double* z_L, double* z_U,
614  bool init_lambda, double* lambda) const {
615  auto d_nlp = &m->d_nlp;
616  try {
617  // Initialize primal variables
618  if (init_x) {
619  casadi_copy(d_nlp->z, nx_, x);
620  }
621 
622  // Initialize dual variables (simple bounds)
623  if (init_z) {
624  for (casadi_int i=0; i<nx_; ++i) {
625  z_L[i] = std::max(0., -d_nlp->lam[i]);
626  z_U[i] = std::max(0., d_nlp->lam[i]);
627  }
628  }
629 
630  // Initialize dual variables (nonlinear bounds)
631  if (init_lambda) {
632  casadi_copy(d_nlp->lam + nx_, ng_, lambda);
633  }
634 
635  return true;
636  } catch(std::exception& ex) {
637  uerr() << "get_starting_point failed: " << ex.what() << std::endl;
638  return false;
639  }
640  }
641 
642  void IpoptInterface::get_nlp_info(IpoptMemory* m, int& nx, int& ng,
643  int& nnz_jac_g, int& nnz_h_lag) const {
644  try {
645  // Number of variables
646  nx = nx_;
647 
648  // Number of constraints
649  ng = ng_;
650 
651  // Number of Jacobian nonzeros
652  nnz_jac_g = ng_==0 ? 0 : jacg_sp_.nnz();
653 
654  // Number of Hessian nonzeros (only upper triangular half)
655  nnz_h_lag = exact_hessian_ ? hesslag_sp_.nnz() : 0;
656 
657  } catch(std::exception& ex) {
658  uerr() << "get_nlp_info failed: " << ex.what() << std::endl;
659  }
660  }
661 
663  try {
665  // No Hessian has been interfaced
666  return -1;
667  } else {
668  // Number of variables that appear nonlinearily
669  int nv = 0;
670  for (auto&& i : nl_ex_) if (i) nv++;
671  return nv;
672  }
673  } catch(std::exception& ex) {
674  uerr() << "get_number_of_nonlinear_variables failed: " << ex.what() << std::endl;
675  return -1;
676  }
677  }
678 
680  get_list_of_nonlinear_variables(int num_nonlin_vars, int* pos_nonlin_vars) const {
681  try {
682  for (int i=0; i<nl_ex_.size(); ++i) {
683  if (nl_ex_[i]) *pos_nonlin_vars++ = i;
684  }
685  return true;
686  } catch(std::exception& ex) {
687  uerr() << "get_list_of_nonlinear_variables failed: " << ex.what() << std::endl;
688  return false;
689  }
690  }
691 
693  get_var_con_metadata(std::map<std::string, std::vector<std::string> >& var_string_md,
694  std::map<std::string, std::vector<int> >& var_integer_md,
695  std::map<std::string, std::vector<double> >& var_numeric_md,
696  std::map<std::string, std::vector<std::string> >& con_string_md,
697  std::map<std::string, std::vector<int> >& con_integer_md,
698  std::map<std::string, std::vector<double> >& con_numeric_md) const {
699  for (auto&& op : var_string_md_) var_string_md[op.first] = op.second;
700  for (auto&& op : var_integer_md_) var_integer_md[op.first] = op.second;
701  for (auto&& op : var_numeric_md_) var_numeric_md[op.first] = op.second;
702  for (auto&& op : con_string_md_) con_string_md[op.first] = op.second;
703  for (auto&& op : con_integer_md_) con_integer_md[op.first] = op.second;
704  for (auto&& op : con_numeric_md_) con_numeric_md[op.first] = op.second;
705  return true;
706  }
707 
709  this->app = nullptr;
710  this->userclass = nullptr;
711  this->return_status = "Unset";
712  }
713 
715  // Free Ipopt application instance (or rather, the smart pointer holding it)
716  if (this->app != nullptr) {
717  delete static_cast<Ipopt::SmartPtr<Ipopt::IpoptApplication>*>(this->app);
718  }
719 
720  // Free Ipopt user class (or rather, the smart pointer holding it)
721  if (this->userclass != nullptr) {
722  delete static_cast<Ipopt::SmartPtr<Ipopt::TNLP>*>(this->userclass);
723  }
724  }
725 
726  Dict IpoptInterface::get_stats(void* mem) const {
727  Dict stats = Nlpsol::get_stats(mem);
728  auto m = static_cast<IpoptMemory*>(mem);
729  stats["return_status"] = m->return_status;
730  stats["iter_count"] = m->iter_count;
731  if (!m->inf_pr.empty()) {
732  Dict iterations;
733  iterations["inf_pr"] = m->inf_pr;
734  iterations["inf_du"] = m->inf_du;
735  iterations["mu"] = m->mu;
736  iterations["d_norm"] = m->d_norm;
737  iterations["regularization_size"] = m->regularization_size;
738  iterations["obj"] = m->obj;
739  iterations["alpha_pr"] = m->alpha_pr;
740  iterations["alpha_du"] = m->alpha_du;
741  stats["iterations"] = iterations;
742  }
743  return stats;
744  }
745 
747  int version = s.version("IpoptInterface", 1, 3);
748  s.unpack("IpoptInterface::jacg_sp", jacg_sp_);
749  s.unpack("IpoptInterface::hesslag_sp", hesslag_sp_);
750  s.unpack("IpoptInterface::exact_hessian", exact_hessian_);
751  s.unpack("IpoptInterface::opts", opts_);
752  s.unpack("IpoptInterface::pass_nonlinear_variables", pass_nonlinear_variables_);
753  s.unpack("IpoptInterface::nl_ex", nl_ex_);
754  s.unpack("IpoptInterface::var_string_md", var_string_md_);
755  s.unpack("IpoptInterface::var_integer_md", var_integer_md_);
756  s.unpack("IpoptInterface::var_numeric_md", var_numeric_md_);
757  s.unpack("IpoptInterface::con_string_md", con_string_md_);
758  s.unpack("IpoptInterface::con_integer_md", con_integer_md_);
759  s.unpack("IpoptInterface::con_numeric_md", con_numeric_md_);
760  if (version>=2) {
761  s.unpack("IpoptInterface::convexify", convexify_);
762  if (convexify_) Convexify::deserialize(s, "IpoptInterface::", convexify_data_);
763  }
764 
765  if (version>=3) {
766  s.unpack("IpoptInterface::clip_inactive_lam", clip_inactive_lam_);
767  s.unpack("IpoptInterface::inactive_lam_strategy", inactive_lam_strategy_);
768  s.unpack("IpoptInterface::inactive_lam_value", inactive_lam_value_);
769  } else {
770  clip_inactive_lam_ = false;
771  inactive_lam_strategy_ = "reltol";
772  inactive_lam_value_ = 10;
773  }
774  }
775 
778  s.version("IpoptInterface", 3);
779  s.pack("IpoptInterface::jacg_sp", jacg_sp_);
780  s.pack("IpoptInterface::hesslag_sp", hesslag_sp_);
781  s.pack("IpoptInterface::exact_hessian", exact_hessian_);
782  s.pack("IpoptInterface::opts", opts_);
783  s.pack("IpoptInterface::pass_nonlinear_variables", pass_nonlinear_variables_);
784  s.pack("IpoptInterface::nl_ex", nl_ex_);
785  s.pack("IpoptInterface::var_string_md", var_string_md_);
786  s.pack("IpoptInterface::var_integer_md", var_integer_md_);
787  s.pack("IpoptInterface::var_numeric_md", var_numeric_md_);
788  s.pack("IpoptInterface::con_string_md", con_string_md_);
789  s.pack("IpoptInterface::con_integer_md", con_integer_md_);
790  s.pack("IpoptInterface::con_numeric_md", con_numeric_md_);
791  s.pack("IpoptInterface::convexify", convexify_);
792  if (convexify_) Convexify::serialize(s, "IpoptInterface::", convexify_data_);
793 
794  s.pack("IpoptInterface::clip_inactive_lam", clip_inactive_lam_);
795  s.pack("IpoptInterface::inactive_lam_strategy", inactive_lam_strategy_);
796  s.pack("IpoptInterface::inactive_lam_value", inactive_lam_value_);
797 
798  }
799 
801  g << "ipopt_init_mem(&" + codegen_mem(g) + ");\n";
802  g << "return 0;\n";
803  }
804 
806  g << "ipopt_free_mem(&" + codegen_mem(g) + ");\n";
807  }
808 
814  g.add_dependency(get_function("nlp_f"));
815  g.add_dependency(get_function("nlp_grad_f"));
816  g.add_dependency(get_function("nlp_g"));
817  g.add_dependency(get_function("nlp_jac_g"));
818  if (exact_hessian_) {
819  g.add_dependency(get_function("nlp_hess_l"));
820  }
821  g.add_include("coin-or/IpStdCInterface.h");
822 
823  std::string name = "nlp_f";
824  std::string f = g.shorthand(g.wrapper(get_function(name), name));
825 
826  g << "bool " << f
827  << "(ipindex n, ipnumber *x, bool new_x, ipnumber *obj_value, UserDataPtr user_data) {\n";
828  g.flush(g.body);
829  g.scope_enter();
830  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
831  g << "d->arg[0] = x;\n";
832  g << "d->arg[1] = d->nlp->p;\n";
833  g << "d->res[0] = obj_value;\n";
834  std::string flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
835  g << "if (" + flag + ") return false;\n";
836  g << "return true;\n";
837  g.scope_exit();
838  g << "}\n";
839 
840  name = "nlp_g";
841  f = g.shorthand(g.wrapper(get_function(name), name));
842  g << "bool " << f
843  << "(ipindex n, ipnumber *x, bool new_x, ipindex m, ipnumber *g, UserDataPtr user_data) {\n";
844  g.flush(g.body);
845  g.scope_enter();
846  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
847  g << "d->arg[0] = x;\n";
848  g << "d->arg[1] = d->nlp->p;\n";
849  g << "d->res[0] = g;\n";
850  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
851  g << "if (" + flag + ") return false;\n";
852  g << "return true;\n";
853  g.scope_exit();
854  g << "}\n";
855 
856  name = "nlp_grad_f";
857  f = g.shorthand(g.wrapper(get_function(name), name));
858  g << "bool " << f
859  << "(ipindex n, ipnumber *x, bool new_x, ipnumber *grad_f, UserDataPtr user_data) {\n";
860  g.flush(g.body);
861  g.scope_enter();
862  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
863  g << "d->arg[0] = x;\n";
864  g << "d->arg[1] = d->nlp->p;\n";
865  g << "d->res[0] = 0;\n";
866  g << "d->res[1] = grad_f;\n";
867  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
868  g << "if (" + flag + ") return false;\n";
869  g << "return true;\n";
870  g.scope_exit();
871  g << "}\n";
872 
873  name = "nlp_jac_g";
874  f = g.shorthand(g.wrapper(get_function(name), name));
875  g << "bool " << f
876  << "(ipindex n, ipnumber *x, bool new_x, ipindex m,"
877  << " ipindex nele_jac, ipindex *iRow, ipindex *jCol, "
878  << "ipnumber *values, UserDataPtr user_data) {\n";
879  g.flush(g.body);
880  g.scope_enter();
881  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
882  g << "if (values) {\n";
883  g << "d->arg[0] = x;\n";
884  g << "d->arg[1] = d->nlp->p;\n";
885  g << "d->res[0] = 0;\n";
886  g << "d->res[1] = values;\n";
887  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
888  g << "if (" + flag + ") return false;\n";
889  g << "} else {\n";
890  g << "casadi_ipopt_sparsity(d->prob->sp_a, iRow, jCol);\n";
891  g << "}\n";
892  g << "return true;\n";
893  g.scope_exit();
894  g << "}\n";
895 
896  if (exact_hessian_) {
897  name = "nlp_hess_l";
898  f = g.shorthand(g.wrapper(get_function(name), name));
899  g << "bool " << f << "(ipindex n, ipnumber *x, bool new_x, ipnumber obj_factor,"
900  << "ipindex m, ipnumber *lambda, bool new_lambda, ipindex nele_hess, "
901  << "ipindex *iRow, ipindex *jCol, ipnumber *values, UserDataPtr user_data) {\n";
902  g.flush(g.body);
903  g.scope_enter();
904  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
905  g << "if (values) {\n";
906  g << "d->arg[0] = x;\n";
907  g << "d->arg[1] = d->nlp->p;\n";
908  g << "d->arg[2] = &obj_factor;\n";
909  g << "d->arg[3] = lambda;\n";
910  g << "d->res[0] = values;\n";
911  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
912  g << "if (" + flag + ") return false;\n";
913  g << "return true;\n";
914  g << "} else {\n";
915  g << "casadi_ipopt_sparsity(d->prob->sp_h, iRow, jCol);\n";
916  g << "}\n";
917  g << "return true;\n";
918  g.scope_exit();
919  g << "}\n";
920  }
921 }
922 
925  g.auxiliaries << g.sanitize_source(ipopt_runtime_str, {"casadi_real"});
926 
927  g.local("d", "struct casadi_ipopt_data*");
928  g.init_local("d", "&" + codegen_mem(g));
929  g.local("p", "struct casadi_ipopt_prob");
930  set_ipopt_prob(g);
931 
932  g << "casadi_ipopt_init(d, &arg, &res, &iw, &w);\n";
933  g << "casadi_ipopt_presolve(d);\n";
934 
935  // Start an IPOPT application
936  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app = new Ipopt::SmartPtr<Ipopt::IpoptApplication>();
937  *app = new Ipopt::IpoptApplication(false);
938 
939  // Get all options available in (s)IPOPT
940  auto regops = (*app)->RegOptions()->RegisteredOptionsList();
941 
942  Dict options = Options::sanitize(opts_);
943  // Replace resto group with prefixes
944  auto it = options.find("resto");
945  if (it!=options.end()) {
946  Dict resto_options = it->second;
947  options.erase(it);
948  for (auto&& op : resto_options) {
949  options["resto." + op.first] = op.second;
950  }
951  }
952 
953  // Pass all the options to ipopt
954  for (auto&& op : options) {
955 
956  // There might be options with a resto prefix.
957  std::string option_name = op.first;
958  if (startswith(option_name, "resto.")) {
959  option_name = option_name.substr(6);
960  }
961 
962  // Find the option
963  auto regops_it = regops.find(option_name);
964  if (regops_it==regops.end()) {
965  casadi_error("No such IPOPT option: " + op.first);
966  }
967 
968  // Get the type
969  Ipopt::RegisteredOptionType ipopt_type = regops_it->second->Type();
970 
971  // Pass to IPOPT
972  switch (ipopt_type) {
973  case Ipopt::OT_Number:
974  g << "AddIpoptNumOption(d->ipopt, \"" << op.first << "\""
975  << "," << op.second.to_double() << ");\n";
976  break;
977  case Ipopt::OT_Integer:
978  g << "AddIpoptIntOption(d->ipopt, \"" << op.first << "\""
979  << "," << op.second.to_int() << ");\n";
980  break;
981  case Ipopt::OT_String:
982  g << "AddIpoptStrOption(d->ipopt, \"" << op.first << "\""
983  << ",\"" << op.second.to_string() << "\");\n";
984  break;
985  case Ipopt::OT_Unknown:
986  default:
987  casadi_warning("Cannot handle option \"" + op.first + "\", ignored");
988  continue;
989  }
990  }
991 
992  // Override IPOPT's default linear solver
993  if (opts_.find("linear_solver") == opts_.end()) {
994  char * default_solver = getenv("IPOPT_DEFAULT_LINEAR_SOLVER");
995  if (default_solver) {
996  g << "AddIpoptStrOption(d->ipopt, \"linear_solver\"" << ",\"" << default_solver << "\");\n";
997  } else {
998  // Fall back to MUMPS (avoid user issues after SPRAL was added to binaries and
999  // chosen default by Ipopt)
1000  g << "AddIpoptStrOption(d->ipopt, \"linear_solver\",\"mumps\");\n";
1001  }
1002 
1003  }
1004 
1005  delete app;
1006 
1007  // Options
1008  g << "casadi_ipopt_solve(d);\n";
1009 
1010  codegen_body_exit(g);
1011 
1012  if (error_on_fail_) {
1013  g << "return d->unified_return_status;\n";
1014  } else {
1015  g << "return 0;\n";
1016  }
1017 }
1018 
1020  if (jacg_sp_.size1()>0 && jacg_sp_.nnz()==0) {
1021  casadi_error("Empty sparsity pattern not supported in IPOPT C interface");
1022  }
1023  g << "d->nlp = &d_nlp;\n";
1024  g << "d->prob = &p;\n";
1025  g << "p.nlp = &p_nlp;\n";
1026  g << "p.sp_a = " << g.sparsity(jacg_sp_) << ";\n";
1027  if (exact_hessian_) {
1028  g << "p.sp_h = " << g.sparsity(hesslag_sp_) << ";\n";
1029  } else {
1030  g << "p.sp_h = 0;\n";
1031  }
1032  g << "casadi_ipopt_setup(&p);\n";
1033 
1034  std::string nlp_f = g.shorthand(g.wrapper(get_function("nlp_f"), "nlp_f"));
1035  g << "p.eval_f = " << nlp_f << ";\n";
1036  std::string nlp_g = g.shorthand(g.wrapper(get_function("nlp_g"), "nlp_g"));
1037  g << "p.eval_g = " << nlp_g << ";\n";
1038  std::string nlp_grad_f = g.shorthand(g.wrapper(get_function("nlp_grad_f"), "nlp_grad_f"));
1039  g << "p.eval_grad_f = " << nlp_grad_f << ";\n";
1040  std::string nlp_jac_g = g.shorthand(g.wrapper(get_function("nlp_jac_g"), "nlp_jac_g"));
1041  g << "p.eval_jac_g = " << nlp_jac_g << ";\n";
1042  if (exact_hessian_) {
1043  std::string nlp_hess_l = g.shorthand(g.wrapper(get_function("nlp_hess_l"), "nlp_hess_l"));
1044  g << "p.eval_h = " << nlp_hess_l << ";\n";
1045  } else {
1046  g << "p.eval_h = casadi_ipopt_hess_l_empty;\n";
1047  }
1048 }
1049 
1050 } // namespace casadi
const char * what() const override
Display error.
Definition: exception.hpp:90
Helper class for C code generation.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string wrapper(const Function &base, const std::string &name)
void scope_enter()
Enter a local scope.
void flush(std::ostream &s)
Flush the buffer to a stream of choice.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void scope_exit()
Exit a local scope.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
std::string shorthand(const std::string &name) const
Get a shorthand.
std::stringstream body
std::string sparsity(const Sparsity &sp, bool canonical=true)
std::stringstream auxiliaries
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
static void serialize(SerializingStream &s, const std::string &prefix, const ConvexifyData &d)
Definition: convexify.cpp:111
static Sparsity setup(ConvexifyData &d, const Sparsity &H, const Dict &opts=Dict(), bool inplace=true)
Definition: convexify.cpp:166
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: convexify.hpp:104
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
std::string codegen_mem(CodeGenerator &g, const std::string &index="mem") const
Get thread-local memory object.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
Function object.
Definition: function.hpp:60
std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order=1, bool tr=false) const
Which variables enter with some order.
Definition: function.cpp:1834
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:823
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:819
bool is_null() const
Is a null pointer?
void get_nlp_info(IpoptMemory *m, int &nx, int &ng, int &nnz_jac_g, int &nnz_h_lag) const
void finalize_solution(IpoptMemory *m, const double *x, const double *z_L, const double *z_U, const double *g, const double *lambda, double obj_value, int iter_count) const
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
static const std::string meta_doc
A documentation string.
bool get_bounds_info(IpoptMemory *m, double *x_l, double *x_u, double *g_l, double *g_u) const
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
void codegen_init_mem(CodeGenerator &g) const override
Codegen alloc_mem.
void codegen_free_mem(CodeGenerator &g) const override
Codegen free_mem.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
bool exact_hessian_
Exact Hessian?
ConvexifyData convexify_data_
Data for convexification.
int get_number_of_nonlinear_variables() const
bool get_var_con_metadata(std::map< std::string, std::vector< std::string > > &var_string_md, std::map< std::string, std::vector< int > > &var_integer_md, std::map< std::string, std::vector< double > > &var_numeric_md, std::map< std::string, std::vector< std::string > > &con_string_md, std::map< std::string, std::vector< int > > &con_integer_md, std::map< std::string, std::vector< double > > &con_numeric_md) const
std::string inactive_lam_strategy_
Dict get_stats(void *mem) const override
Get all statistics.
void set_ipopt_prob(CodeGenerator &g) const
static const Options options_
Options.
Dict opts_
All IPOPT options.
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
int init_mem(void *mem) const override
Initalize memory block.
int solve(void *mem) const override
void init(const Dict &opts) override
Initialize.
bool intermediate_callback(IpoptMemory *m, const double *x, const double *z_L, const double *z_U, const double *g, const double *lambda, double obj_value, int iter, double inf_pr, double inf_du, double mu, double d_norm, double regularization_size, double alpha_du, double alpha_pr, int ls_trials, bool full_callback) const
bool get_list_of_nonlinear_variables(int num_nonlin_vars, int *pos_nonlin_vars) const
std::vector< bool > nl_ex_
IpoptInterface(const std::string &name, const Function &nlp)
bool get_starting_point(IpoptMemory *m, bool init_x, double *x, bool init_z, double *z_L, double *z_U, bool init_lambda, double *lambda) const
NLP solver storage class.
Definition: nlpsol_impl.hpp:59
bool iteration_callback_ignore_errors_
Options.
Definition: nlpsol_impl.hpp:95
void codegen_body_exit(CodeGenerator &g) const override
Generate code for the function body.
Definition: nlpsol.cpp:1346
Dict get_stats(void *mem) const override
Get all statistics.
Definition: nlpsol.cpp:1239
static const Options options_
Options.
void codegen_body_enter(CodeGenerator &g) const override
Generate code for the function body.
Definition: nlpsol.cpp:1256
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
Definition: nlpsol.cpp:1327
void init(const Dict &opts) override
Initialize.
Definition: nlpsol.cpp:497
casadi_int ng_
Number of constraints.
Definition: nlpsol_impl.hpp:69
int init_mem(void *mem) const override
Initalize memory block.
Definition: nlpsol.cpp:680
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: nlpsol.cpp:1383
casadi_int nx_
Number of variables.
Definition: nlpsol_impl.hpp:66
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Definition: nlpsol.cpp:872
Function fcallback_
callback function, executed at each iteration
Definition: nlpsol_impl.hpp:75
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
Function oracle_
Oracle: Used to generate other functions.
Function create_function(const Function &oracle, const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux=Function::AuxOut(), const Dict &opts=Dict())
std::vector< std::string > get_function() const override
Get list of dependency functions.
bool has_function(const std::string &fname) const override
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
bool error_on_fail_
Throw an exception on failure?
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
bool is_triu(bool strictly=false) const
Is upper triangular?
Definition: sparsity.cpp:325
The casadi namespace.
Definition: archiver.cpp:28
@ NLPSOL_G
Constraints function at the optimal solution (ng x 1)
Definition: nlpsol.hpp:221
@ NLPSOL_X
Decision variables at the optimal solution (nx x 1)
Definition: nlpsol.hpp:217
@ NLPSOL_LAM_P
Lagrange multipliers for bounds on P at the solution (np x 1)
Definition: nlpsol.hpp:227
@ NLPSOL_F
Cost function value at the optimal solution (1 x 1)
Definition: nlpsol.hpp:219
@ NLPSOL_LAM_G
Lagrange multipliers for bounds on G at the solution (ng x 1)
Definition: nlpsol.hpp:225
@ NLPSOL_LAM_X
Lagrange multipliers for bounds on X at the solution (nx x 1)
Definition: nlpsol.hpp:223
std::ostream & uerr()
int CASADI_NLPSOL_IPOPT_EXPORT casadi_register_nlpsol_ipopt(Nlpsol::Plugin *plugin)
bool startswith(const std::string &s, const std::string &p)
Checks if s starts with p.
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
void CASADI_NLPSOL_IPOPT_EXPORT casadi_load_nlpsol_ipopt()
const char * return_status_string(Bonmin::TMINLP::SolverReturn status)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
std::ostream & uout()
@ SOLVER_RET_LIMITED
casadi_int sz_iw
Definition: mx.hpp:62
casadi_int sz_w
Definition: mx.hpp:63
IpoptMemory()
Constructor.
std::vector< double > regularization_size
std::vector< double > alpha_pr
const char * return_status
std::vector< double > obj
std::vector< double > inf_du
std::vector< double > d_norm
std::vector< double > inf_pr
std::vector< double > alpha_du
std::vector< int > ls_trials
std::vector< double > mu
casadi_nlpsol_data< double > d_nlp
Definition: nlpsol_impl.hpp:42
Options metadata for a class.
Definition: options.hpp:40
static Dict sanitize(const Dict &opts, bool top_level=true)
Sanitize a options dictionary.
Definition: options.cpp:173
std::map< std::string, FStats > fstats