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 
220  convexify_ = false;
221 
222  // Allocate temporary work vectors
223  if (exact_hessian_) {
224  if (!has_function("nlp_hess_l")) {
225  create_function("nlp_hess_l", {"x", "p", "lam:f", "lam:g"},
226  {"triu:hess:gamma:x:x"}, {{"gamma", {"f", "g"}}});
227  }
228  hesslag_sp_ = get_function("nlp_hess_l").sparsity_out(0);
229  casadi_assert(hesslag_sp_.is_triu(), "Hessian must be upper triangular");
230  if (convexify_strategy!="none") {
231  convexify_ = true;
232  Dict opts;
233  opts["strategy"] = convexify_strategy;
234  opts["margin"] = convexify_margin;
235  opts["max_iter_eig"] = max_iter_eig;
236  opts["verbose"] = verbose_;
238  }
239  } else if (pass_nonlinear_variables_) {
240  nl_ex_ = oracle_.which_depends("x", {"f", "g"}, 2, false);
241  }
242 
243  // Allocate work vectors
244  alloc_w(ng_, true); // gk_
245  alloc_w(nx_, true); // grad_fk_
246  alloc_w(jacg_sp_.nnz(), true); // jac_gk_
247  if (exact_hessian_) {
248  alloc_w(hesslag_sp_.nnz(), true); // hess_lk_
249  }
250  if (convexify_) {
253  }
254  }
255 
256  int IpoptInterface::init_mem(void* mem) const {
257  if (Nlpsol::init_mem(mem)) return 1;
258  auto m = static_cast<IpoptMemory*>(mem);
259 
260  // Start an IPOPT application
261  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app = new Ipopt::SmartPtr<Ipopt::IpoptApplication>();
262  m->app = static_cast<void*>(app);
263  *app = new Ipopt::IpoptApplication(false);
264 
265  // Direct output through casadi::uout()
266  StreamJournal* jrnl_raw = new StreamJournal("console", J_ITERSUMMARY);
267  jrnl_raw->SetOutputStream(&casadi::uout());
268  jrnl_raw->SetPrintLevel(J_DBG, J_NONE);
269  SmartPtr<Journal> jrnl = jrnl_raw;
270  (*app)->Jnlst()->AddJournal(jrnl);
271 
272  // Create an Ipopt user class -- need to use Ipopts spart pointer class
273  Ipopt::SmartPtr<Ipopt::TNLP> *userclass = new Ipopt::SmartPtr<Ipopt::TNLP>();
274  m->userclass = static_cast<void*>(userclass);
275  *userclass = new IpoptUserClass(*this, m);
276 
277  if (verbose_) {
278  uout() << "There are " << nx_ << " variables and " << ng_ << " constraints." << std::endl;
279  if (exact_hessian_) uout() << "Using exact Hessian" << std::endl;
280  else uout() << "Using limited memory Hessian approximation" << std::endl;
281  }
282 
283  // Get all options available in (s)IPOPT
284  auto regops = (*app)->RegOptions()->RegisteredOptionsList();
285 
286  Dict options = Options::sanitize(opts_);
287  // Replace resto group with prefixes
288  auto it = options.find("resto");
289  if (it!=options.end()) {
290  Dict resto_options = it->second;
291  options.erase(it);
292  for (auto&& op : resto_options) {
293  options["resto." + op.first] = op.second;
294  }
295  }
296 
297  // Pass all the options to ipopt
298  for (auto&& op : options) {
299 
300  // There might be options with a resto prefix.
301  std::string option_name = op.first;
302  if (startswith(option_name, "resto.")) {
303  option_name = option_name.substr(6);
304  }
305 
306  // Find the option
307  auto regops_it = regops.find(option_name);
308  if (regops_it==regops.end()) {
309  casadi_error("No such IPOPT option: " + op.first);
310  }
311 
312  // Get the type
313  Ipopt::RegisteredOptionType ipopt_type = regops_it->second->Type();
314 
315  // Pass to IPOPT
316  bool ret;
317  switch (ipopt_type) {
318  case Ipopt::OT_Number:
319  ret = (*app)->Options()->SetNumericValue(op.first, op.second.to_double(), false);
320  break;
321  case Ipopt::OT_Integer:
322  ret = (*app)->Options()->SetIntegerValue(op.first, op.second.to_int(), false);
323  break;
324  case Ipopt::OT_String:
325  ret = (*app)->Options()->SetStringValue(op.first, op.second.to_string(), false);
326  break;
327  case Ipopt::OT_Unknown:
328  default:
329  casadi_warning("Cannot handle option \"" + op.first + "\", ignored");
330  continue;
331  }
332  if (!ret) casadi_error("Invalid options were detected by Ipopt.");
333  }
334 
335  // Override IPOPT's default linear solver
336  if (opts_.find("linear_solver") == opts_.end()) {
337  char * default_solver = getenv("IPOPT_DEFAULT_LINEAR_SOLVER");
338  if (default_solver) {
339  bool ret = (*app)->Options()->SetStringValue("linear_solver", default_solver, false);
340  casadi_assert(ret, "Corrupted IPOPT_DEFAULT_LINEAR_SOLVER environmental variable");
341  } else {
342  // Fall back to MUMPS (avoid user issues after SPRAL was added to binaries and
343  // chosen default by Ipopt)
344  bool ret = (*app)->Options()->SetStringValue("linear_solver", "mumps", false);
345  casadi_assert_dev(ret);
346  }
347 
348  }
349 
350  // Intialize the IpoptApplication and process the options
351  Ipopt::ApplicationReturnStatus status = (*app)->Initialize();
352  casadi_assert(status == Solve_Succeeded, "Error during IPOPT initialization");
353 
354  if (convexify_) m->add_stat("convexify");
355  return 0;
356  }
357 
358  void IpoptInterface::set_work(void* mem, const double**& arg, double**& res,
359  casadi_int*& iw, double*& w) const {
360  auto m = static_cast<IpoptMemory*>(mem);
361 
362  // Set work in base classes
363  Nlpsol::set_work(mem, arg, res, iw, w);
364 
365  // Work vectors
366  m->gk = w; w += ng_;
367  m->grad_fk = w; w += nx_;
368  m->jac_gk = w; w += jacg_sp_.nnz();
369  if (exact_hessian_) {
370  m->hess_lk = w; w += hesslag_sp_.nnz();
371  }
372  }
373 
374  inline const char* return_status_string(Ipopt::ApplicationReturnStatus status) {
375  switch (status) {
376  case Solve_Succeeded:
377  return "Solve_Succeeded";
378  case Solved_To_Acceptable_Level:
379  return "Solved_To_Acceptable_Level";
380  case Infeasible_Problem_Detected:
381  return "Infeasible_Problem_Detected";
382  case Search_Direction_Becomes_Too_Small:
383  return "Search_Direction_Becomes_Too_Small";
384  case Diverging_Iterates:
385  return "Diverging_Iterates";
386  case User_Requested_Stop:
387  return "User_Requested_Stop";
388  case Maximum_Iterations_Exceeded:
389  return "Maximum_Iterations_Exceeded";
390  case Restoration_Failed:
391  return "Restoration_Failed";
392  case Error_In_Step_Computation:
393  return "Error_In_Step_Computation";
394  case Not_Enough_Degrees_Of_Freedom:
395  return "Not_Enough_Degrees_Of_Freedom";
396  case Invalid_Problem_Definition:
397  return "Invalid_Problem_Definition";
398  case Invalid_Option:
399  return "Invalid_Option";
400  case Invalid_Number_Detected:
401  return "Invalid_Number_Detected";
402  case Unrecoverable_Exception:
403  return "Unrecoverable_Exception";
404  case NonIpopt_Exception_Thrown:
405  return "NonIpopt_Exception_Thrown";
406  case Insufficient_Memory:
407  return "Insufficient_Memory";
408  case Internal_Error:
409  return "Internal_Error";
410  case Maximum_CpuTime_Exceeded:
411  return "Maximum_CpuTime_Exceeded";
412  case Feasible_Point_Found:
413  return "Feasible_Point_Found";
414 #if (IPOPT_VERSION_MAJOR > 3) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR >= 14)
415  case Maximum_WallTime_Exceeded:
416  return "Maximum_WallTime_Exceeded";
417 #endif
418  }
419  return "Unknown";
420  }
421 
422  int IpoptInterface::solve(void* mem) const {
423  auto m = static_cast<IpoptMemory*>(mem);
424  auto d_nlp = &m->d_nlp;
425 
426  // Reset statistics
427  m->inf_pr.clear();
428  m->inf_du.clear();
429  m->mu.clear();
430  m->d_norm.clear();
431  m->regularization_size.clear();
432  m->alpha_pr.clear();
433  m->alpha_du.clear();
434  m->obj.clear();
435  m->ls_trials.clear();
436 
437  // Reset number of iterations
438  m->n_iter = 0;
439 
440  // Get back the smart pointers
441  Ipopt::SmartPtr<Ipopt::TNLP> *userclass =
442  static_cast<Ipopt::SmartPtr<Ipopt::TNLP>*>(m->userclass);
443  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app =
444  static_cast<Ipopt::SmartPtr<Ipopt::IpoptApplication>*>(m->app);
445 
446  // Ask Ipopt to solve the problem
447  Ipopt::ApplicationReturnStatus status = (*app)->OptimizeTNLP(*userclass);
448  m->return_status = return_status_string(status);
449  m->success = status==Solve_Succeeded || status==Solved_To_Acceptable_Level
450  || status==Feasible_Point_Found;
451  if (status==Maximum_Iterations_Exceeded ||
452  status==Maximum_CpuTime_Exceeded) m->unified_return_status = SOLVER_RET_LIMITED;
453 
454 #if (IPOPT_VERSION_MAJOR > 3) || (IPOPT_VERSION_MAJOR == 3 && IPOPT_VERSION_MINOR >= 14)
455  if (status==Maximum_WallTime_Exceeded) m->unified_return_status = SOLVER_RET_LIMITED;
456 #endif
457 
458  // Save results to outputs
459  casadi_copy(m->gk, ng_, d_nlp->z + nx_);
460 
461  if (clip_inactive_lam_) {
462  // Compute a margin
463  double margin;
464  if (inactive_lam_strategy_=="abstol") {
465  margin = inactive_lam_value_;
466  } else if (inactive_lam_strategy_=="reltol") {
467  double constr_viol_tol;
468  (*app)->Options()->GetNumericValue("constr_viol_tol", constr_viol_tol, "");
469  if (status==Solved_To_Acceptable_Level) {
470  (*app)->Options()->GetNumericValue("acceptable_constr_viol_tol", constr_viol_tol, "");
471  }
472  margin = inactive_lam_value_*constr_viol_tol;
473  } else {
474  casadi_error("inactive_lam_strategy '" + inactive_lam_strategy_ +
475  "' unknown. Use 'abstol' or reltol'.");
476  }
477 
478  for (casadi_int i=0; i<nx_ + ng_; ++i) {
479  // Sufficiently inactive -> make multiplier exactly zero
480  if (d_nlp->lam[i]>0 && d_nlp->ubz[i] - d_nlp->z[i] > margin) d_nlp->lam[i]=0;
481  if (d_nlp->lam[i]<0 && d_nlp->z[i] - d_nlp->lbz[i] > margin) d_nlp->lam[i]=0;
482  }
483  }
484 
485  return 0;
486  }
487 
489  intermediate_callback(IpoptMemory* m, const double* x, const double* z_L, const double* z_U,
490  const double* g, const double* lambda, double obj_value, int iter,
491  double inf_pr, double inf_du, double mu, double d_norm,
492  double regularization_size, double alpha_du, double alpha_pr,
493  int ls_trials, bool full_callback) const {
494  auto d_nlp = &m->d_nlp;
495  m->n_iter += 1;
496  try {
497  m->inf_pr.push_back(inf_pr);
498  m->inf_du.push_back(inf_du);
499  m->mu.push_back(mu);
500  m->d_norm.push_back(d_norm);
501  m->regularization_size.push_back(regularization_size);
502  m->alpha_pr.push_back(alpha_pr);
503  m->alpha_du.push_back(alpha_du);
504  m->ls_trials.push_back(ls_trials);
505  m->obj.push_back(obj_value);
506  if (!fcallback_.is_null()) {
507  ScopedTiming tic(m->fstats.at("callback_fun"));
508  if (full_callback) {
509  casadi_copy(x, nx_, d_nlp->z);
510  for (casadi_int i=0; i<nx_; ++i) {
511  d_nlp->lam[i] = z_U[i]-z_L[i];
512  }
513  casadi_copy(lambda, ng_, d_nlp->lam + nx_);
514  casadi_copy(g, ng_, m->gk);
515  } else {
516  if (iter==0) {
517  uerr()
518  << "Warning: intermediate_callback is disfunctional in your installation. "
519  "You will only be able to use stats(). "
520  "See https://github.com/casadi/casadi/wiki/enableIpoptCallback to enable it."
521  << std::endl;
522  }
523  }
524 
525  // Inputs
526  std::fill_n(m->arg, fcallback_.n_in(), nullptr);
527  if (full_callback) {
528  // The values used below are meaningless
529  // when not doing a full_callback
530  m->arg[NLPSOL_X] = x;
531  m->arg[NLPSOL_F] = &obj_value;
532  m->arg[NLPSOL_G] = g;
533  m->arg[NLPSOL_LAM_P] = nullptr;
534  m->arg[NLPSOL_LAM_X] = d_nlp->lam;
535  m->arg[NLPSOL_LAM_G] = d_nlp->lam + nx_;
536  }
537 
538  // Outputs
539  std::fill_n(m->res, fcallback_.n_out(), nullptr);
540  double ret_double;
541  m->res[0] = &ret_double;
542 
543  fcallback_(m->arg, m->res, m->iw, m->w, 0);
544  casadi_int ret = static_cast<casadi_int>(ret_double);
545 
546  return !ret;
547  } else {
548  return 1;
549  }
550 
551  } catch(KeyboardInterruptException& ex) {
552  return 0;
553  } catch(std::exception& ex) {
554  casadi_warning("intermediate_callback: " + std::string(ex.what()));
555  if (iteration_callback_ignore_errors_) return 1;
556  return 0;
557  }
558  }
559 
561  finalize_solution(IpoptMemory* m, const double* x, const double* z_L, const double* z_U,
562  const double* g, const double* lambda, double obj_value,
563  int iter_count) const {
564  auto d_nlp = &m->d_nlp;
565  try {
566  // Get primal solution
567  casadi_copy(x, nx_, d_nlp->z);
568 
569  // Get optimal cost
570  d_nlp->objective = obj_value;
571 
572  // Get dual solution (simple bounds)
573  for (casadi_int i=0; i<nx_; ++i) {
574  d_nlp->lam[i] = z_U[i]-z_L[i];
575  }
576 
577  // Get dual solution (nonlinear bounds)
578  casadi_copy(lambda, ng_, d_nlp->lam + nx_);
579 
580  // Get the constraints
581  casadi_copy(g, ng_, m->gk);
582 
583  // Get statistics
584  m->iter_count = iter_count;
585 
586  } catch(std::exception& ex) {
587  uerr() << "finalize_solution failed: " << ex.what() << std::endl;
588  }
589  }
590 
592  get_bounds_info(IpoptMemory* m, double* x_l, double* x_u,
593  double* g_l, double* g_u) const {
594  auto d_nlp = &m->d_nlp;
595  try {
596  casadi_copy(d_nlp->lbz, nx_, x_l);
597  casadi_copy(d_nlp->ubz, nx_, x_u);
598  casadi_copy(d_nlp->lbz+nx_, ng_, g_l);
599  casadi_copy(d_nlp->ubz+nx_, ng_, g_u);
600  return true;
601  } catch(std::exception& ex) {
602  uerr() << "get_bounds_info failed: " << ex.what() << std::endl;
603  return false;
604  }
605  }
606 
608  get_starting_point(IpoptMemory* m, bool init_x, double* x,
609  bool init_z, double* z_L, double* z_U,
610  bool init_lambda, double* lambda) const {
611  auto d_nlp = &m->d_nlp;
612  try {
613  // Initialize primal variables
614  if (init_x) {
615  casadi_copy(d_nlp->z, nx_, x);
616  }
617 
618  // Initialize dual variables (simple bounds)
619  if (init_z) {
620  for (casadi_int i=0; i<nx_; ++i) {
621  z_L[i] = std::max(0., -d_nlp->lam[i]);
622  z_U[i] = std::max(0., d_nlp->lam[i]);
623  }
624  }
625 
626  // Initialize dual variables (nonlinear bounds)
627  if (init_lambda) {
628  casadi_copy(d_nlp->lam + nx_, ng_, lambda);
629  }
630 
631  return true;
632  } catch(std::exception& ex) {
633  uerr() << "get_starting_point failed: " << ex.what() << std::endl;
634  return false;
635  }
636  }
637 
638  void IpoptInterface::get_nlp_info(IpoptMemory* m, int& nx, int& ng,
639  int& nnz_jac_g, int& nnz_h_lag) const {
640  try {
641  // Number of variables
642  nx = nx_;
643 
644  // Number of constraints
645  ng = ng_;
646 
647  // Number of Jacobian nonzeros
648  nnz_jac_g = ng_==0 ? 0 : jacg_sp_.nnz();
649 
650  // Number of Hessian nonzeros (only upper triangular half)
651  nnz_h_lag = exact_hessian_ ? hesslag_sp_.nnz() : 0;
652 
653  } catch(std::exception& ex) {
654  uerr() << "get_nlp_info failed: " << ex.what() << std::endl;
655  }
656  }
657 
659  try {
661  // No Hessian has been interfaced
662  return -1;
663  } else {
664  // Number of variables that appear nonlinearily
665  int nv = 0;
666  for (auto&& i : nl_ex_) if (i) nv++;
667  return nv;
668  }
669  } catch(std::exception& ex) {
670  uerr() << "get_number_of_nonlinear_variables failed: " << ex.what() << std::endl;
671  return -1;
672  }
673  }
674 
676  get_list_of_nonlinear_variables(int num_nonlin_vars, int* pos_nonlin_vars) const {
677  try {
678  for (int i=0; i<nl_ex_.size(); ++i) {
679  if (nl_ex_[i]) *pos_nonlin_vars++ = i;
680  }
681  return true;
682  } catch(std::exception& ex) {
683  uerr() << "get_list_of_nonlinear_variables failed: " << ex.what() << std::endl;
684  return false;
685  }
686  }
687 
689  get_var_con_metadata(std::map<std::string, std::vector<std::string> >& var_string_md,
690  std::map<std::string, std::vector<int> >& var_integer_md,
691  std::map<std::string, std::vector<double> >& var_numeric_md,
692  std::map<std::string, std::vector<std::string> >& con_string_md,
693  std::map<std::string, std::vector<int> >& con_integer_md,
694  std::map<std::string, std::vector<double> >& con_numeric_md) const {
695  for (auto&& op : var_string_md_) var_string_md[op.first] = op.second;
696  for (auto&& op : var_integer_md_) var_integer_md[op.first] = op.second;
697  for (auto&& op : var_numeric_md_) var_numeric_md[op.first] = op.second;
698  for (auto&& op : con_string_md_) con_string_md[op.first] = op.second;
699  for (auto&& op : con_integer_md_) con_integer_md[op.first] = op.second;
700  for (auto&& op : con_numeric_md_) con_numeric_md[op.first] = op.second;
701  return true;
702  }
703 
705  this->app = nullptr;
706  this->userclass = nullptr;
707  this->return_status = "Unset";
708  }
709 
711  // Free Ipopt application instance (or rather, the smart pointer holding it)
712  if (this->app != nullptr) {
713  delete static_cast<Ipopt::SmartPtr<Ipopt::IpoptApplication>*>(this->app);
714  }
715 
716  // Free Ipopt user class (or rather, the smart pointer holding it)
717  if (this->userclass != nullptr) {
718  delete static_cast<Ipopt::SmartPtr<Ipopt::TNLP>*>(this->userclass);
719  }
720  }
721 
722  Dict IpoptInterface::get_stats(void* mem) const {
723  Dict stats = Nlpsol::get_stats(mem);
724  auto m = static_cast<IpoptMemory*>(mem);
725  stats["return_status"] = m->return_status;
726  stats["iter_count"] = m->iter_count;
727  if (!m->inf_pr.empty()) {
728  Dict iterations;
729  iterations["inf_pr"] = m->inf_pr;
730  iterations["inf_du"] = m->inf_du;
731  iterations["mu"] = m->mu;
732  iterations["d_norm"] = m->d_norm;
733  iterations["regularization_size"] = m->regularization_size;
734  iterations["obj"] = m->obj;
735  iterations["alpha_pr"] = m->alpha_pr;
736  iterations["alpha_du"] = m->alpha_du;
737  stats["iterations"] = iterations;
738  }
739  return stats;
740  }
741 
743  int version = s.version("IpoptInterface", 1, 3);
744  s.unpack("IpoptInterface::jacg_sp", jacg_sp_);
745  s.unpack("IpoptInterface::hesslag_sp", hesslag_sp_);
746  s.unpack("IpoptInterface::exact_hessian", exact_hessian_);
747  s.unpack("IpoptInterface::opts", opts_);
748  s.unpack("IpoptInterface::pass_nonlinear_variables", pass_nonlinear_variables_);
749  s.unpack("IpoptInterface::nl_ex", nl_ex_);
750  s.unpack("IpoptInterface::var_string_md", var_string_md_);
751  s.unpack("IpoptInterface::var_integer_md", var_integer_md_);
752  s.unpack("IpoptInterface::var_numeric_md", var_numeric_md_);
753  s.unpack("IpoptInterface::con_string_md", con_string_md_);
754  s.unpack("IpoptInterface::con_integer_md", con_integer_md_);
755  s.unpack("IpoptInterface::con_numeric_md", con_numeric_md_);
756  if (version>=2) {
757  s.unpack("IpoptInterface::convexify", convexify_);
758  if (convexify_) Convexify::deserialize(s, "IpoptInterface::", convexify_data_);
759  }
760 
761  if (version>=3) {
762  s.unpack("IpoptInterface::clip_inactive_lam", clip_inactive_lam_);
763  s.unpack("IpoptInterface::inactive_lam_strategy", inactive_lam_strategy_);
764  s.unpack("IpoptInterface::inactive_lam_value", inactive_lam_value_);
765  } else {
766  clip_inactive_lam_ = false;
767  inactive_lam_strategy_ = "reltol";
768  inactive_lam_value_ = 10;
769  }
770  }
771 
774  s.version("IpoptInterface", 3);
775  s.pack("IpoptInterface::jacg_sp", jacg_sp_);
776  s.pack("IpoptInterface::hesslag_sp", hesslag_sp_);
777  s.pack("IpoptInterface::exact_hessian", exact_hessian_);
778  s.pack("IpoptInterface::opts", opts_);
779  s.pack("IpoptInterface::pass_nonlinear_variables", pass_nonlinear_variables_);
780  s.pack("IpoptInterface::nl_ex", nl_ex_);
781  s.pack("IpoptInterface::var_string_md", var_string_md_);
782  s.pack("IpoptInterface::var_integer_md", var_integer_md_);
783  s.pack("IpoptInterface::var_numeric_md", var_numeric_md_);
784  s.pack("IpoptInterface::con_string_md", con_string_md_);
785  s.pack("IpoptInterface::con_integer_md", con_integer_md_);
786  s.pack("IpoptInterface::con_numeric_md", con_numeric_md_);
787  s.pack("IpoptInterface::convexify", convexify_);
788  if (convexify_) Convexify::serialize(s, "IpoptInterface::", convexify_data_);
789 
790  s.pack("IpoptInterface::clip_inactive_lam", clip_inactive_lam_);
791  s.pack("IpoptInterface::inactive_lam_strategy", inactive_lam_strategy_);
792  s.pack("IpoptInterface::inactive_lam_value", inactive_lam_value_);
793 
794  }
795 
797  g << "ipopt_init_mem(&" + codegen_mem(g) + ");\n";
798  g << "return 0;\n";
799  }
800 
802  g << "ipopt_free_mem(&" + codegen_mem(g) + ");\n";
803  }
804 
810  g.add_dependency(get_function("nlp_f"));
811  g.add_dependency(get_function("nlp_grad_f"));
812  g.add_dependency(get_function("nlp_g"));
813  g.add_dependency(get_function("nlp_jac_g"));
814  if (exact_hessian_) {
815  g.add_dependency(get_function("nlp_hess_l"));
816  }
817  g.add_include("coin-or/IpStdCInterface.h");
818 
819  std::string name = "nlp_f";
820  std::string f = g.shorthand(g.wrapper(get_function(name), name));
821 
822  g << "bool " << f
823  << "(ipindex n, ipnumber *x, bool new_x, ipnumber *obj_value, UserDataPtr user_data) {\n";
824  g.flush(g.body);
825  g.scope_enter();
826  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
827  g << "d->arg[0] = x;\n";
828  g << "d->arg[1] = d->nlp->p;\n";
829  g << "d->res[0] = obj_value;\n";
830  std::string flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
831  g << "if (" + flag + ") return false;\n";
832  g << "return true;\n";
833  g.scope_exit();
834  g << "}\n";
835 
836  name = "nlp_g";
837  f = g.shorthand(g.wrapper(get_function(name), name));
838  g << "bool " << f
839  << "(ipindex n, ipnumber *x, bool new_x, ipindex m, ipnumber *g, UserDataPtr user_data) {\n";
840  g.flush(g.body);
841  g.scope_enter();
842  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
843  g << "d->arg[0] = x;\n";
844  g << "d->arg[1] = d->nlp->p;\n";
845  g << "d->res[0] = g;\n";
846  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
847  g << "if (" + flag + ") return false;\n";
848  g << "return true;\n";
849  g.scope_exit();
850  g << "}\n";
851 
852  name = "nlp_grad_f";
853  f = g.shorthand(g.wrapper(get_function(name), name));
854  g << "bool " << f
855  << "(ipindex n, ipnumber *x, bool new_x, ipnumber *grad_f, UserDataPtr user_data) {\n";
856  g.flush(g.body);
857  g.scope_enter();
858  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
859  g << "d->arg[0] = x;\n";
860  g << "d->arg[1] = d->nlp->p;\n";
861  g << "d->res[0] = 0;\n";
862  g << "d->res[1] = grad_f;\n";
863  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
864  g << "if (" + flag + ") return false;\n";
865  g << "return true;\n";
866  g.scope_exit();
867  g << "}\n";
868 
869  name = "nlp_jac_g";
870  f = g.shorthand(g.wrapper(get_function(name), name));
871  g << "bool " << f
872  << "(ipindex n, ipnumber *x, bool new_x, ipindex m,"
873  << " ipindex nele_jac, ipindex *iRow, ipindex *jCol, "
874  << "ipnumber *values, UserDataPtr user_data) {\n";
875  g.flush(g.body);
876  g.scope_enter();
877  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
878  g << "if (values) {\n";
879  g << "d->arg[0] = x;\n";
880  g << "d->arg[1] = d->nlp->p;\n";
881  g << "d->res[0] = 0;\n";
882  g << "d->res[1] = values;\n";
883  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
884  g << "if (" + flag + ") return false;\n";
885  g << "} else {\n";
886  g << "casadi_ipopt_sparsity(d->prob->sp_a, iRow, jCol);\n";
887  g << "}\n";
888  g << "return true;\n";
889  g.scope_exit();
890  g << "}\n";
891 
892  if (exact_hessian_) {
893  name = "nlp_hess_l";
894  f = g.shorthand(g.wrapper(get_function(name), name));
895  g << "bool " << f << "(ipindex n, ipnumber *x, bool new_x, ipnumber obj_factor,"
896  << "ipindex m, ipnumber *lambda, bool new_lambda, ipindex nele_hess, "
897  << "ipindex *iRow, ipindex *jCol, ipnumber *values, UserDataPtr user_data) {\n";
898  g.flush(g.body);
899  g.scope_enter();
900  g << "struct casadi_ipopt_data* d = (struct casadi_ipopt_data*) user_data;\n";
901  g << "if (values) {\n";
902  g << "d->arg[0] = x;\n";
903  g << "d->arg[1] = d->nlp->p;\n";
904  g << "d->arg[2] = &obj_factor;\n";
905  g << "d->arg[3] = lambda;\n";
906  g << "d->res[0] = values;\n";
907  flag = g(get_function(name), "d->arg", "d->res", "d->iw", "d->w", "false");
908  g << "if (" + flag + ") return false;\n";
909  g << "return true;\n";
910  g << "} else {\n";
911  g << "casadi_ipopt_sparsity(d->prob->sp_h, iRow, jCol);\n";
912  g << "}\n";
913  g << "return true;\n";
914  g.scope_exit();
915  g << "}\n";
916  }
917 }
918 
921  g.auxiliaries << g.sanitize_source(ipopt_runtime_str, {"casadi_real"});
922 
923  g.local("d", "struct casadi_ipopt_data*");
924  g.init_local("d", "&" + codegen_mem(g));
925  g.local("p", "struct casadi_ipopt_prob");
926  set_ipopt_prob(g);
927 
928  g << "casadi_ipopt_init(d, &arg, &res, &iw, &w);\n";
929  g << "casadi_ipopt_presolve(d);\n";
930 
931  // Start an IPOPT application
932  Ipopt::SmartPtr<Ipopt::IpoptApplication> *app = new Ipopt::SmartPtr<Ipopt::IpoptApplication>();
933  *app = new Ipopt::IpoptApplication(false);
934 
935  // Get all options available in (s)IPOPT
936  auto regops = (*app)->RegOptions()->RegisteredOptionsList();
937 
938  Dict options = Options::sanitize(opts_);
939  // Replace resto group with prefixes
940  auto it = options.find("resto");
941  if (it!=options.end()) {
942  Dict resto_options = it->second;
943  options.erase(it);
944  for (auto&& op : resto_options) {
945  options["resto." + op.first] = op.second;
946  }
947  }
948 
949  // Pass all the options to ipopt
950  for (auto&& op : options) {
951 
952  // There might be options with a resto prefix.
953  std::string option_name = op.first;
954  if (startswith(option_name, "resto.")) {
955  option_name = option_name.substr(6);
956  }
957 
958  // Find the option
959  auto regops_it = regops.find(option_name);
960  if (regops_it==regops.end()) {
961  casadi_error("No such IPOPT option: " + op.first);
962  }
963 
964  // Get the type
965  Ipopt::RegisteredOptionType ipopt_type = regops_it->second->Type();
966 
967  // Pass to IPOPT
968  switch (ipopt_type) {
969  case Ipopt::OT_Number:
970  g << "AddIpoptNumOption(d->ipopt, \"" << op.first << "\""
971  << "," << op.second.to_double() << ");\n";
972  break;
973  case Ipopt::OT_Integer:
974  g << "AddIpoptIntOption(d->ipopt, \"" << op.first << "\""
975  << "," << op.second.to_int() << ");\n";
976  break;
977  case Ipopt::OT_String:
978  g << "AddIpoptStrOption(d->ipopt, \"" << op.first << "\""
979  << ",\"" << op.second.to_string() << "\");\n";
980  break;
981  case Ipopt::OT_Unknown:
982  default:
983  casadi_warning("Cannot handle option \"" + op.first + "\", ignored");
984  continue;
985  }
986  }
987 
988  // Override IPOPT's default linear solver
989  if (opts_.find("linear_solver") == opts_.end()) {
990  char * default_solver = getenv("IPOPT_DEFAULT_LINEAR_SOLVER");
991  if (default_solver) {
992  g << "AddIpoptStrOption(d->ipopt, \"linear_solver\"" << ",\"" << default_solver << "\");\n";
993  } else {
994  // Fall back to MUMPS (avoid user issues after SPRAL was added to binaries and
995  // chosen default by Ipopt)
996  g << "AddIpoptStrOption(d->ipopt, \"linear_solver\",\"mumps\");\n";
997  }
998 
999  }
1000 
1001  delete app;
1002 
1003  // Options
1004  g << "casadi_ipopt_solve(d);\n";
1005 
1006  codegen_body_exit(g);
1007 
1008  if (error_on_fail_) {
1009  g << "return d->unified_return_status;\n";
1010  } else {
1011  g << "return 0;\n";
1012  }
1013 }
1014 
1016  if (jacg_sp_.size1()>0 && jacg_sp_.nnz()==0) {
1017  casadi_error("Empty sparsity pattern not supported in IPOPT C interface");
1018  }
1019  g << "d->nlp = &d_nlp;\n";
1020  g << "d->prob = &p;\n";
1021  g << "p.nlp = &p_nlp;\n";
1022  g << "p.sp_a = " << g.sparsity(jacg_sp_) << ";\n";
1023  if (exact_hessian_) {
1024  g << "p.sp_h = " << g.sparsity(hesslag_sp_) << ";\n";
1025  } else {
1026  g << "p.sp_h = 0;\n";
1027  }
1028  g << "casadi_ipopt_setup(&p);\n";
1029 
1030  std::string nlp_f = g.shorthand(g.wrapper(get_function("nlp_f"), "nlp_f"));
1031  g << "p.eval_f = " << nlp_f << ";\n";
1032  std::string nlp_g = g.shorthand(g.wrapper(get_function("nlp_g"), "nlp_g"));
1033  g << "p.eval_g = " << nlp_g << ";\n";
1034  std::string nlp_grad_f = g.shorthand(g.wrapper(get_function("nlp_grad_f"), "nlp_grad_f"));
1035  g << "p.eval_grad_f = " << nlp_grad_f << ";\n";
1036  std::string nlp_jac_g = g.shorthand(g.wrapper(get_function("nlp_jac_g"), "nlp_jac_g"));
1037  g << "p.eval_jac_g = " << nlp_jac_g << ";\n";
1038  if (exact_hessian_) {
1039  std::string nlp_hess_l = g.shorthand(g.wrapper(get_function("nlp_hess_l"), "nlp_hess_l"));
1040  g << "p.eval_h = " << nlp_hess_l << ";\n";
1041  } else {
1042  g << "p.eval_h = casadi_ipopt_hess_l_empty;\n";
1043  }
1044 }
1045 
1046 } // 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:1826
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:1269
Dict get_stats(void *mem) const override
Get all statistics.
Definition: nlpsol.cpp:1162
static const Options options_
Options.
void codegen_body_enter(CodeGenerator &g) const override
Generate code for the function body.
Definition: nlpsol.cpp:1179
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
Definition: nlpsol.cpp:1250
void init(const Dict &opts) override
Initialize.
Definition: nlpsol.cpp:420
casadi_int ng_
Number of constraints.
Definition: nlpsol_impl.hpp:69
int init_mem(void *mem) const override
Initalize memory block.
Definition: nlpsol.cpp:603
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: nlpsol.cpp:1306
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:795
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
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)
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