worhp_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 #include "worhp_interface.hpp"
27 
28 #include "casadi/core/casadi_misc.hpp"
29 #include <ctime>
30 #include <cstring>
31 
32 namespace casadi {
33 
34  extern "C"
35  int CASADI_NLPSOL_WORHP_EXPORT
36  casadi_register_nlpsol_worhp(Nlpsol::Plugin* plugin) {
37  plugin->creator = WorhpInterface::creator;
38  plugin->name = "worhp";
39  plugin->doc = WorhpInterface::meta_doc.c_str();
40  plugin->version = CASADI_VERSION;
41  plugin->options = &WorhpInterface::options_;
42  plugin->deserialize = &WorhpInterface::deserialize;
43  return 0;
44  }
45 
46  extern "C"
47  void CASADI_NLPSOL_WORHP_EXPORT casadi_load_nlpsol_worhp() {
49  }
50 
51  WorhpInterface::WorhpInterface(const std::string& name, const Function& nlp)
52  : Nlpsol(name, nlp) {
53  }
54 
56  clear_mem();
57  }
58 
60  = {{&Nlpsol::options_},
61  {{"worhp",
62  {OT_DICT,
63  "Options to be passed to WORHP"}}
64  }
65  };
66 
67  void WorhpInterface::init(const Dict& opts) {
68 
69  // Call the init method of the base class
70  Nlpsol::init(opts);
71 
72  if (CheckWorhpVersion(WORHP_MAJOR, WORHP_MINOR, WORHP_PATCH)) {
73  casadi_warning("Worhp incompatibility. Interface was compiled for Worhp " +
74  str(WORHP_MAJOR) + "." + str(WORHP_MINOR) + "." + std::string(WORHP_PATCH));
75  }
76 
77  // Default options
78  Dict worhp_opts;
79 
80  // Read user options
81  for (auto&& op : opts) {
82  if (op.first=="worhp") {
83  worhp_opts = op.second;
84  }
85  }
86 
87  // Sort Worhp options
88  casadi_int nopts = WorhpGetParamCount();
89  for (auto&& op : worhp_opts) {
90  if (op.first=="qp") {
91  qp_opts_ = op.second;
92  continue;
93  }
94 
95  // Get corresponding index using a linear search
96  casadi_int ind;
97  for (ind=1; ind<=nopts; ++ind) {
98  // Get name in WORHP
99  const char* name = WorhpGetParamName(ind);
100  // Break if matching name
101  if (op.first==name) break;
102  }
103  if (ind>nopts) casadi_error("No such Worhp option: " + op.first);
104 
105  // Add to the corresponding list
106  switch (WorhpGetParamType(ind)) {
107  case WORHP_BOOL_T:
108  bool_opts_[op.first] = op.second;
109  break;
110  case WORHP_DOUBLE_T:
111  double_opts_[op.first] = op.second;
112  break;
113  case WORHP_INT_T:
114  int_opts_[op.first] = op.second;
115  break;
116  default:
117  casadi_error("Cannot handle WORHP option \"" + op.first + "\": Unknown type " +
118  str(WorhpGetParamType(ind)) + ".");
119  break;
120  }
121  }
122 
123  // Setup NLP functions
124  create_function("nlp_f", {"x", "p"}, {"f"});
125  create_function("nlp_g", {"x", "p"}, {"g"});
126  create_function("nlp_grad_f", {"x", "p"}, {"f", "grad:f:x"});
127  Function jac_g_fcn = create_function("nlp_jac_g", {"x", "p"}, {"g", "jac:g:x"});
128  Function hess_l_fcn = create_function("nlp_hess_l", {"x", "p", "lam:f", "lam:g"},
129  {"transpose:triu:hess:gamma:x:x"},
130  {{"gamma", {"f", "g"}}});
131  jacg_sp_ = jac_g_fcn.sparsity_out(1);
132  hesslag_sp_ = hess_l_fcn.sparsity_out(0);
133 
134  // Temporary vectors
135  alloc_w(nx_); // for fetching diagonal entries form Hessian
136  }
137 
138  void worhp_disp(int mode, const char message[]) {
139  if (mode & WORHP_PRINT_MESSAGE) {
140  uout() << message << std::endl;
141  }
142  if (mode & WORHP_PRINT_WARNING) {
143  uerr() << message << std::endl;
144  }
145  if (mode & WORHP_PRINT_ERROR) {
146  uerr() << message << std::endl;
147  }
148  }
149 
150  int WorhpInterface::init_mem(void* mem) const {
151  if (Nlpsol::init_mem(mem)) return 1;
152  auto m = static_cast<WorhpMemory*>(mem);
153 
154  SetWorhpPrint(&worhp_disp);
155 
156  WorhpPreInit(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
157  m->worhp_o.initialised = false;
158  m->worhp_w.initialised = false;
159  m->worhp_p.initialised = false;
160  m->worhp_c.initialised = false;
161 
162  // Initialize parameters to default values
163  int status;
164  InitParams(&status, &m->worhp_p);
165  casadi_assert(status==0, "Problem in Worhp InitParams. Status: " + str(status));
166 
167 
168  // Pass boolean parameters
169  for (auto&& op : bool_opts_) {
170  casadi_assert(
171  WorhpSetBoolParam(&m->worhp_p, op.first.c_str(), op.second),
172  "Problem setting boolean Worhp parameter " + op.first);
173  }
174 
175  // Pass double parameters
176  for (auto&& op : double_opts_) {
177  casadi_assert(
178  WorhpSetDoubleParam(&m->worhp_p, op.first.c_str(), op.second),
179  "Problem setting double Worhp parameter " + op.first);
180  }
181 
182  // Pass integer parameters
183  for (auto&& op : int_opts_) {
184  casadi_assert(
185  WorhpSetIntParam(&m->worhp_p, op.first.c_str(), op.second),
186  "Problem setting integer Worhp parameter " + op.first);
187  }
188 
189  // Pass qp parameters
190  for (auto&& op : qp_opts_) {
191  if (op.first=="ipBarrier") {
192  m->worhp_p.qp.ipBarrier = op.second;
193  } else if (op.first=="ipComTol") {
194  m->worhp_p.qp.ipComTol = op.second;
195  } else if (op.first=="ipFracBound") {
196  m->worhp_p.qp.ipFracBound = op.second;
197  } else if (op.first=="ipMinAlpha") {
198  m->worhp_p.qp.ipMinAlpha = op.second;
199  } else if (op.first=="ipRelaxDiv") {
200  m->worhp_p.qp.ipRelaxDiv = op.second;
201  } else if (op.first=="ipRelaxMax") {
202  m->worhp_p.qp.ipRelaxMax = op.second;
203  } else if (op.first=="ipRelaxMin") {
204  m->worhp_p.qp.ipRelaxMin = op.second;
205  } else if (op.first=="ipRelaxMult") {
206  m->worhp_p.qp.ipRelaxMult = op.second;
207  } else if (op.first=="ipResTol") {
208  m->worhp_p.qp.ipResTol = op.second;
209  } else if (op.first=="lsTol") {
210  m->worhp_p.qp.lsTol = op.second;
211  } else if (op.first=="nsnBeta") {
212  m->worhp_p.qp.nsnBeta = op.second;
213  } else if (op.first=="nsnKKT") {
214  m->worhp_p.qp.nsnKKT = op.second;
215  } else if (op.first=="nsnMinAlpha") {
216  m->worhp_p.qp.nsnMinAlpha = op.second;
217  } else if (op.first=="nsnSigma") {
218  m->worhp_p.qp.nsnSigma = op.second;
219  } else if (op.first=="ipLsMethod") {
220  m->worhp_p.qp.ipLsMethod = op.second;
221  } else if (op.first=="lsItMaxIter") {
222  m->worhp_p.qp.lsItMaxIter = op.second;
223  } else if (op.first=="lsItMethod") {
224  m->worhp_p.qp.lsItMethod = op.second;
225  } else if (op.first=="lsItPrecondMethod") {
226  m->worhp_p.qp.lsItPrecondMethod = op.second;
227  } else if (op.first=="lsRefineMaxIter") {
228  m->worhp_p.qp.lsRefineMaxIter = op.second;
229  } else if (op.first=="maxIter") {
230  m->worhp_p.qp.maxIter = op.second;
231  } else if (op.first=="method") {
232  m->worhp_p.qp.method = op.second;
233  } else if (op.first=="nsnLsMethod") {
234  m->worhp_p.qp.nsnLsMethod = op.second;
235  } else if (op.first=="printLevel") {
236  m->worhp_p.qp.printLevel = op.second;
237  } else if (op.first=="ipTryRelax") {
238  m->worhp_p.qp.ipTryRelax = op.second;
239  } else if (op.first=="lsScale") {
240  m->worhp_p.qp.lsScale = op.second;
241  } else if (op.first=="lsTrySimple") {
242  m->worhp_p.qp.lsTrySimple = op.second;
243  } else if (op.first=="nsnGradStep") {
244  m->worhp_p.qp.nsnGradStep = op.second;
245  } else if (op.first=="scaleIntern") {
246  m->worhp_p.qp.scaleIntern = op.second;
247  } else if (op.first=="strict") {
248  m->worhp_p.qp.strict = op.second;
249  } else {
250  casadi_error("No such Worhp option: qp." + op.first);
251  }
252  }
253 
254  // Mark the parameters as set
255  m->worhp_p.initialised = true;
256  m->init_ = false;
257 
258  return 0;
259  }
260 
261  void WorhpInterface::set_work(void* mem, const double**& arg, double**& res,
262  casadi_int*& iw, double*& w) const {
263  auto m = static_cast<WorhpMemory*>(mem);
264 
265  // Set work in base classes
266  Nlpsol::set_work(mem, arg, res, iw, w);
267 
268  // Free existing Worhp memory (except parameters)
269  m->worhp_p.initialised = false; // Avoid freeing the memory for parameters
270  if (m->worhp_o.initialised || m->worhp_w.initialised || m->worhp_c.initialised) {
271  WorhpFree(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
272  }
273  m->worhp_p.initialised = true;
274 
275  // Number of (free) variables
276  m->worhp_o.n = nx_;
277 
278  // Number of constraints
279  m->worhp_o.m = ng_;
280 
282  m->worhp_c.initialised = false;
283  m->worhp_w.initialised = false;
284  m->worhp_o.initialised = false;
285 
286  // Worhp uses the CS format internally, hence it is the preferred sparse matrix format.
287  m->worhp_w.DF.nnz = nx_;
288  if (m->worhp_o.m>0) {
289  m->worhp_w.DG.nnz = jacg_sp_.nnz(); // Jacobian of G
290  } else {
291  m->worhp_w.DG.nnz = 0;
292  }
293 
294  if (true /*m->worhp_w.HM.NeedStructure*/) { // not initialized // NOLINT
295  m->worhp_w.HM.nnz = nx_ + hesslag_sp_.nnz_lower(true);
296  } else {
297  m->worhp_w.HM.nnz = 0;
298  }
299 
300  /* Data structure initialisation. */
301  WorhpInit(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
302  m->init_ = true;
303  if (m->worhp_c.status != FirstCall) {
304  std::string msg = return_codes(m->worhp_c.status);
305  casadi_error("Main: Initialisation failed. Status: " + msg);
306  }
307 
308  if (m->worhp_w.DF.NeedStructure) {
309  for (casadi_int i=0; i<nx_; ++i) {
310  m->worhp_w.DF.row[i] = i + 1; // Index-1 based
311  }
312  }
313 
314  if (m->worhp_o.m>0 && m->worhp_w.DG.NeedStructure) {
315  casadi_int nz=0;
316  const casadi_int* colind = jacg_sp_.colind();
317  const casadi_int* row = jacg_sp_.row();
318  for (casadi_int c=0; c<nx_; ++c) {
319  for (casadi_int el=colind[c]; el<colind[c+1]; ++el) {
320  casadi_int r = row[el];
321  m->worhp_w.DG.col[nz] = c + 1; // Index-1 based
322  m->worhp_w.DG.row[nz] = r + 1;
323  nz++;
324  }
325  }
326  }
327 
328  if (m->worhp_w.HM.NeedStructure) {
329  // Get the sparsity pattern of the Hessian
330  const casadi_int* colind = hesslag_sp_.colind();
331  const casadi_int* row = hesslag_sp_.row();
332 
333  casadi_int nz=0;
334 
335  // Strictly lower triangular part of the Hessian (note CCS -> CRS format change)
336  for (casadi_int c=0; c<nx_; ++c) {
337  for (casadi_int el=colind[c]; el<colind[c+1]; ++el) {
338  if (row[el]>c) {
339  m->worhp_w.HM.row[nz] = row[el] + 1;
340  m->worhp_w.HM.col[nz] = c + 1;
341  nz++;
342  }
343  }
344  }
345 
346  // Diagonal always included
347  for (casadi_int r=0; r<nx_; ++r) {
348  m->worhp_w.HM.row[nz] = r + 1;
349  m->worhp_w.HM.col[nz] = r + 1;
350  nz++;
351  }
352  }
353  }
354 
355  int WorhpInterface::solve(void* mem) const {
356  auto m = static_cast<WorhpMemory*>(mem);
357  auto d_nlp = &m->d_nlp;
358 
359  for (casadi_int i=0; i<ng_; ++i) {
360  casadi_assert(!(d_nlp->lbz[nx_+i]==-inf && d_nlp->ubz[nx_+i] == inf),
361  "WorhpInterface::evaluate: Worhp cannot handle the case when both "
362  "LBG and UBG are infinite."
363  "You have that case at non-zero " + str(i)+ "."
364  "Reformulate your problem eliminating the corresponding constraint.");
365  }
366 
367  // Pass inputs to WORHP data structures
368  casadi_copy(d_nlp->z, nx_, m->worhp_o.X);
369  casadi_copy(d_nlp->lbz, nx_, m->worhp_o.XL);
370  casadi_copy(d_nlp->ubz, nx_, m->worhp_o.XU);
371  casadi_copy(d_nlp->lam, nx_, m->worhp_o.Lambda);
372  if (m->worhp_o.m>0) {
373  casadi_copy(d_nlp->lam+nx_, ng_, m->worhp_o.Mu);
374  casadi_copy(d_nlp->lbz+nx_, ng_, m->worhp_o.GL);
375  casadi_copy(d_nlp->ubz+nx_, ng_, m->worhp_o.GU);
376  }
377 
378  // Replace infinite bounds with m->worhp_p.Infty
379  double inf = std::numeric_limits<double>::infinity();
380  for (casadi_int i=0; i<nx_; ++i)
381  if (m->worhp_o.XL[i]==-inf) m->worhp_o.XL[i] = -m->worhp_p.Infty;
382  for (casadi_int i=0; i<nx_; ++i)
383  if (m->worhp_o.XU[i]== inf) m->worhp_o.XU[i] = m->worhp_p.Infty;
384  for (casadi_int i=0; i<ng_; ++i)
385  if (m->worhp_o.GL[i]==-inf) m->worhp_o.GL[i] = -m->worhp_p.Infty;
386  for (casadi_int i=0; i<ng_; ++i)
387  if (m->worhp_o.GU[i]== inf) m->worhp_o.GU[i] = m->worhp_p.Infty;
388 
389  if (verbose_) casadi_message("WorhpInterface::starting iteration");
390 
391  // Reverse Communication loop
392  while (m->worhp_c.status < TerminateSuccess && m->worhp_c.status > TerminateError) {
393  if (GetUserAction(&m->worhp_c, callWorhp)) {
394  Worhp(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
395  }
396 
397 
398  if (GetUserAction(&m->worhp_c, iterOutput)) {
399 
400  if (!fcallback_.is_null()) {
401  m->iter = m->worhp_w.MajorIter;
402  m->iter_sqp = m->worhp_w.MinorIter;
403  m->inf_pr = m->worhp_w.NormMax_CV;
404  m->inf_du = m->worhp_w.OptiMax;
405  m->alpha_pr = m->worhp_w.ArmijoAlpha;
406 
407  // Inputs
408  std::fill_n(m->arg, fcallback_.n_in(), nullptr);
409  m->arg[NLPSOL_X] = m->worhp_o.X;
410  m->arg[NLPSOL_F] = &m->worhp_o.F;
411  m->arg[NLPSOL_G] = m->worhp_o.G;
412  m->arg[NLPSOL_LAM_P] = nullptr;
413  m->arg[NLPSOL_LAM_X] = m->worhp_o.Lambda;
414  m->arg[NLPSOL_LAM_G] = m->worhp_o.Mu;
415 
416  // Outputs
417  std::fill_n(m->res, fcallback_.n_out(), nullptr);
418  double ret_double = 0;
419  m->res[0] = &ret_double;
420 
421  try {
422  ScopedTiming tic(m->fstats.at("callback_fun"));
423  // Evaluate the callback function
424  fcallback_(m->arg, m->res, m->iw, m->w, 0);
425  casadi_int ret = static_cast<casadi_int>(ret_double);
426  if (ret) m->worhp_c.status = TerminateError;
427  } catch(KeyboardInterruptException& ex) {
428  m->worhp_c.status = TerminateError;
429  } catch(std::exception& ex) {
430  casadi_warning("iteration_callback: " + std::string(ex.what()));
431  if (!iteration_callback_ignore_errors_) m->worhp_c.status = TerminateError;
432  }
433  }
434 
435 
436  IterationOutput(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
437  DoneUserAction(&m->worhp_c, iterOutput);
438  }
439 
440  if (GetUserAction(&m->worhp_c, evalF)) {
441  m->arg[0] = m->worhp_o.X;
442  m->arg[1] = d_nlp->p;
443  m->res[0] = &m->worhp_o.F;
444  calc_function(m, "nlp_f");
445  d_nlp->objective = m->worhp_o.F; // Store cost, before scaling
446  m->worhp_o.F *= m->worhp_w.ScaleObj;
447  DoneUserAction(&m->worhp_c, evalF);
448  }
449 
450  if (GetUserAction(&m->worhp_c, evalG)) {
451  m->arg[0] = m->worhp_o.X;
452  m->arg[1] = d_nlp->p;
453  m->res[0] = m->worhp_o.G;
454  calc_function(m, "nlp_g");
455  DoneUserAction(&m->worhp_c, evalG);
456  }
457 
458  if (GetUserAction(&m->worhp_c, evalDF)) {
459  m->arg[0] = m->worhp_o.X;
460  m->arg[1] = d_nlp->p;
461  m->res[0] = nullptr;
462  m->res[1] = m->worhp_w.DF.val;
463  calc_function(m, "nlp_grad_f");
464  casadi_scal(nx_, m->worhp_w.ScaleObj, m->worhp_w.DF.val);
465  DoneUserAction(&m->worhp_c, evalDF);
466  }
467 
468  if (GetUserAction(&m->worhp_c, evalDG)) {
469  m->arg[0] = m->worhp_o.X;
470  m->arg[1] = d_nlp->p;
471  m->res[0] = nullptr;
472  m->res[1] = m->worhp_w.DG.val;
473  calc_function(m, "nlp_jac_g");
474  DoneUserAction(&m->worhp_c, evalDG);
475  }
476 
477  if (GetUserAction(&m->worhp_c, evalHM)) {
478  m->arg[0] = m->worhp_o.X;
479  m->arg[1] = d_nlp->p;
480  m->arg[2] = &m->worhp_w.ScaleObj;
481  m->arg[3] = m->worhp_o.Mu;
482  m->res[0] = m->worhp_w.HM.val;
483  calc_function(m, "nlp_hess_l");
484  // Diagonal values
485  double *dval = m->w;
486  casadi_clear(dval, nx_);
487 
488  // Remove diagonal
489  const casadi_int* colind = hesslag_sp_.colind();
490  const casadi_int* row = hesslag_sp_.row();
491  casadi_int ind=0;
492  for (casadi_int c=0; c<nx_; ++c) {
493  for (casadi_int el=colind[c]; el<colind[c+1]; ++el) {
494  if (row[el]==c) {
495  dval[c] = m->worhp_w.HM.val[el];
496  } else {
497  m->worhp_w.HM.val[ind++] = m->worhp_w.HM.val[el];
498  }
499  }
500  }
501 
502  // Add diagonal entries at the end
503  casadi_copy(dval, nx_, m->worhp_w.HM.val+ind);
504  DoneUserAction(&m->worhp_c, evalHM);
505  }
506 
507  if (GetUserAction(&m->worhp_c, fidif)) {
508  WorhpFidif(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
509  }
510  }
511 
512  // Copy outputs
513  casadi_copy(m->worhp_o.X, nx_, d_nlp->z);
514  casadi_copy(m->worhp_o.G, ng_, d_nlp->z+nx_);
515  casadi_copy(m->worhp_o.Lambda, nx_, d_nlp->lam);
516  casadi_copy(m->worhp_o.Mu, ng_, d_nlp->lam+nx_);
517 
518  StatusMsg(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c);
519 
520  m->iter = m->worhp_w.MajorIter;
521  m->iter_sqp = m->worhp_w.MinorIter;
522  m->inf_pr = m->worhp_w.NormMax_CV;
523  m->inf_du = m->worhp_w.OptiMax;
524 
525  m->return_code = m->worhp_c.status;
526  m->return_status = return_codes(m->worhp_c.status);
527  m->success = m->return_code > TerminateSuccess;
528  if (m->return_code==MaxCalls || m->return_code==MaxCalls || m->return_code==Timeout)
529  m->unified_return_status = SOLVER_RET_LIMITED;
530  if (m->return_code==evalsNaN)
531  m->unified_return_status = SOLVER_RET_NAN;
532  return 0;
533  }
534 
535  const char* WorhpInterface::return_codes(casadi_int flag) {
536  switch (flag) {
537  case OptimalSolution: return "OptimalSolution";
538  case OptimalSolutionConstantF: return "OptimalSolutionConstantF";
539  case SearchDirectionZero: return "SearchDirectionZero";
540  case SearchDirectionSmall: return "SearchDirectionSmall";
541  case FritzJohn: return "FritzJohn";
542  case NotDiffable: return "NotDiffable";
543  case Unbounded: return "Unbounded";
544  case FeasibleSolution: return "FeasibleSolution";
545  case LowPassFilterOptimal: return "LowPassFilterOptimal";
546  case LowPassFilterAcceptable: return "LowPassFilterAcceptable";
547  case AcceptableSolution: return "AcceptableSolution";
548  case AcceptablePrevious: return "AcceptablePrevious";
549  case AcceptableSolutionConstantF: return "AcceptableSolutionConstantF";
550  case AcceptablePreviousConstantF: return "AcceptablePreviousConstantF";
551  case AcceptableSolutionSKKT: return "AcceptableSolutionSKKT";
552  case AcceptableSolutionScaled: return "AcceptableSolutionScaled";
553  case AcceptablePreviousScaled: return "AcceptablePreviousScaled";
554  case TerminateError: return "TerminateError";
555  case MaxCalls: return "MaxCalls";
556  case MaxIter: return "MaxIter";
557  case Timeout: return "Timeout";
558  case TooBig: return "TooBig";
559  case evalsNaN: return "evalsNaN";
560  case DivergingPrimal: return "DivergingPrimal";
561  case DivergingDual: return "DivergingDual";
562  case MinimumStepsize: return "MinimumStepsize";
563  case RegularizationFailed: return "RegularizationFailed";
564  case InitError: return "InitError";
565  case DataError: return "DataError";
566  case RestartError: return "RestartError";
567  case QPerror: return "QPerror";
568  case LinearSolverFailed: return "LinearSolverFailed";
569  case TerminatedByCheckFD: return "TerminatedByCheckFD";
570  case LicenseError: return "LicenseError";
571  case Debug: return "Debug";
572  }
573  return "Unknown WORHP return code";
574  }
575 
577  this->worhp_o.initialised = false;
578  this->worhp_w.initialised = false;
579  this->worhp_p.initialised = false;
580  this->worhp_c.initialised = false;
581  }
582 
584  if (this->init_) {
585  if (this->worhp_p.initialised || this->worhp_o.initialised ||
586  this->worhp_w.initialised || this->worhp_c.initialised) {
587  WorhpFree(&this->worhp_o, &this->worhp_w, &this->worhp_p, &this->worhp_c);
588  }
589  }
590  }
591 
592  Dict WorhpInterface::get_stats(void* mem) const {
593  Dict stats = Nlpsol::get_stats(mem);
594  auto m = static_cast<WorhpMemory*>(mem);
595  stats["return_status"] = m->return_status;
596  stats["iter_count"] = m->iter;
597  stats["iter_minor"] = m->iter_sqp;
598  stats["inf_pr"] = m->inf_pr;
599  stats["inf_du"] = m->inf_du;
600  return stats;
601  }
602 
604  s.version("WorhpInterface", 1);
605  s.unpack("WorhpInterface::jacg_sp", jacg_sp_);
606  s.unpack("WorhpInterface::hesslag_sp", hesslag_sp_);
607  s.unpack("WorhpInterface::bool_opts", bool_opts_);
608  s.unpack("WorhpInterface::int_opts", int_opts_);
609  s.unpack("WorhpInterface::double_opts", double_opts_);
610  s.unpack("WorhpInterface::qp_opts", qp_opts_);
611  }
612 
615  s.version("WorhpInterface", 1);
616  s.pack("WorhpInterface::jacg_sp", jacg_sp_);
617  s.pack("WorhpInterface::hesslag_sp", hesslag_sp_);
618  s.pack("WorhpInterface::bool_opts", bool_opts_);
619  s.pack("WorhpInterface::int_opts", int_opts_);
620  s.pack("WorhpInterface::double_opts", double_opts_);
621  s.pack("WorhpInterface::qp_opts", qp_opts_);
622  }
623 
624 } // namespace casadi
const char * what() const override
Display error.
Definition: exception.hpp:90
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_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
Function object.
Definition: function.hpp:126
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:975
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
bool is_null() const
Is a null pointer?
NLP solver storage class.
Definition: nlpsol_impl.hpp:59
bool iteration_callback_ignore_errors_
Options.
Definition: nlpsol_impl.hpp:95
Dict get_stats(void *mem) const override
Get all statistics.
Definition: nlpsol.cpp:1241
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
Definition: nlpsol.cpp:509
casadi_int ng_
Number of constraints.
Definition: nlpsol_impl.hpp:69
int init_mem(void *mem) const override
Initalize memory block.
Definition: nlpsol.cpp:704
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: nlpsol.cpp:1399
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:896
Function fcallback_
callback function, executed at each iteration
Definition: nlpsol_impl.hpp:75
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())
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
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 nnz_lower(bool strictly=false) const
Number of nonzeros in the lower triangular part, i.e. entries (i, j) with i >= j.
Definition: sparsity.cpp:354
casadi_int nnz() const
Number of structural nonzeros.
Definition: sparsity.cpp:150
const casadi_int * row() const
Get a reference to row-vector,.
Definition: sparsity.cpp:166
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Definition: sparsity.cpp:170
std::map< std::string, casadi_int > int_opts_
int init_mem(void *mem) const override
Initalize memory block.
static const std::string meta_doc
A documentation string.
void init(const Dict &opts) override
Initialize.
static const Options options_
Options.
static const char * return_codes(casadi_int flag)
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
std::map< std::string, double > double_opts_
WorhpInterface(const std::string &name, const Function &nlp)
std::map< std::string, bool > bool_opts_
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Dict get_stats(void *mem) const override
Get all statistics.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
int solve(void *mem) const override
The casadi namespace.
Definition: archiver.cpp:28
@ NLPSOL_G
Constraints function at the optimal solution (ng x 1)
Definition: nlpsol.hpp:858
@ NLPSOL_X
Decision variables at the optimal solution (nx x 1)
Definition: nlpsol.hpp:854
@ NLPSOL_LAM_P
Definition: nlpsol.hpp:866
@ NLPSOL_F
Cost function value at the optimal solution (1 x 1)
Definition: nlpsol.hpp:856
@ NLPSOL_LAM_G
Lagrange multipliers for bounds on G at the solution (ng x 1); same sign convention.
Definition: nlpsol.hpp:863
@ NLPSOL_LAM_X
Definition: nlpsol.hpp:861
std::ostream & uerr()
int CASADI_NLPSOL_WORHP_EXPORT casadi_register_nlpsol_worhp(Nlpsol::Plugin *plugin)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void CASADI_NLPSOL_WORHP_EXPORT casadi_load_nlpsol_worhp()
const double inf
infinity
Definition: calculus.hpp:50
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
void worhp_disp(int mode, const char message[])
std::ostream & uout()
@ SOLVER_RET_NAN
@ SOLVER_RET_LIMITED
casadi_nlpsol_data< double > d_nlp
Definition: nlpsol_impl.hpp:42
Options metadata for a class.
Definition: options.hpp:40
const char * return_status
WorhpMemory()
Constructor.