feasiblesqpmethod.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  * Copyright (C) 2022-2023 David Kiessling
9  *
10  * CasADi is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * CasADi is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with CasADi; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 #include "feasiblesqpmethod.hpp"
27 
28 #include "casadi/core/casadi_misc.hpp"
29 #include "casadi/core/calculus.hpp"
30 #include "casadi/core/conic.hpp"
31 #include "casadi/core/conic_impl.hpp"
32 #include "casadi/core/convexify.hpp"
33 
34 #include <ctime>
35 #include <iomanip>
36 #include <fstream>
37 #include <cmath>
38 #include <cfloat>
39 #include <signal.h>
40 
41 namespace casadi {
42 
43 
44  extern "C"
45  int CASADI_NLPSOL_FEASIBLESQPMETHOD_EXPORT
46  casadi_register_nlpsol_feasiblesqpmethod(Nlpsol::Plugin* plugin) {
47  plugin->creator = Feasiblesqpmethod::creator;
48  plugin->name = "feasiblesqpmethod";
49  plugin->doc = Feasiblesqpmethod::meta_doc.c_str();
50  plugin->version = CASADI_VERSION;
51  plugin->options = &Feasiblesqpmethod::options_;
52  plugin->deserialize = &Feasiblesqpmethod::deserialize;
53  return 0;
54  }
55 
56  extern "C"
57  void CASADI_NLPSOL_FEASIBLESQPMETHOD_EXPORT casadi_load_nlpsol_feasiblesqpmethod() {
59  }
60 
61  Feasiblesqpmethod::Feasiblesqpmethod(const std::string& name, const Function& nlp)
62  : Nlpsol(name, nlp) {
63  }
64 
66  clear_mem();
67  }
68 
70  = {{&Nlpsol::options_},
71  {{"solve_type",
72  {OT_STRING,
73  "The solver type: Either SQP or SLP. Defaults to SQP"}},
74  {"qpsol",
75  {OT_STRING,
76  "The QP solver to be used by the SQP method [qpoases]"}},
77  {"qpsol_options",
78  {OT_DICT,
79  "Options to be passed to the QP solver"}},
80  {"hessian_approximation",
81  {OT_STRING,
82  "limited-memory|exact"}},
83  {"max_iter",
84  {OT_INT,
85  "Maximum number of SQP iterations"}},
86  {"min_iter",
87  {OT_INT,
88  "Minimum number of SQP iterations"}},
89  {"tol_pr",
90  {OT_DOUBLE,
91  "Stopping criterion for primal infeasibility"}},
92  {"tol_du",
93  {OT_DOUBLE,
94  "Stopping criterion for dual infeasability"}},
95  {"merit_memory",
96  {OT_INT,
97  "Size of memory to store history of merit function values"}},
98  {"lbfgs_memory",
99  {OT_INT,
100  "Size of L-BFGS memory."}},
101  {"print_header",
102  {OT_BOOL,
103  "Print the header with problem statistics"}},
104  {"print_iteration",
105  {OT_BOOL,
106  "Print the iterations"}},
107  {"print_status",
108  {OT_BOOL,
109  "Print a status message after solving"}},
110  {"f",
111  {OT_FUNCTION,
112  "Function for calculating the objective function (autogenerated by default)"}},
113  {"g",
114  {OT_FUNCTION,
115  "Function for calculating the constraints (autogenerated by default)"}},
116  {"grad_f",
117  {OT_FUNCTION,
118  "Function for calculating the gradient of the objective (autogenerated by default)"}},
119  {"jac_g",
120  {OT_FUNCTION,
121  "Function for calculating the Jacobian of the constraints (autogenerated by default)"}},
122  {"hess_lag",
123  {OT_FUNCTION,
124  "Function for calculating the Hessian of the Lagrangian (autogenerated by default)"}},
125  {"convexify_strategy",
126  {OT_STRING,
127  "NONE|regularize|eigen-reflect|eigen-clip. "
128  "Strategy to convexify the Lagrange Hessian before passing it to the solver."}},
129  {"convexify_margin",
130  {OT_DOUBLE,
131  "When using a convexification strategy, make sure that "
132  "the smallest eigenvalue4 is at least this (default: 1e-7)."}},
133  {"max_iter_eig",
134  {OT_DOUBLE,
135  "Maximum number of iterations to compute an eigenvalue decomposition (default: 50)."}},
136  {"init_feasible",
137  {OT_BOOL,
138  "Initialize the QP subproblems with a feasible initial value (default: false)."}},
139  {"optim_tol",
140  {OT_DOUBLE,
141  "Optimality tolerance. Below this value an iterate is considered to be optimal."}},
142  {"feas_tol",
143  {OT_DOUBLE,
144  "Feasibility tolerance. Below this tolerance an iterate is considered to be feasible."}},
145  {"tr_rad0",
146  {OT_DOUBLE,
147  "Initial trust-region radius."}},
148  {"tr_eta1",
149  {OT_DOUBLE,
150  "Lower eta in trust-region acceptance criterion."}},
151  {"tr_eta2",
152  {OT_DOUBLE,
153  "Upper eta in trust-region acceptance criterion."}},
154  {"tr_alpha1",
155  {OT_DOUBLE,
156  "Lower alpha in trust-region size criterion."}},
157  {"tr_alpha2",
158  {OT_DOUBLE,
159  "Upper alpha in trust-region size criterion."}},
160  {"tr_tol",
161  {OT_DOUBLE,
162  "Trust-region tolerance. "
163  "Below this value another scalar is equal to the trust region radius."}},
164  {"tr_acceptance",
165  {OT_DOUBLE,
166  "Is the trust-region ratio above this value, the step is accepted."}},
167  {"tr_rad_min",
168  {OT_DOUBLE,
169  "Minimum trust-region radius."}},
170  {"tr_rad_max",
171  {OT_DOUBLE,
172  "Maximum trust-region radius."}},
173  {"tr_scale_vector",
175  "Vector that tells where trust-region is applied."}},
176  {"contraction_acceptance_value",
177  {OT_DOUBLE,
178  "If the empirical contraction rate in the feasibility iterations "
179  "is above this value in the heuristics the iterations are aborted."}},
180  {"watchdog",
181  {OT_INT,
182  "Number of watchdog iterations in feasibility iterations. "
183  "After this amount of iterations, it is checked with the contraction acceptance value, "
184  "if iterations are converging."}},
185  {"max_inner_iter",
186  {OT_DOUBLE,
187  "Maximum number of inner iterations."}},
188  {"use_anderson",
189  {OT_BOOL,
190  "Use Anderson Acceleration. (default false)"}},
191  {"anderson_memory",
192  {OT_INT,
193  "Anderson memory. If Anderson is used default is 1, else default is 0."}},
194  }
195  };
196 
197  void Feasiblesqpmethod::init(const Dict& opts) {
198  // Call the init method of the base class
199  Nlpsol::init(opts);
200 
201  // Default options
202  min_iter_ = 0;
203  max_iter_ = 50;
204  lbfgs_memory_ = 10;
205  tol_pr_ = 1e-6;
206  tol_du_ = 1e-6;
207  std::string hessian_approximation = "exact";
208  // min_step_size_ = 1e-10;
209  std::string solve_type = "SQP";
210  std::string qpsol_plugin = "qpoases";
211  Dict qpsol_options;
212  print_header_ = true;
213  print_iteration_ = true;
214  print_status_ = true;
215  // so_corr_ = false;
216  init_feasible_ = false;
217 
218  // parameters and options for FP-SQP solver
219  optim_tol_ = 1e-8;
220  feas_tol_ = 1e-8;
221  tr_eta1_ = 0.25;
222  tr_eta2_ = 0.75;
223  tr_alpha1_ = 0.5;
224  tr_alpha2_ = 2.0;
225  tr_tol_ = 1e-8;
226  tr_acceptance_ = 1e-8;
227  tr_rad_min_ = 1e-10; //is this valid??
228  tr_rad_max_ = 10.0;
229  tr_rad0_ = 1.0;
230  tr_scale_vector_ = std::vector<double>(nx_, 1.0);
232  watchdog_ = 5;
233  max_inner_iter_ = 50;
234  use_anderson_ = false;
236 
237 
238  std::string convexify_strategy = "none";
239  double convexify_margin = 1e-7;
240  casadi_int max_iter_eig = 200;
241 
242  // Read user options
243  for (auto&& op : opts) {
244  if (op.first=="max_iter") {
245  max_iter_ = op.second;
246  } else if (op.first=="min_iter") {
247  min_iter_ = op.second;
248 
249  } else if (op.first=="use_anderson") {
250  use_anderson_ = op.second;
251  } else if (op.first=="anderson_memory") {
252  sz_anderson_memory_ = op.second;
253 
254  } else if (op.first=="lbfgs_memory") {
255  lbfgs_memory_ = op.second;
256  } else if (op.first=="tol_pr") {
257  tol_pr_ = op.second;
258  } else if (op.first=="tol_du") {
259  tol_du_ = op.second;
260  } else if (op.first=="hessian_approximation") {
261  hessian_approximation = op.second.to_string();
262  } else if (op.first=="solve_type") {
263  solve_type = op.second.to_string();
264  } else if (op.first=="qpsol") {
265  qpsol_plugin = op.second.to_string();
266  } else if (op.first=="qpsol_options") {
267  qpsol_options = op.second;
268  } else if (op.first=="print_header") {
269  print_header_ = op.second;
270  } else if (op.first=="print_iteration") {
271  print_iteration_ = op.second;
272  } else if (op.first=="print_status") {
273  print_status_ = op.second;
274  } else if (op.first=="hess_lag") {
275  Function f = op.second;
276  casadi_assert_dev(f.n_in()==4);
277  casadi_assert_dev(f.n_out()==1);
278  set_function(f, "nlp_hess_l");
279  } else if (op.first=="jac_g") {
280  Function f = op.second;
281  casadi_assert_dev(f.n_in()==2);
282  casadi_assert_dev(f.n_out()==1);
283  set_function(f, "nlp_jac_g");
284  } else if (op.first=="grad_f") {
285  Function f = op.second;
286  casadi_assert_dev(f.n_in()==2);
287  casadi_assert_dev(f.n_out()==1);
288  set_function(f, "nlp_grad_f");
289  } else if (op.first=="f") {
290  Function f = op.second;
291  casadi_assert_dev(f.n_in()==2);
292  casadi_assert_dev(f.n_out()==1);
293  set_function(f, "nlp_f");
294  } else if (op.first=="g") {
295  Function f = op.second;
296  casadi_assert_dev(f.n_in()==2);
297  casadi_assert_dev(f.n_out()==1);
298  set_function(f, "nlp_g");
299  /*
300  else if (op.first=="nlp_jac_fg") {
301  Function f = op.second;
302  casadi_assert_dev(f.n_in()==2);
303  casadi_assert_dev(f.n_out()==4);
304  set_function(f, "nlp_jac_fg");
305  }*/
306  } else if (op.first=="convexify_strategy") {
307  convexify_strategy = op.second.to_string();
308  } else if (op.first=="convexify_margin") {
309  convexify_margin = op.second;
310  } else if (op.first=="max_iter_eig") {
311  max_iter_eig = op.second;
312  } else if (op.first=="init_feasible") {
313  init_feasible_ = op.second;
314 
315  // from here FP-SQP
316  } else if (op.first == "optim_tol") {
317  optim_tol_ = op.second;
318  } else if (op.first == "feas_tol") {
319  feas_tol_ = op.second;
320  } else if (op.first == "tr_rad0") {
321  tr_rad0_ = op.second;
322  } else if (op.first == "tr_eta1") {
323  tr_eta1_ = op.second;
324  } else if (op.first == "tr_eta2") {
325  tr_eta2_ = op.second;
326  } else if (op.first == "tr_alpha1") {
327  tr_alpha1_ = op.second;
328  } else if (op.first == "tr_alpha2") {
329  tr_alpha2_ = op.second;
330  } else if (op.first == "tr_tol") {
331  tr_tol_ = op.second;
332  } else if (op.first == "tr_acceptance") {
333  tr_acceptance_ = op.second;
334  } else if (op.first == "tr_rad_min") {
335  tr_rad_min_ = op.second;
336  } else if (op.first == "tr_rad_max") {
337  tr_rad_max_ = op.second;
338  } else if (op.first == "tr_scale_vector") {
339  tr_scale_vector_ = op.second;
340  } else if (op.first == "contraction_acceptance_value") {
341  contraction_acceptance_value_ = op.second;
342  } else if (op.first == "watchdog") {
343  watchdog_ = op.second;
344  } else if (op.first == "max_inner_iter") {
345  max_inner_iter_ = op.second;
346  }
347  }
348 
349  // Use exact Hessian?
350  exact_hessian_ = hessian_approximation =="exact";
351  uout() << "print solve type" << solve_type << std::endl;
352  use_sqp_ = solve_type=="SQP";
353 
354  convexify_ = false;
355 
356  // Get/generate required functions
357  //if (max_iter_ls_ || so_corr_) create_function("nlp_fg", {"x", "p"}, {"f", "g"});
358  // First order derivative information
359 
360  if (!has_function("nlp_f")) {
361  create_function("nlp_f", {"x", "p"},
362  {"f"});
363  }
364  if (!has_function("nlp_g")) {
365  create_function("nlp_g", {"x", "p"},
366  {"g"});
367  }
368  if (!has_function("nlp_jac_g")) {
369  create_function("nlp_jac_g", {"x", "p"},
370  {"jac:g:x"});
371  }
372  if (!has_function("nlp_grad_f")) {
373  create_function("nlp_grad_f", {"x", "p"},
374  {"grad:f:x"});
375  }
376  Asp_ = get_function("nlp_jac_g").sparsity_out(0);
377 
378  /*
379  if (!has_function("nlp_jac_fg")) {
380  create_function("nlp_jac_fg", {"x", "p"},
381  {"f", "grad:f:x", "g", "jac:g:x"});
382  }
383  Asp_ = get_function("nlp_jac_fg").sparsity_out(3);*/
384  if (use_sqp_) {
385  if (exact_hessian_) {
386  if (!has_function("nlp_hess_l")) {
387  create_function("nlp_hess_l", {"x", "p", "lam:f", "lam:g"},
388  {"hess:gamma:x:x"}, {{"gamma", {"f", "g"}}});
389  }
390  Hsp_ = get_function("nlp_hess_l").sparsity_out(0);
391  uout() << "Sparsity pattern: " << Hsp_ << std::endl;
392  casadi_assert(Hsp_.is_symmetric(), "Hessian must be symmetric");
393  if (convexify_strategy!="none") {
394  convexify_ = true;
395  Dict opts;
396  opts["strategy"] = convexify_strategy;
397  opts["margin"] = convexify_margin;
398  opts["max_iter_eig"] = max_iter_eig;
399  opts["verbose"] = verbose_;
401  }
402  } else {
404  }
405  }
406 
407  casadi_assert(!qpsol_plugin.empty(), "'qpsol' option has not been set");
408  // qpsol_options["dump_in"] = true;
409  // qpsol_options["dump_out"] = true;
410  // qpsol_options["dump"] = true;
411  // qpsol_options["print_out"] = true;
412  // qpsol_options["error_on_fail"] = false;
413 
414  // Hsp_.to_file("h.mtx");
415  // Asp_.to_file("a.mtx");
416  // uout() << qpsol_options << std::endl;
417  if (use_sqp_) {
418  qpsol_ = conic("qpsol", qpsol_plugin, {{"h", Hsp_}, {"a", Asp_}},
419  qpsol_options);
420  // cout << qpsol_ <<std::endl;
421  } else {
422  Hsp_ = Sparsity(nx_, nx_);
423  uout() << "Sparsity pattern: " << Hsp_ << std::endl;
424  uout() << "Sparsity pattern: " << Asp_ << std::endl;
425  // uout() << "Nonzeros: " << Hsp_.nnz() << std::endl;
426  // qpsol_ = conic("qpsol", qpsol_plugin, {{"h", Hsp_}, {"a", Asp_}},
427  // qpsol_options);
428  qpsol_ = conic("qpsol", qpsol_plugin, {{"a", Asp_}},
429  qpsol_options);
430  // qpsol_ = Function::load("/home/david/testproblems_feasible_casadi/qpsol.casadi");
431  // cout << qpsol_ <<std::endl;
432  }
433 
434  alloc(qpsol_);
435 
436  // BFGS?
437  if (!exact_hessian_) {
438  alloc_w(2*nx_); // casadi_bfgs
439  }
440 
441  // Header
442  if (print_header_) {
443  print("-------------------------------------------\n");
444  print("This is casadi::Feasiblesqpmethod.\n");
445  if (exact_hessian_) {
446  print("Using exact Hessian\n");
447  } else {
448  print("Using limited memory BFGS Hessian approximation\n");
449  }
450  print("Number of variables: %9d\n", nx_);
451  print("Number of constraints: %9d\n", ng_);
452  print("Number of nonzeros in constraint Jacobian: %9d\n", Asp_.nnz());
453  print("Number of nonzeros in Lagrangian Hessian: %9d\n", Hsp_.nnz());
454  print("\n");
455  }
456 
457 
458  set_feasiblesqpmethod_prob();
459  // Allocate memory
460  casadi_int sz_w, sz_iw;
461  casadi_feasiblesqpmethod_work(&p_, &sz_iw, &sz_w);
462  alloc_iw(sz_iw, true);
463  alloc_w(sz_w, true);
464  if (convexify_) {
467  }
468  }
469 
470  void Feasiblesqpmethod::set_feasiblesqpmethod_prob() {
471 
472  p_.sp_h = Hsp_;
473 
474  p_.sp_a = Asp_;
475  // p_.merit_memsize = merit_memsize_;
476  // p_.max_iter_ls = max_iter_ls_;
477  p_.nlp = &p_nlp_;
479  }
480 
481  void Feasiblesqpmethod::set_work(void* mem, const double**& arg, double**& res,
482  casadi_int*& iw, double*& w) const {
483  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
484 
485  // Set work in base classes
486  Nlpsol::set_work(mem, arg, res, iw, w);
487 
488  m->d.prob = &p_;
489  casadi_feasiblesqpmethod_set_work(&m->d, &arg, &res, &iw, &w);
490 
491  m->iter_count = -1;
492  }
493 
494  int Feasiblesqpmethod::init_mem(void* mem) const {
495  if (Nlpsol::init_mem(mem)) return 1;
496  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
497 
498  if (convexify_) m->add_stat("convexify");
499  m->add_stat("BFGS");
500  m->add_stat("QP");
501  return 0;
502  }
503 
504 double Feasiblesqpmethod::eval_m_k(void* mem) const {
505  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
506  auto d = &m->d;
507  if (use_sqp_) {
508  return 0.5*casadi_bilin(d->Bk, Hsp_, d->dx, d->dx) + casadi_dot(nx_, d->gf, d->dx);
509  } else {
510  return casadi_dot(nx_, d->gf, d->dx);
511  }
512 }
513 
514 double Feasiblesqpmethod::eval_tr_ratio(double val_f, double val_f_corr, double val_m_k) const {
515  return (val_f - val_f_corr) / (-val_m_k);
516 }
517 
518 void Feasiblesqpmethod::tr_update(void* mem, double& tr_rad, double tr_ratio) const {
519  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
520  auto d = &m->d;
521 
522  if (tr_ratio < tr_eta1_) {
523  tr_rad = tr_alpha1_ * casadi_masked_norm_inf(nx_, d->dx, d->tr_mask);
524  } else if (tr_ratio > tr_eta2_ &&
525  abs(casadi_masked_norm_inf(nx_, d->dx, d->tr_mask) - tr_rad) < optim_tol_) {
526  tr_rad = fmin(tr_alpha2_*tr_rad, tr_rad_max_);
527  }
528  // else: keep trust-region as it is....
529 }
530 
531 int Feasiblesqpmethod::step_update(void* mem, double tr_ratio) const {
532  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
533  auto d_nlp = &m->d_nlp;
534  auto d = &m->d;
535 
536  if (tr_ratio > tr_acceptance_) {
537  // This is not properly implemented yet: d_nlp->z_old = d_mlp->z;
538  casadi_copy(d->z_feas, nx_ + ng_, d_nlp->z);
539  d_nlp->objective = d->f_feas;
540  casadi_copy(d->dlam_feas, nx_ + ng_, d_nlp->lam);
541 
542  uout() << "ACCEPTED" << std::endl;
543  return 0;
544  } else {
545  uout() << "REJECTED" << std::endl;
546  return -1;
547  }
548 }
549 
550 
551 /*
552 Do the Anderson step update here and also update the memory here
553 */
554 void Feasiblesqpmethod::anderson_acc_step_update(void* mem, casadi_int iter_index) const {
555  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
556  auto d = &m->d;
557 
558  if (sz_anderson_memory_ == 1) {
559  // Calculte gamma
560  casadi_copy(d->dx_feas, nx_, d->z_tmp);
561  casadi_axpy(nx_, -1.0, d->anderson_memory_step, d->z_tmp);
562  *d->gamma = casadi_dot(nx_, d->dx_feas, d->z_tmp) / casadi_dot(nx_, d->z_tmp, d->z_tmp);
563  // DM(gamma).to_file("gamma.mtx");
564 
565 
566  // Prepare the step update
567  casadi_copy(d->z_feas, nx_, d->z_tmp);
568  casadi_axpy(nx_, -1.0, d->anderson_memory_iterate, d->z_tmp);
569  casadi_axpy(nx_, 1.0, d->dx_feas, d->z_tmp);
570  casadi_axpy(nx_, -1.0, d->anderson_memory_step, d->z_tmp);
571 
572  // Update the Anderson memory
573  anderson_acc_update_memory(mem, d->dx_feas, d->z_feas);
574  // casadi_copy(d->dx_feas, nx_, d->anderson_memory_step);
575  // casadi_copy(d->z_feas, nx_, d->anderson_memory_iterate);
576 
577  // Do the step update
578  double beta = 1.0;
579  casadi_axpy(nx_, beta, d->dx_feas, d->z_feas);
580  casadi_axpy(nx_, -*d->gamma, d->z_tmp, d->z_feas);
581  // DM(std::vector<double>(d->z_feas,d->z_feas+nx_)).to_file("dx_anderson2.mtx");
582 
583  } else {
584  print("This is not implemented yet!!!");
585  casadi_int curr_stage = fmin(iter_index+1, sz_anderson_memory_);
586  // Create matrix F_k
587  casadi_copy(d->dx_feas, nx_, d->z_tmp);
588  casadi_copy(d->anderson_memory_step, (curr_stage-1)*nx_, d->z_tmp+nx_);
589  casadi_axpy(curr_stage*nx_, -1.0, d->anderson_memory_step+nx_, d->z_tmp);
590 
591  // Solve the least-squares problem
592  casadi_dense_lsqr_solve(d->z_tmp, d->dx_feas, 1, 1, curr_stage, nx_, d->gamma);
593 
594  // Update the Anderson memory
595  anderson_acc_update_memory(mem, d->dx_feas, d->z_feas);
596 
598  double beta = 1.0;
599  // Calculate E_k + beta*F_k
600  casadi_axpy(nx_, 1.0, d->z_feas, d->z_tmp);
601  casadi_axpy((curr_stage-1)*nx_, 1.0, d->anderson_memory_iterate, d->z_tmp+nx_);
602  casadi_axpy(curr_stage*nx_, -1.0, d->anderson_memory_iterate, d->z_tmp);
603  // Do the final update
604  casadi_axpy(nx_, beta, d->dx_feas, d->z_feas);
605  casadi_axpy(nx_, -*d->gamma, d->z_tmp, d->z_feas);
606 
607  }
608 }
609 
610 /*
611 Initialize the memory of the Anderson acceleration
612 */
613 void Feasiblesqpmethod::anderson_acc_init_memory(void* mem, double* step, double* iterate) const {
614  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
615  auto d = &m->d;
616 
617  casadi_clear(d->anderson_memory_step, sz_anderson_memory_*nx_);
618  casadi_clear(d->anderson_memory_iterate, sz_anderson_memory_*nx_);
619 
620  // if (sz_anderson_memory_ == 1) {
621  // casadi_copy(step, nx_, d->anderson_memory_step);
622  // casadi_copy(x, nx_, d->anderson_memory_iterate);
623  // } else {
624  // print("This is not implemented yet!!!");
625  // }
626 
627  casadi_copy(step, nx_, d->anderson_memory_step);
628  casadi_copy(iterate, nx_, d->anderson_memory_iterate);
629 
630 }
631 
632 /*
633 Update the memory of the Anderson acceleration
634 */
635 void Feasiblesqpmethod::anderson_acc_update_memory(void* mem, double* step, double* iterate) const {
636  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
637  auto d = &m->d;
638 
639  if (sz_anderson_memory_ == 1) {
640  casadi_copy(step, nx_, d->anderson_memory_step);
641  casadi_copy(iterate, nx_, d->anderson_memory_iterate);
642  } else {
643  // Shift old values further
644  casadi_copy(d->anderson_memory_step,
645  (sz_anderson_memory_-1)*nx_, d->anderson_memory_step + nx_);
646  casadi_copy(d->anderson_memory_iterate,
647  (sz_anderson_memory_-1)*nx_, d->anderson_memory_iterate + nx_);
648  // Insert new values
649  casadi_copy(step, nx_, d->anderson_memory_step);
650  casadi_copy(iterate, nx_, d->anderson_memory_iterate);
651  }
652 }
653 
654 
655 /*
656 Calculates the feasibility_iterations. If iterations are accepted return 0.
657 If iterations are aborted return -1.
658 */
659 
660 int Feasiblesqpmethod::feasibility_iterations(void* mem, double tr_rad) const {
661  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
662  auto d_nlp = &m->d_nlp;
663  auto d = &m->d;
664 
665  // p_tmp = p
666  casadi_copy(d->dx, nx_, d->dx_feas);
667 
668 // lam_p_g_tmp = self.lam_p_g_k
669 // lam_p_x_tmp = self.lam_p_x_k
670  casadi_copy(d->dlam, nx_ + ng_, d->dlam_feas);
671 
672  // Why do we do this at the moment??
673  casadi_copy(d->dlam, nx_+ng_, d->z_tmp);
674  casadi_axpy(nx_+ng_, -1.0, d_nlp->lam, d->z_tmp);
675 
676  // this is in solve in fslp.py
677  double step_inf_norm = casadi_masked_norm_inf(nx_, d->dx, d->tr_mask);
678  double prev_step_inf_norm = step_inf_norm;
679 
680  // bool kappa_acceptance = false;
681 
682  // self.x_tmp = self.x_k + p_tmp
683  casadi_copy(d_nlp->z, nx_+ng_, d->z_feas);
684  casadi_axpy(nx_, 1., d->dx_feas, d->z_feas);
685 
686  if (use_anderson_) {
687  // anderson_acc_init_memory(mem, d->dx_feas, d->z_feas);
688  anderson_acc_init_memory(mem, d->dx_feas, d_nlp->z);
689  }
690 
691  // DM(std::vector<double>(d->z_feas,d->z_feas+nx_)).to_file("dx_anderson1.mtx");
692  // Evaluate g
693  // self.g_tmp = self.__eval_g(self.x_tmp)
694  m->arg[0] = d->z_feas;
695  m->arg[1] = d_nlp->p;
696  m->res[0] = d->z_feas + nx_;
697  if (calc_function(m, "nlp_g")) {
698  uout() << "What does it mean that calc_function fails here??" << std::endl;
699  }
700  int inner_iter = 0;
701 
702 // asymptotic_exactness = []
703  // double asymptotic_exactness = 0.0;
704 // self.prev_infeas = self.feasibility_measure(self.x_tmp, self.g_tmp)
705 // self.curr_infeas = self.feasibility_measure(self.x_tmp, self.g_tmp)
706 
707  double prev_infeas = casadi_max_viol(nx_+ng_, d->z_feas, d_nlp->lbz, d_nlp->ubz);
708  double curr_infeas = prev_infeas;
709 // feasibilities = [self.prev_infeas]
710 // step_norms = []
711 // kappas = []
712 
713 // watchdog_prev_inf_norm = self.prev_step_inf_norm
714 // accumulated_as_ex = 0
715 
716  // Calculate asymptotic exactness of current step
717  casadi_copy(d->dx, nx_, d->z_tmp);
718  casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
719  casadi_axpy(nx_, 1., d_nlp->z, d->z_tmp);
720  double as_exac = casadi_norm_2(nx_, d->z_tmp) / casadi_norm_2(nx_, d->dx);
721 
722  double kappa_watchdog = 0.0;
723  double kappa = 0.0;
724  double acc_as_exac = 0.0;
725 
726 
727  double watchdog_prev_inf_norm = prev_step_inf_norm; // until here everything is correct!
728 
729  for (int j=0; j<max_inner_iter_; ++j) {
730  if (curr_infeas < feas_tol_) {
731  inner_iter = j;
732  // kappa_acceptance = true;
733  if (as_exac < 0.5) {
734  return 0;
735  } else {
736  return -1;
737  }
738  } else if (j>0 && (curr_infeas > 1.0 || as_exac > 1.0)) {
739  // kappa_acceptance = false;
740  return -1;
741  }
742  inner_iter = j+1;
743 
744  // self.lam_tmp_g = self.lam_p_g_k
745  // self.lam_tmp_x = self.lam_p_x_k
746 
747  // create corrected gradient here -----------------------------
748  casadi_copy(d->z_feas, nx_, d->z_tmp);
749  casadi_axpy(nx_, -1., d_nlp->z, d->z_tmp);
750  casadi_copy(d->gf, nx_, d->gf_feas);
751  // In case of SQP we need to multiply with
752  if (use_sqp_) {
753  casadi_mv(d->Bk, Hsp_, d->z_tmp, d->gf_feas, true);
754  }
755 
756  // create bounds of correction QP -----------------------------
757  // upper bounds of constraints
758  casadi_copy(d_nlp->ubz + nx_, ng_, d->ubdz_feas + nx_);
759  casadi_axpy(ng_, -1., d->z_feas + nx_, d->ubdz_feas + nx_);
760 
761  // lower bounds of constraints
762  casadi_copy(d_nlp->lbz + nx_, ng_, d->lbdz_feas + nx_);
763  casadi_axpy(ng_, -1., d->z_feas + nx_, d->lbdz_feas + nx_);
764 
765  // lower bounds of variables
766  // lbp = cs.fmax(-self.tr_rad_k*self.tr_scale_mat_inv_k @
767  // cs.DM.ones(self.nx, 1) - (self.x_tmp-self.x_k),
768  // self.lbx - self.x_tmp)
769 
770  casadi_copy(d_nlp->lbz, nx_, d->lbdz_feas);
771  casadi_clip_min(d->lbdz_feas, nx_, -tr_rad, d->tr_mask);
772  // DM(std::vector<double>(d->lbdz_feas,d->lbdz_feas+nx_)).to_file("lbx_feas_part1_part1.mtx");
773  // casadi_fill(d->lbdz_feas, nx_, -tr_rad);
774  casadi_axpy(nx_, -1., d->z_feas, d->lbdz_feas);
775  casadi_axpy(nx_, 1., d_nlp->z, d->lbdz_feas);
776  // DM(std::vector<double>(d->lbdz_feas,d->lbdz_feas+nx_)).to_file("lbx_feas_part1.mtx");
777 
778 
779  casadi_copy(d_nlp->lbz, nx_, d->z_tmp);
780  casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
781  // DM(std::vector<double>(d->z_tmp,d->z_tmp+nx_)).to_file("lbx_feas_part2.mtx");
782 
783  // comparison of both vectors
784  casadi_vector_fmax(nx_, d->z_tmp, d->lbdz_feas, d->lbdz_feas);
785  // DM(std::vector<double>(d->lbdz_feas,d->lbdz_feas+nx_)).to_file("lbx_feas_end.mtx");
786 
787 
788  // upper bounds of variables
789  // ubp = cs.fmin(self.tr_rad_k*self.tr_scale_mat_inv_k @
790  // cs.DM.ones(self.nx, 1) - (self.x_tmp-self.x_k),
791  // self.ubx - self.x_tmp)
792 
793 
794  casadi_copy(d_nlp->ubz, nx_, d->ubdz_feas);
795  casadi_clip_max(d->ubdz_feas, nx_, tr_rad, d->tr_mask);
796  // DM(std::vector<double>(d->ubdz_feas,d->ubdz_feas+nx_)).to_file("ubx_feas_part1_part1.mtx");
797  // casadi_fill(d->ubdz_feas, nx_, tr_rad);
798  casadi_axpy(nx_, -1., d->z_feas, d->ubdz_feas);
799  // DM(std::vector<double>(d->z_feas,d->z_feas+nx_)).to_file("ubx_feas_part1_zfeas.mtx");
800  casadi_axpy(nx_, 1., d_nlp->z, d->ubdz_feas);
801 
802  // DM(std::vector<double>(d->ubdz_feas,d->ubdz_feas+nx_)).to_file("ubx_feas_part1.mtx");
803 
804  casadi_copy(d_nlp->ubz, nx_, d->z_tmp);
805  casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
806  // DM(std::vector<double>(d->z_tmp,d->z_tmp+nx_)).to_file("ubx_feas_part2.mtx");
807  // comparison of both vectors
808  casadi_vector_fmin(nx_, d->z_tmp, d->ubdz_feas, d->ubdz_feas);
809  // DM(std::vector<double>(d->ubdz_feas,d->ubdz_feas+nx_)).to_file("ubx_feas_end.mtx");
810 
811 
812  // std::string suffix = str(j);
813  // DM(std::vector<double>(d_nlp->lbz,d_nlp->lbz+nx_+ng_)).to_file("nlp_lbz"+suffix+".mtx");
814  // DM(std::vector<double>(d_nlp->ubz,d_nlp->ubz+nx_+ng_)).to_file("nlp_ubz"+suffix+".mtx");
815  // DM(std::vector<double>(d->lbdz_feas,d->lbdz_feas+nx_+ng_)).to_file("lbz"+suffix+".mtx");
816  // DM(std::vector<double>(d->ubdz_feas,d->ubdz_feas+nx_+ng_)).to_file("ubz"+suffix+".mtx");
817  // DM(std::vector<double>(d->z_feas,d->z_feas+nx_+ng_)).to_file("z_feas"+suffix+".mtx");
818  // DM(std::vector<double>(d->dx_feas,d->dx_feas+nx_)).to_file("dx_feas"+suffix+".mtx");
819  // copy back d->dx back to d->dx_feas
820  // casadi_copy(d->dx, nx_, d->x_tmp);
821 
822  //prepare step_inf_norm
823  // DM(std::vector<double>(d->dx_feas,d->dx_feas+nx_)).to_file("dx_input.mtx");
824  // DM(std::vector<double>(d->gf_feas,d->gf_feas+nx_)).to_file("gf_feas.mtx");
825  // DM(std::vector<double>(d->lbdz_feas, d->lbdz_feas+nx_)).to_file("lb_var_correction.mtx");
826  // DM(std::vector<double>(d->ubdz_feas, d->ubdz_feas+nx_)).to_file("ub_var_correction.mtx");
827  // DM(std::vector<double>(d->lbdz_feas+nx_,
828  // d->lbdz_feas+nx_+ng_)).to_file("lba_correction.mtx");
829  // DM(std::vector<double>(d->ubdz_feas+nx_,
830  // d->ubdz_feas+nx_+ng_)).to_file("uba_correction.mtx");
831  // DM(std::vector<double>(d->dlam_feas, d->dlam_feas+nx_)).to_file("lam_x.mtx");
832  // DM(std::vector<double>(d->dlam_feas+nx_, d->dlam_feas+nx_+ng_)).to_file("lam_g.mtx");
833 
834  if (use_sqp_) {
835  solve_QP(m, d->Bk, d->gf_feas, d->lbdz_feas, d->ubdz_feas,
836  d->Jk, d->dx_feas, d->dlam_feas, 0);
837  } else {
838  solve_LP(m, d->gf_feas, d->lbdz_feas, d->ubdz_feas,
839  d->Jk, d->dx_feas, d->dlam_feas, 0);
840  }
841 
842  // put definition of ret out of loop
843 
844  // DM(std::vector<double>(d->dx_feas,d->dx_feas+nx_)).to_file("dx_feas.mtx");
845  // uout() << "Feas QP step: " << std::vector<double>(d->dx_feas, d->dx_feas+nx_) << std::endl;
846  //MISSING: Depending on the result terminate program
847 
848  //MISSING: Calculate the step_inf_norm
849  // self.step_inf_norm = cs.fmax(
850  // cs.norm_inf(self.p_k),
851  // cs.fmax(
852  // cs.norm_inf(self.lam_tmp_g-self.lam_p_g_k),
853  // cs.norm_inf(self.lam_tmp_x-self.lam_p_x_k)
854  // )
855  // )
856 
857  // TODO(david) the python code has a bug and does not consider the step in lambda
858  // here!!
859  // casadi_copy(d->dlam_feas, nx_+ng_, d->z_tmp);
860  // casadi_axpy(nx_+ng_, -1.0, d->dlam, d->z_tmp);
861  step_inf_norm = casadi_masked_norm_inf(nx_, d->dx_feas, d->tr_mask);
862 
863  // self.x_tmp = self.x_tmp + p_tmp
864  // self.g_tmp = self.__eval_g(self.x_tmp) # x_tmp = x_{tmp-1} + p_tmp
865 
866  if (use_anderson_) {
867  anderson_acc_step_update(mem, j);
868  } else {
869  casadi_axpy(nx_, 1., d->dx_feas, d->z_feas);
870  }
871 
872  // Evaluate g
873  m->arg[0] = d->z_feas;
874  m->arg[1] = d_nlp->p;
875  m->res[0] = d->z_feas + nx_;
876  if (calc_function(m, "nlp_g")) {
877  uout() << "What does it mean that calc_function fails here??" << std::endl;
878  }
879 
880  // self.curr_infeas = self.feasibility_measure(self.x_tmp, self.g_tmp)
881  // self.prev_infeas = self.curr_infeas
882  prev_infeas = casadi_max_viol(nx_+ng_, d->z_feas, d_nlp->lbz, d_nlp->ubz);
883  curr_infeas = prev_infeas;
884  // kappa = self.step_inf_norm/self.prev_step_inf_norm
885  // kappas.append(kappa)
886  kappa = step_inf_norm/prev_step_inf_norm;
887  //MISSING: as_exac:
888 
889  // DM(std::vector<double>(d_nlp->z, d_nlp->z+nx_)).to_file("x_k.mtx");
890  // DM(std::vector<double>(d->z_feas,d->z_feas+nx_)).to_file("x_tmp.mtx");
891  // DM(std::vector<double>(d->dx_feas,d->dx_feas+nx_)).to_file("dx_feas"+suffix+".mtx");
892  // DM(std::vector<double>(d->dx,d->dx+nx_)).to_file("p_k.mtx");
893 
894 
895  casadi_copy(d->dx, nx_, d->z_tmp);
896  casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
897  casadi_axpy(nx_, 1., d_nlp->z, d->z_tmp);
898  as_exac = casadi_norm_2(nx_, d->z_tmp) / casadi_norm_2(nx_, d->dx);
899 
900 
901  // as_exac = cs.norm_2(
902  // self.p_k - (self.x_tmp - self.x_k)) / cs.norm_2(self.p_k)
903 
904  // if self.verbose:
905  // print("Kappa: ", kappa,
906  // "Infeasibility", self.feasibility_measure(
907  // self.x_tmp, self.g_tmp),
908  // "Asymptotic Exactness: ", as_exac)
909  print("%6s %9.10f %14s %9.10f %20s %9.10f\n", "Kappa:", kappa,
910  "Infeasibility:", curr_infeas, "AsymptoticExactness:", as_exac);
911 
912  // accumulated_as_ex += as_exac
913  acc_as_exac += as_exac;
914  // if inner_iter % self.watchdog == 0:
915  // kappa_watch = self.step_inf_norm/watchdog_prev_inf_norm
916  // watchdog_prev_inf_norm = self.step_inf_norm
917  // if self.verbose:
918  // print("kappa watchdog: ", kappa_watch)
919  // if self.curr_infeas < self.feas_tol and as_exac < 0.5:
920  // self.kappa_acceptance = True
921  // break
922  if (inner_iter % watchdog_ == 0) {
923  kappa_watchdog = step_inf_norm / watchdog_prev_inf_norm;
924  watchdog_prev_inf_norm = step_inf_norm;
925  print("Kappa watchdog: %9.10f\n", kappa_watchdog);
926  if (curr_infeas < feas_tol_ && as_exac < 0.5) {
927  // kappa_acceptance = true;
928  return 0;
929  }
930  // if kappa_watch > self.contraction_acceptance or
931  // accumulated_as_ex/self.watchdog > 0.5:
932  // self.kappa_acceptance = False
933  // break
934  if (kappa_watchdog > contraction_acceptance_value_ || acc_as_exac/watchdog_ > 0.5) {
935  // kappa_acceptance = false;
936  return -1;
937  }
938  // accumulated_as_ex = 0
939  acc_as_exac = 0.0;
940  }
941 
942  // Do some saving here??
943  // feasibilities.append(
944  // self.feasibility_measure(self.x_tmp, self.g_tmp))
945  // asymptotic_exactness.append(as_exac)
946  // step_norms.append(cs.norm_inf(p_tmp))
947 
948  // self.prev_step_inf_norm = self.step_inf_norm
949  // self.lam_tmp_g = self.lam_p_g_k
950  // self.lam_tmp_x = self.lam_p_x_k
951  prev_step_inf_norm = step_inf_norm;
952  }
953  //maximum iterations reached
954  // kappa_acceptance = false;
955  return -1;
956 }
957 
958 int Feasiblesqpmethod::solve(void* mem) const {
959  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
960  auto d_nlp = &m->d_nlp;
961  auto d = &m->d;
962 
963  // DM(std::vector<double>(d_nlp->z, d_nlp->z+nx_)).to_file("x0.mtx");
964  // Number of SQP iterations
965  m->iter_count = 0;
966 
967  // Reset
968  // m->merit_ind = 0;
969  // m->sigma = 0.; // NOTE: Move this into the main optimization loop
970  // m->reg = 0;
971  int step_accepted = 0;
972 
973  // Default quadratic model value of objective
974  double m_k = -1.0;
975 
976  double tr_ratio = 0.0;
977 
978  double tr_rad = tr_rad0_;
979  double tr_rad_prev = tr_rad0_;
980 
981  // transfer the scale vector to the problem
982  casadi_copy(get_ptr(tr_scale_vector_), nx_, d->tr_scale_vector);
983 
984  for (casadi_int i=0;i<nx_;++i) {
985  d->tr_mask[i] = d->tr_scale_vector[i]!=0;
986  }
987 
988  // For seeds ---- This is so far needed!!! ------------------
989  const double one = 1.;
990 
991  // Info for printing
992  std::string info = "";
993 
994  casadi_clear(d->dx, nx_);
995 
996  // ------------------------------------------------------------------------
997  // MAIN OPTIMIZATION LOOP
998  // ------------------------------------------------------------------------
999  while (true) {
1000  // Evaluate f, g and first order derivative information
1001  /*m->arg[0] = d_nlp->z;
1002  m->arg[1] = d_nlp->p;
1003  m->res[0] = &d_nlp->objective;
1004  m->res[1] = d->gf;
1005  m->res[2] = d_nlp->z + nx_;
1006  m->res[3] = d->Jk;
1007  switch (calc_function(m, "nlp_jac_fg")) {
1008  case -1:
1009  m->return_status = "Non_Regular_Sensitivities";
1010  m->unified_return_status = SOLVER_RET_NAN;
1011  if (print_status_)
1012  print("MESSAGE(feasiblesqpmethod): No regularity of sensitivities at current point.\n");
1013  return 1;
1014  case 0:
1015  break;
1016  default:
1017  return 1;
1018  }*/
1019  if (m->iter_count == 0) {
1020  // Evaluate the sensitivities -------------------------------------------
1021  // Evaluate f
1022  m->arg[0] = d_nlp->z;
1023  m->arg[1] = d_nlp->p;
1024  m->res[0] = &d_nlp->objective;
1025  if (calc_function(m, "nlp_f")) {
1026  uout() << "What does it mean that calc_function fails here??" << std::endl;
1027  }
1028  // Evaluate g
1029  m->arg[0] = d_nlp->z;
1030  m->arg[1] = d_nlp->p;
1031  m->res[0] = d_nlp->z + nx_;
1032  if (calc_function(m, "nlp_g")) {
1033  uout() << "What does it mean that calc_function fails here??" << std::endl;
1034  }
1035  // Evaluate grad_f
1036  m->arg[0] = d_nlp->z;
1037  m->arg[1] = d_nlp->p;
1038  m->res[0] = d->gf;
1039  if (calc_function(m, "nlp_grad_f")) {
1040  uout() << "What does it mean that calc_function fails here??" << std::endl;
1041  }
1042  // Evaluate jac_g
1043  m->arg[0] = d_nlp->z;
1044  m->arg[1] = d_nlp->p;
1045  m->res[0] = d->Jk;
1046  switch (calc_function(m, "nlp_jac_g")) {
1047  case -1:
1048  m->return_status = "Non_Regular_Sensitivities";
1049  m->unified_return_status = SOLVER_RET_NAN;
1050  if (print_status_)
1051  print("MESSAGE(feasiblesqpmethod): "
1052  "No regularity of sensitivities at current point.\n");
1053  return 1;
1054  case 0:
1055  break;
1056  default:
1057  return 1;
1058 
1059  }
1060  // uout() << "x0: " << *d_nlp->z << std::endl;
1061  // uout() << "nlp_f: " << d_nlp->objective << std::endl;
1062  // uout() << "nlp_g: " << *(d_nlp->z + nx_) << std::endl;
1063 
1064  if (use_sqp_) {
1065  if (exact_hessian_) {
1066  // Update/reset exact Hessian
1067  m->arg[0] = d_nlp->z;
1068  m->arg[1] = d_nlp->p;
1069  m->arg[2] = &one;
1070  m->arg[3] = d_nlp->lam + nx_;
1071  m->res[0] = d->Bk;
1072  if (calc_function(m, "nlp_hess_l")) return 1;
1073  if (convexify_) {
1074  ScopedTiming tic(m->fstats.at("convexify"));
1075  if (casadi_convexify_eval(&convexify_data_.config,
1076  d->Bk, d->Bk, m->iw, m->w)) return 1;
1077  }
1078  } else if (m->iter_count==0) {
1079  ScopedTiming tic(m->fstats.at("BFGS"));
1080  // Initialize BFGS
1081  casadi_fill(d->Bk, Hsp_.nnz(), 1.);
1082  casadi_bfgs_reset(Hsp_, d->Bk);
1083  } else {
1084  ScopedTiming tic(m->fstats.at("BFGS"));
1085  // Update BFGS
1086  if (m->iter_count % lbfgs_memory_ == 0) casadi_bfgs_reset(Hsp_, d->Bk);
1087  // Update the Hessian approximation
1088  casadi_bfgs(Hsp_, d->Bk, d->dx, d->gLag, d->gLag_old, m->w);
1089  }
1090 
1091  // test if initialization is feasible
1092  if (casadi_max_viol(nx_ + ng_, d_nlp->z, d_nlp->lbz, d_nlp->ubz) > feas_tol_) {
1093  if (print_status_)print("MESSAGE(feasiblesqpmethod): "
1094  "No feasible initialization given! "
1095  "Find feasible initialization.\n");
1096  m->return_status = "No_Feasible_Initialization";
1097  break;
1098  }
1099  }
1100 
1101  } else if (step_accepted == 0) {
1102  // Evaluate grad_f
1103  m->arg[0] = d_nlp->z;
1104  m->arg[1] = d_nlp->p;
1105  m->res[0] = d->gf;
1106  if (calc_function(m, "nlp_grad_f")) {
1107  uout() << "What does it mean that calc_function fails here??" << std::endl;
1108  }
1109  // Evaluate jac_g
1110  m->arg[0] = d_nlp->z;
1111  m->arg[1] = d_nlp->p;
1112  m->res[0] = d->Jk;
1113  switch (calc_function(m, "nlp_jac_g")) {
1114  case -1:
1115  m->return_status = "Non_Regular_Sensitivities";
1116  m->unified_return_status = SOLVER_RET_NAN;
1117  if (print_status_)
1118  print("MESSAGE(feasiblesqpmethod): "
1119  "No regularity of sensitivities at current point.\n");
1120  return 1;
1121  case 0:
1122  break;
1123  default:
1124  return 1;
1125  }
1126  // uout() << "x0: " << *d_nlp->z << std::endl;
1127  // uout() << "nlp_f: " << d_nlp->objective << std::endl;
1128  // uout() << "nlp_g: " << *(d_nlp->z + nx_) << std::endl;
1129 
1130  if (use_sqp_) {
1131  if (exact_hessian_) {
1132  // Update/reset exact Hessian
1133  m->arg[0] = d_nlp->z;
1134  m->arg[1] = d_nlp->p;
1135  m->arg[2] = &one;
1136  m->arg[3] = d_nlp->lam + nx_;
1137  m->res[0] = d->Bk;
1138  if (calc_function(m, "nlp_hess_l")) return 1;
1139  if (convexify_) {
1140  ScopedTiming tic(m->fstats.at("convexify"));
1141  if (casadi_convexify_eval(&convexify_data_.config,
1142  d->Bk, d->Bk, m->iw, m->w)) return 1;
1143  }
1144  } else if (m->iter_count==0) {
1145  ScopedTiming tic(m->fstats.at("BFGS"));
1146  // Initialize BFGS
1147  casadi_fill(d->Bk, Hsp_.nnz(), 1.);
1148  casadi_bfgs_reset(Hsp_, d->Bk);
1149  } else {
1150  ScopedTiming tic(m->fstats.at("BFGS"));
1151  // Update BFGS
1152  if (m->iter_count % lbfgs_memory_ == 0) casadi_bfgs_reset(Hsp_, d->Bk);
1153  // Update the Hessian approximation
1154  casadi_bfgs(Hsp_, d->Bk, d->dx, d->gLag, d->gLag_old, m->w);
1155  }
1156  }
1157  }
1158 
1159  // Evaluate the gradient of the Lagrangian
1160  casadi_copy(d->gf, nx_, d->gLag);
1161  casadi_mv(d->Jk, Asp_, d_nlp->lam+nx_, d->gLag, true);
1162  casadi_axpy(nx_, 1., d_nlp->lam, d->gLag);
1163 
1164  // Primal infeasability
1165  double pr_inf = casadi_max_viol(nx_+ng_, d_nlp->z, d_nlp->lbz, d_nlp->ubz);
1166  // uout() << "pr_inf: " << pr_inf << std::endl;
1167  // inf-norm of Lagrange gradient
1168  // uout() << "grad Lag: " << std::vector<double>(*d->gLag,0,nx_) << std::endl;
1169  double du_inf = casadi_norm_inf(nx_, d->gLag);
1170  // uout() << "du_inf: " << du_inf << std::endl;
1171 
1172  // inf-norm of step, d->dx is a nullptr???
1173  // uout() << "HERE!!!!" << *d->dx << std::endl;
1174  double dx_norminf = casadi_norm_inf(nx_, d->dx);
1175 
1176  // uout() << "objective value: " << d_nlp->objective << std::endl;
1177  // Printing information about the actual iterate
1178  if (print_iteration_) {
1179  // if (m->iter_count % 10 == 0) print_iteration();
1180  print_iteration();
1181  print_iteration(m->iter_count, d_nlp->objective, m_k, tr_ratio,
1182  pr_inf, du_inf, dx_norminf, m->reg, tr_rad_prev, info);
1183  info = "";
1184  }
1185  tr_rad_prev = tr_rad;
1186 
1187  // Callback function
1188  if (callback(m)) {
1189  if (print_status_) print("WARNING(feasiblesqpmethod): Aborted by callback...\n");
1190  m->return_status = "User_Requested_Stop";
1191  break;
1192  }
1193 
1194  // Checking convergence criteria
1195  // Where is the complementarity condition??
1196  // if (m->iter_count >= min_iter_ && pr_inf < tol_pr_ && du_inf < tol_du_) {
1197  // if (print_status_)
1198  // print("MESSAGE(feasiblesqpmethod): "
1199  // "Convergence achieved after %d iterations\n", m->iter_count);
1200  // m->return_status = "Solve_Succeeded";
1201  // m->success = true;
1202  // break;
1203  // }
1204 
1205  if (m->iter_count >= max_iter_) {
1206  if (print_status_) {
1207  print("MESSAGE(feasiblesqpmethod): Maximum number of iterations reached.\n");
1208  }
1209  m->return_status = "Maximum_Iterations_Exceeded";
1210  m->unified_return_status = SOLVER_RET_LIMITED;
1211  break;
1212  }
1213 
1214  // Formulate the QP
1215  // Define lower bounds
1216  casadi_copy(d_nlp->lbz, nx_+ng_, d->lbdz);
1217  casadi_axpy(nx_+ng_, -1., d_nlp->z, d->lbdz);
1218  casadi_clip_min(d->lbdz, nx_, -tr_rad, d->tr_mask);
1219  // uout() << "lbdz: " << std::vector<double>(d->lbdz, d->lbdz+nx_) << std::endl;
1220 
1221 
1222  // Define upper bounds
1223  casadi_copy(d_nlp->ubz, nx_+ng_, d->ubdz);
1224  casadi_axpy(nx_+ng_, -1., d_nlp->z, d->ubdz);
1225  casadi_clip_max(d->ubdz, nx_, tr_rad, d->tr_mask);
1226  // uout() << "ubdz: " << std::vector<double>(d->ubdz, d->ubdz+nx_) << std::endl;
1227 
1228  // Initial guess
1229  casadi_copy(d_nlp->lam, nx_+ng_, d->dlam);
1230  //casadi_clear(d->dx, nx_);
1231 
1232  // Increase counter
1233  m->iter_count++;
1234 
1235  // DM(std::vector<double>(d->gf,d->gf+nx_)).to_file("gf.mtx");
1236  // DM(std::vector<double>(d->lbdz, d->lbdz+nx_)).to_file("lb_var.mtx");
1237  // DM(std::vector<double>(d->ubdz, d->ubdz+nx_)).to_file("ub_var.mtx");
1238  // DM(std::vector<double>(d->lbdz+nx_, d->lbdz+nx_+ng_)).to_file("lba.mtx");
1239  // DM(std::vector<double>(d->ubdz+nx_, d->ubdz+nx_+ng_)).to_file("uba.mtx");
1240  // // DM(std::vector<double>(d->Bk, d->Bk+Hsp_.nnz())).to_file("Bk.mtx");
1241  // DM(std::vector<double>(d->Jk, d->Jk+Asp_.nnz())).to_file("Jk.mtx");
1242  // DM(std::vector<double>(d->dlam, d->dlam+nx_)).to_file("lam_x.mtx");
1243  // DM(std::vector<double>(d->dx, d->dx+nx_)).to_file("dx_input.mtx");
1244  // DM(std::vector<double>(d->dlam+nx_, d->dlam+nx_+ng_)).to_file("lam_g.mtx");
1245 
1246  int ret = 0;
1247  // Solve the QP
1248  if (use_sqp_) {
1249  ret = solve_QP(m, d->Bk, d->gf, d->lbdz, d->ubdz, d->Jk,
1250  d->dx, d->dlam, 0);
1251  } else {
1252  ret = solve_LP(m, d->gf, d->lbdz, d->ubdz, d->Jk,
1253  d->dx, d->dlam, 0);
1254  }
1255 
1256  // DM(std::vector<double>(d->dx,d->dx+nx_)).to_file("dx_out.mtx");
1257  // Eval quadratic model and check for convergence
1258  m_k = eval_m_k(mem);
1259  if (fabs(m_k) < optim_tol_) {
1260  if (print_status_)
1261  print("MESSAGE(feasiblesqpmethod): "
1262  "Optimal Point Found? Quadratic model is zero. "
1263  "After %d iterations\n", m->iter_count-1);
1264  m->return_status = "Solve_Succeeded";
1265  m->success = true;
1266  break;
1267  }
1268 
1269  // uout() << "QP step: " << std::vector<double>(d->dx, d->dx+nx_) << std::endl;
1270  // Detecting indefiniteness
1271  if (use_sqp_) {
1272  double gain = casadi_bilin(d->Bk, Hsp_, d->dx, d->dx);
1273  if (gain < 0) {
1274  if (print_status_) print("WARNING(feasiblesqpmethod): Indefinite Hessian detected\n");
1275  }
1276  }
1277 
1278  // Do the feasibility iterations here
1279  ret = feasibility_iterations(mem, tr_rad);
1280 
1281  // Check if step was accepted or not
1282  if (ret < 0) {
1283  uout() << "Rejected inner iterates" << std::endl;
1284  // uout() << casadi_masked_norm_inf(nx_, d->dx, d->tr_mask) << std::endl;
1285 
1286  tr_rad = 0.5 * casadi_masked_norm_inf(nx_, d->dx, d->tr_mask);
1287  } else {
1288  // Evaluate f
1289  m->arg[0] = d->z_feas;
1290  m->arg[1] = d_nlp->p;
1291  m->res[0] = &d->f_feas;
1292  if (calc_function(m, "nlp_f")) {
1293  uout() << "What does it mean that calc_function fails here??" << std::endl;
1294  }
1295  tr_ratio = eval_tr_ratio(d_nlp->objective, d->f_feas, m_k);
1296  tr_update(mem, tr_rad, tr_ratio);
1297  if (tr_rad < feas_tol_) {
1298  if (print_status_) print("MESSAGE(feasiblesqpmethod): "
1299  "Trust-region radius smaller than feasibility!! "
1300  "Abort!!.\n");
1301  m->return_status = "Trust_Region_Radius_Becomes_Too_Small";
1302  break;
1303  }
1304 
1305  step_accepted = step_update(mem, tr_ratio);
1306  }
1307 
1308  if (!exact_hessian_) {
1309  // Evaluate the gradient of the Lagrangian with the old x but new lam (for BFGS)
1310  casadi_copy(d->gf, nx_, d->gLag_old);
1311  casadi_mv(d->Jk, Asp_, d_nlp->lam+nx_, d->gLag_old, true);
1312  casadi_axpy(nx_, 1., d_nlp->lam, d->gLag_old);
1313  }
1314  }
1315 
1316  return 0;
1317  }
1318 
1320  print("%4s %9s %14s %9s %9s %9s %9s %7s %5s %7s\n",
1321  "iter", "m_k", "objective", "tr_ratio", "inf_pr",
1322  "inf_du", "||d||", "lg(rg)", "tr_rad", "info");
1323  }
1324 
1325  void Feasiblesqpmethod::print_iteration(casadi_int iter, double obj,
1326  double m_k, double tr_ratio,
1327  double pr_inf, double du_inf,
1328  double dx_norm, double rg,
1329  double tr_rad,
1330  std::string info) const {
1331  print("%4d %9.2e %14.6e %9.2e %9.2e %9.2e %9.2e ",
1332  iter, m_k, obj, tr_ratio, pr_inf, du_inf, dx_norm);
1333  if (rg>0) {
1334  print("%7.2f ", log10(rg));
1335  } else {
1336  print("%7s ", "-");
1337  }
1338 
1339  print("%9.5e", tr_rad);
1340  // if (!ls_success) {
1341  // print("F");
1342  // } else {
1343  // print (" ");
1344  // }
1345 
1346  print(" - ");
1347  print(info.c_str());
1348  print("\n");
1349  }
1350 
1352  const double* lbdz, const double* ubdz, const double* A,
1353  double* x_opt, double* dlam, int mode) const {
1354  ScopedTiming tic(m->fstats.at("QP"));
1355  // Inputs
1356  std::fill_n(m->arg, qpsol_.n_in(), nullptr);
1357  // double lol;
1358  m->arg[CONIC_H] = nullptr;
1359  m->arg[CONIC_G] = g;
1360  m->arg[CONIC_X0] = x_opt;
1361  m->arg[CONIC_LAM_X0] = dlam;
1362  m->arg[CONIC_LAM_A0] = dlam + nx_;
1363  m->arg[CONIC_LBX] = lbdz;
1364  m->arg[CONIC_UBX] = ubdz;
1365  m->arg[CONIC_A] = A;
1366  m->arg[CONIC_LBA] = lbdz+nx_;
1367  m->arg[CONIC_UBA] = ubdz+nx_;
1368 
1369  // Outputs
1370  std::fill_n(m->res, qpsol_.n_out(), nullptr);
1371  m->res[CONIC_X] = x_opt;
1372  m->res[CONIC_LAM_X] = dlam;
1373  m->res[CONIC_LAM_A] = dlam + nx_;
1374  double obj;
1375  m->res[CONIC_COST] = &obj;
1376  // m->res[CONIC_COST] = nullptr;
1377 
1378 
1379  // Solve the QP
1380  qpsol_(m->arg, m->res, m->iw, m->w);
1381 
1382  if (verbose_) print("QP solved\n");
1383  return 0;
1384  }
1385 
1386  int Feasiblesqpmethod::solve_QP(FeasiblesqpmethodMemory* m, const double* H, const double* g,
1387  const double* lbdz, const double* ubdz, const double* A,
1388  double* x_opt, double* dlam, int mode) const {
1389  ScopedTiming tic(m->fstats.at("QP"));
1390  // Inputs
1391  std::fill_n(m->arg, qpsol_.n_in(), nullptr);
1392  m->arg[CONIC_H] = H;
1393  m->arg[CONIC_G] = g;
1394  m->arg[CONIC_X0] = x_opt;
1395  m->arg[CONIC_LAM_X0] = dlam;
1396  m->arg[CONIC_LAM_A0] = dlam + nx_;
1397  m->arg[CONIC_LBX] = lbdz;
1398  m->arg[CONIC_UBX] = ubdz;
1399  m->arg[CONIC_A] = A;
1400  m->arg[CONIC_LBA] = lbdz+nx_;
1401  m->arg[CONIC_UBA] = ubdz+nx_;
1402 
1403  // Outputs
1404  std::fill_n(m->res, qpsol_.n_out(), nullptr);
1405  m->res[CONIC_X] = x_opt;
1406  m->res[CONIC_LAM_X] = dlam;
1407  m->res[CONIC_LAM_A] = dlam + nx_;
1408  double obj;
1409  m->res[CONIC_COST] = &obj;
1410  // m->res[CONIC_COST] = nullptr;
1411 
1412 
1413  // Solve the QP
1414  qpsol_(m->arg, m->res, m->iw, m->w);
1415 
1416  if (verbose_) print("QP solved\n");
1417  return 0;
1418  }
1419 
1422  g.add_dependency(get_function("nlp_grad_f"));
1423  g.add_dependency(get_function("nlp_jac_g"));
1424  g.add_dependency(get_function("nlp_g"));
1425  g.add_dependency(get_function("nlp_f"));
1426  if (exact_hessian_) g.add_dependency(get_function("nlp_hess_l"));
1428  }
1429 
1432  codegen_body_enter(g);
1433  // From nlpsol
1434  g.local("m_p", "const casadi_real", "*");
1435  g.init_local("m_p", g.arg(NLPSOL_P));
1436  g.local("m_f", "casadi_real");
1437  g.local("m_f_feas", "casadi_real");
1438  g.copy_default(g.arg(NLPSOL_X0), nx_, "d_nlp.z", "0", false);
1439  g.copy_default(g.arg(NLPSOL_LAM_X0), nx_, "d_nlp.lam", "0", false);
1440  g.copy_default(g.arg(NLPSOL_LAM_G0), ng_, "d_nlp.lam+"+str(nx_), "0", false);
1441  g.copy_default(g.arg(NLPSOL_LBX), nx_, "d_nlp.lbz", "-casadi_inf", false);
1442  g.copy_default(g.arg(NLPSOL_UBX), nx_, "d_nlp.ubz", "casadi_inf", false);
1443  g.copy_default(g.arg(NLPSOL_LBG), ng_, "d_nlp.lbz+"+str(nx_),
1444  "-casadi_inf", false);
1445  g.copy_default("d_nlp.ubg", ng_, "d_nlp.ubz+"+str(nx_),
1446  "casadi_inf", false);
1447  casadi_assert(exact_hessian_, "Codegen implemented for exact Hessian only.", false);
1448 
1449  // auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
1450  // auto d_nlp = &m->d_nlp;
1451  // auto d = &m->d;
1452  // Define the problem struct and problem data struct here
1453  g.local("d", "struct casadi_feasiblesqpmethod_data");
1454  g.local("p", "struct casadi_feasiblesqpmethod_prob");
1455 
1456  g << "d.prob = &p;\n";
1457  g << "p.sp_h = " << g.sparsity(Hsp_) << ";\n";
1458  g << "p.sp_a = " << g.sparsity(Asp_) << ";\n";
1459  g << "p.nlp = &p_nlp;\n";
1460  g << "p.sz_anderson_memory = " << sz_anderson_memory_ << ";\n";
1461  g << "casadi_feasiblesqpmethod_set_work(&d, &arg, &res, &iw, &w);\n";
1462 
1463  g.local("m_w", "casadi_real", "*");
1464  g << "m_w = w;\n";
1465  g.local("m_iw", "casadi_int", "*");
1466  g << "m_iw = iw;\n";
1467  g.local("m_arg", "const casadi_real", "**");
1468  g.init_local("m_arg", "arg+" + str(NLPSOL_NUM_IN));
1469  g.local("m_res", "casadi_real", "**");
1470  g.init_local("m_res", "res+" + str(NLPSOL_NUM_OUT));
1471 
1472  // g.local("ret", "int");
1473  g.local("ret", "casadi_int");
1474 
1475  // Number of SQP iterations
1476  // m->iter_count = 0;
1477  g.local("iter_count", "casadi_int");
1478  g.init_local("iter_count", "0");
1479 
1480  // Reset
1481  // int step_accepted = 0;
1482  g.local("step_accepted", "casadi_int");
1483  g.init_local("step_accepted", "0");
1484 
1485  // Default quadratic model value of objective
1486  // double m_k = -1.0;
1487  g.local("m_k", "casadi_real");
1488  g.init_local("m_k", "-1.0");
1489 
1490  // double tr_ratio = 0.0;
1491  g.local("tr_ratio", "casadi_real");
1492  g.init_local("tr_ratio", "0.0");
1493 
1494  // double tr_rad = tr_rad0_;
1495  // double tr_rad_prev = tr_rad0_;
1496  g.local("tr_rad", "casadi_real");
1497  g << "tr_rad = " << tr_rad0_ << ";\n";
1498  g.local("tr_rad_prev", "casadi_real");
1499  g << "tr_rad_prev = " << tr_rad0_ << ";\n";
1500 
1501  // transfer the scale vector to the problem
1502  // casadi_copy(get_ptr(tr_scale_vector_), nx_, d->tr_scale_vector);
1503  //transfer the scale vector to the problem
1504  g << g.copy(g.constant(tr_scale_vector_), nx_, "d.tr_scale_vector") << "\n";
1505  // g << g.copy("casadi_tr_scale_vector_", nx_, "d.tr_scale_vector") << "\n";
1506 
1507  // for (casadi_int i=0;i<nx_;++i) {
1508  // d->tr_mask[i] = d->tr_scale_vector[i]!=0;
1509  // }
1510  g << "for (casadi_int i = 0; i < " << nx_ << "; ++i) {\n";
1511  g << "d.tr_mask[i] = d.tr_scale_vector != 0;\n";
1512  g << "}\n";
1513 
1514 
1515  // HERE STARTS THE MAIN OPTIMIZATION LOOP ---------------------------------
1516  // For seeds ---- This is so far needed!!! ------------------
1517  // const double one = 1.;
1518  g.local("one", "const casadi_real");
1519  g.init_local("one", "1");
1520 
1521  // Info for printing
1522  // string info = "";
1523 
1524  // casadi_clear(d->dx, nx_);
1525  g << g.clear("d.dx", nx_) << "\n";
1526 
1527  // ------------------------------------------------------------------------
1528  // MAIN OPTIMIZATION LOOP
1529  // ------------------------------------------------------------------------
1530  // while (true) {
1531  g.comment("MAIN OPTIMIZATION LOOP");
1532  g << "while (1) {\n";
1533  // if(m->iter_count == 0) {
1534  g << "if (iter_count == 0) {;\n";
1535  // Evaluate the sensitivities -------------------------------------------
1536  // Evaluate f
1537  // m->arg[0] = d_nlp->z;
1538  // m->arg[1] = d_nlp->p;
1539  // m->res[0] = &d_nlp->f;
1540  // if (calc_function(m, "nlp_f")) {
1541  // uout() << "What does it mean that calc_function fails here??" << std::endl;
1542  // }
1543  g.comment("Evaluate f");
1544  g << "m_arg[0] = d_nlp.z;\n";
1545  g << "m_arg[1] = m_p;\n";
1546  g << "m_res[0] = &m_f;\n";
1547  std::string nlp_f = g(get_function("nlp_f"), "m_arg", "m_res", "m_iw", "m_w");
1548  // g << "if (" + nlp_f + ") return 1;\n";
1549  g << "if (" + nlp_f + ") return 10;\n";
1550 
1551  // Evaluate g
1552  // m->arg[0] = d_nlp->z;
1553  // m->arg[1] = d_nlp->p;
1554  // m->res[0] = d_nlp->z + nx_;
1555  // if (calc_function(m, "nlp_g")) {
1556  // uout() << "What does it mean that calc_function fails here??" << std::endl;
1557  // }
1558  g.comment("Evaluate g");
1559  g << "m_arg[0] = d_nlp.z;\n";
1560  g << "m_arg[1] = m_p;\n";
1561  g << "m_res[0] = d_nlp.z+" + str(nx_) + ";\n";
1562  std::string nlp_g = g(get_function("nlp_g"), "m_arg", "m_res", "m_iw", "m_w");
1563  // g << "if (" + nlp_g + ") return 1;\n";
1564  g << "if (" + nlp_g + ") return 20;\n";
1565 
1566  // Evaluate grad_f
1567  // m->arg[0] = d_nlp->z;
1568  // m->arg[1] = d_nlp->p;
1569  // m->res[0] = d->gf;
1570  // if (calc_function(m, "nlp_grad_f")) {
1571  // uout() << "What does it mean that calc_function fails here??" << std::endl;
1572  // }
1573  g.comment("Evaluate grad f");
1574  g << "m_arg[0] = d_nlp.z;\n";
1575  g << "m_arg[1] = m_p;\n";
1576  g << "m_res[0] = d.gf;\n";
1577  std::string nlp_grad_f = g(get_function("nlp_grad_f"), "m_arg", "m_res", "m_iw", "m_w");
1578  // g << "if (" + nlp_grad_f + ") return 1;\n";
1579  g << "if (" + nlp_grad_f + ") return 30;\n";
1580 
1581  // Evaluate jac_g
1582  // m->arg[0] = d_nlp->z;
1583  // m->arg[1] = d_nlp->p;
1584  // m->res[0] = d->Jk;
1585  // switch (calc_function(m, "nlp_jac_g")) {
1586  // case -1:
1587  // m->return_status = "Non_Regular_Sensitivities";
1588  // m->unified_return_status = SOLVER_RET_NAN;
1589  // if (print_status_)
1590  // print("MESSAGE(feasiblesqpmethod): "
1591  // "No regularity of sensitivities at current point.\n");
1592  // return 1;
1593  // case 0:
1594  // break;
1595  // default:
1596  // return 1;
1597 
1598  // }
1599  g.comment("Evaluate jac g");
1600  g << "m_arg[0] = d_nlp.z;\n";
1601  g << "m_arg[1] = m_p;\n";
1602  g << "m_res[0] = d.Jk;\n";
1603  std::string nlp_jac_g = g(get_function("nlp_jac_g"), "m_arg", "m_res", "m_iw", "m_w");
1604  // g << "if (" + nlp_jac_g + ") return 1;\n";
1605  g << "if (" + nlp_jac_g + ") return 40;\n";
1606 
1607  // if (use_sqp_) {
1608  // if (exact_hessian_) {
1609  // // Update/reset exact Hessian
1610  // m->arg[0] = d_nlp->z;
1611  // m->arg[1] = d_nlp->p;
1612  // m->arg[2] = &one;
1613  // m->arg[3] = d_nlp->lam + nx_;
1614  // m->res[0] = d->Bk;
1615  // if (calc_function(m, "nlp_hess_l")) return 1;
1616  // if (convexify_) {
1617  // ScopedTiming tic(m->fstats.at("convexify"));
1618  // if (casadi_convexify_eval(&convexify_data_.config,
1619  // d->Bk, d->Bk, m->iw, m->w)) return 1;
1620  // }
1621  // } else if (m->iter_count==0) {
1622  // ScopedTiming tic(m->fstats.at("BFGS"));
1623  // // Initialize BFGS
1624  // casadi_fill(d->Bk, Hsp_.nnz(), 1.);
1625  // casadi_bfgs_reset(Hsp_, d->Bk);
1626  // } else {
1627  // ScopedTiming tic(m->fstats.at("BFGS"));
1628  // // Update BFGS
1629  // if (m->iter_count % lbfgs_memory_ == 0) casadi_bfgs_reset(Hsp_, d->Bk);
1630  // // Update the Hessian approximation
1631  // casadi_bfgs(Hsp_, d->Bk, d->dx, d->gLag, d->gLag_old, m->w);
1632  // }
1633  g.comment("Just exact Hessian implemented, GN would be possible!");
1634  g << "m_arg[0] = d_nlp.z;\n";
1635  g << "m_arg[1] = m_p;\n";
1636  g << "m_arg[2] = &one;\n";
1637  g << "m_arg[3] = d_nlp.lam+" + str(nx_) + ";\n";
1638  g << "m_res[0] = d.Bk;\n";
1639  std::string nlp_hess_l = g(get_function("nlp_hess_l"), "m_arg", "m_res", "m_iw", "m_w");
1640  // g << "if (" + nlp_hess_l + ") return 1;\n";
1641  g << "if (" + nlp_hess_l + ") return 70;\n";
1642 
1643  // }
1644  // test if initialization is feasible
1645  // if (casadi_max_viol(nx_ + ng_, d_nlp->z, d_nlp->lbz, d_nlp->ubz) > feas_tol_) {
1646  // if (print_status_) print("MESSAGE(feasiblesqpmethod): "
1647  // "No feasible initialization given! "
1648  // "Find feasible initialization.\n");
1649  // m->return_status = "No_Feasible_Initialization";
1650  // break;
1651  // }
1652  std::string viol = g.max_viol(nx_+ ng_, "d_nlp.z", "d_nlp.lbz", "d_nlp.ubz");
1653  g << "if (" << viol << "> " << feas_tol_ << ") {\n";
1654  g << "printf(\"MESSAGE(feasiblesqpmethod): "
1655  "No feasible initialization given! Find feasible initialization.\\n\");\n";
1656  g << "break;\n";
1657  g << "}\n";
1658 
1659  // } else if (step_accepted == 0) {
1660  g << "} else if (step_accepted == 0) {\n";
1661  // Evaluate grad_f
1662  // m->arg[0] = d_nlp->z;
1663  // m->arg[1] = d_nlp->p;
1664  // m->res[0] = d->gf;
1665  // if (calc_function(m, "nlp_grad_f")) {
1666  // uout() << "What does it mean that calc_function fails here??" << std::endl;
1667  // }
1668  g.comment("Evaluate grad f");
1669  g << "m_arg[0] = d_nlp.z;\n";
1670  g << "m_arg[1] = m_p;\n";
1671  g << "m_res[0] = d.gf;\n";
1672  nlp_grad_f = g(get_function("nlp_grad_f"), "m_arg", "m_res", "m_iw", "m_w");
1673  // g << "if (" + nlp_grad_f + ") return 1;\n";
1674  g << "if (" + nlp_grad_f + ") return 50;\n";
1675 
1676  // Evaluate jac_g
1677  // m->arg[0] = d_nlp->z;
1678  // m->arg[1] = d_nlp->p;
1679  // m->res[0] = d->Jk;
1680  // switch (calc_function(m, "nlp_jac_g")) {
1681  // case -1:
1682  // m->return_status = "Non_Regular_Sensitivities";
1683  // m->unified_return_status = SOLVER_RET_NAN;
1684  // if (print_status_)
1685  // print("MESSAGE(feasiblesqpmethod): "
1686  // "No regularity of sensitivities at current point.\n");
1687  // return 1;
1688  // case 0:
1689  // break;
1690  // default:
1691  // return 1;
1692  // }
1693  g.comment("Evaluate jac g");
1694  g << "m_arg[0] = d_nlp.z;\n";
1695  g << "m_arg[1] = m_p;\n";
1696  g << "m_res[0] = d.Jk;\n";
1697  nlp_jac_g = g(get_function("nlp_jac_g"), "m_arg", "m_res", "m_iw", "m_w");
1698  // g << "if (" + nlp_jac_g + ") return 1;\n";
1699  g << "if (" + nlp_jac_g + ") return 60;\n";
1700 
1701  // if (use_sqp_) {
1702  // if (exact_hessian_) {
1703  // // Update/reset exact Hessian
1704  // m->arg[0] = d_nlp->z;
1705  // m->arg[1] = d_nlp->p;
1706  // m->arg[2] = &one;
1707  // m->arg[3] = d_nlp->lam + nx_;
1708  // m->res[0] = d->Bk;
1709  // if (calc_function(m, "nlp_hess_l")) return 1;
1710  // if (convexify_) {
1711  // ScopedTiming tic(m->fstats.at("convexify"));
1712  // if (casadi_convexify_eval(&convexify_data_.config,
1713  // d->Bk, d->Bk, m->iw, m->w)) return 1;
1714  // }
1715  // } else if (m->iter_count==0) {
1716  // ScopedTiming tic(m->fstats.at("BFGS"));
1717  // // Initialize BFGS
1718  // casadi_fill(d->Bk, Hsp_.nnz(), 1.);
1719  // casadi_bfgs_reset(Hsp_, d->Bk);
1720  // } else {
1721  // ScopedTiming tic(m->fstats.at("BFGS"));
1722  // // Update BFGS
1723  // if (m->iter_count % lbfgs_memory_ == 0) casadi_bfgs_reset(Hsp_, d->Bk);
1724  // // Update the Hessian approximation
1725  // casadi_bfgs(Hsp_, d->Bk, d->dx, d->gLag, d->gLag_old, m->w);
1726  // }
1727  // }
1728  g.comment("Just exact Hessian implemented, GN would be possible!");
1729  g << "m_arg[0] = d_nlp.z;\n";
1730  g << "m_arg[1] = m_p;\n";
1731  g << "m_arg[2] = &one;\n";
1732  g << "m_arg[3] = d_nlp.lam+" + str(nx_) + ";\n";
1733  g << "m_res[0] = d.Bk;\n";
1734  nlp_hess_l = g(get_function("nlp_hess_l"), "m_arg", "m_res", "m_iw", "m_w");
1735  // g << "if (" + nlp_hess_l + ") return 1;\n";
1736  g << "if (" + nlp_hess_l + ") return 70;\n";
1737 
1738  // }
1739  g << "}\n";
1740 
1741  // // Evaluate the gradient of the Lagrangian
1742  // casadi_copy(d->gf, nx_, d->gLag);
1743  // casadi_mv(d->Jk, Asp_, d_nlp->lam+nx_, d->gLag, true);
1744  // casadi_axpy(nx_, 1., d_nlp->lam, d->gLag);
1745  g.comment("Evaluate the gradient of the Lagrangian");
1746  g << g.copy("d.gf", nx_, "d.gLag") << "\n";
1747  g << g.mv("d.Jk", Asp_, "d_nlp.lam+"+str(nx_), "d.gLag", true) << "\n";
1748  g << g.axpy(nx_, "1.0", "d_nlp.lam", "d.gLag") << "\n";
1749 
1750  // Primal infeasability
1751  // double pr_inf = casadi_max_viol(nx_+ng_, d_nlp->z, d_nlp->lbz, d_nlp->ubz);
1752  g.comment("Primal infeasability");
1753  g.local("pr_inf", "casadi_real");
1754  g << "pr_inf = " << g.max_viol(nx_+ng_, "d_nlp.z", "d_nlp.lbz", "d_nlp.ubz") << ";\n";
1755 
1756  // inf-norm of Lagrange gradient
1757  // double du_inf = casadi_norm_inf(nx_, d->gLag);
1758  g.comment("inf-norm of lagrange gradient");
1759  g.local("du_inf", "casadi_real");
1760  g << "du_inf = " << g.norm_inf(nx_, "d.gLag") << ";\n";
1761 
1762  // inf-norm of step, d->dx is a nullptr???
1763  // double dx_norminf = casadi_norm_inf(nx_, d->dx);
1764  g.comment("inf-norm of step");
1765  g.local("dx_norminf", "casadi_real");
1766  g << "dx_norminf = " << g.norm_inf(nx_, "d.dx") << ";\n";
1767 
1768  // Printing information about the actual iterate
1769  // if (print_iteration_) {
1770  // // if (m->iter_count % 10 == 0) print_iteration();
1771  // print_iteration();
1772  // print_iteration(m->iter_count, d_nlp->f, m_k, tr_ratio,
1773  // pr_inf, du_inf, dx_norminf, m->reg, tr_rad_prev, info);
1774  // info = "";
1775  // }
1776  g << "if (" << print_iteration_ << ") {\n";
1777  g << "printf(\"%4s %9s %14s %9s %9s %9s %9s %5s\\n\", "
1778  "\"iter\", \"m_k\", \"objective\", \"tr_ratio\", "
1779  "\"inf_pr\",\"inf_du\", \"||d||\", \"tr_rad\");\n";
1780  g << "printf(\"%4lld %9.2e %14.6e %9.2e %9.2e %9.2e %9.2e %5.2e\\n\", "
1781  "iter_count, m_k, m_f, tr_ratio, pr_inf, du_inf, dx_norminf, tr_rad_prev);";
1782  g << "}\n";
1783 
1784  // tr_rad_prev = tr_rad;
1785  g << "tr_rad_prev = tr_rad;\n";
1786 
1787  // // Callback function NOT IMPLEMENTED IN CODEGEN
1788  // if (callback(m)) {
1789  // if (print_status_) print("WARNING(feasiblesqpmethod): Aborted by callback...\n");
1790  // m->return_status = "User_Requested_Stop";
1791  // break;
1792  // }
1793 
1794  // Checking convergence criteria
1795  // Where is the complementarity condition??
1796  // if (m->iter_count >= min_iter_ && pr_inf < tol_pr_ && du_inf < tol_du_) {
1797  // if (print_status_)
1798  // print("MESSAGE(feasiblesqpmethod): "
1799  // "Convergence achieved after %d iterations\n", m->iter_count);
1800  // m->return_status = "Solve_Succeeded";
1801  // m->success = true;
1802  // break;
1803  // }
1804 
1805 
1806  g << "if (iter_count >= " << max_iter_ << ") {\n";
1807  g << "if (" << print_status_ << ") {\n";
1808  g << g.printf("MESSAGE(feasiblesqpmethod): "
1809  "Maximum number of iterations reached.\\n") << "\n";
1810  g << "break;\n";
1811  g << "}\n";
1812  g << "}\n";
1813 
1814  // Formulate the QP
1815  // Define lower bounds
1816  // casadi_copy(d_nlp->lbz, nx_+ng_, d->lbdz);
1817  // casadi_axpy(nx_+ng_, -1., d_nlp->z, d->lbdz);
1818  // casadi_clip_min(d->lbdz, nx_, -tr_rad, d->tr_mask);
1819  g.comment("Formulate the QP");
1820  g.comment("Define the lower bounds");
1821  g << g.copy("d_nlp.lbz", nx_+ng_, "d.lbdz") << "\n";
1822  g << g.axpy(nx_+ng_, "-1.0", "d_nlp.z", "d.lbdz") << "\n";
1823  g << g.clip_min("d.lbdz", nx_, "-tr_rad", "d.tr_mask") << "\n";
1824 
1825 
1826  // Define upper bounds
1827  // casadi_copy(d_nlp->ubz, nx_+ng_, d->ubdz);
1828  // casadi_axpy(nx_+ng_, -1., d_nlp->z, d->ubdz);
1829  // casadi_clip_max(d->ubdz, nx_, tr_rad, d->tr_mask);
1830  g.comment("Define the upper bounds");
1831  g << g.copy("d_nlp.ubz", nx_+ng_, "d.ubdz") << "\n";
1832  g << g.axpy(nx_+ng_, "-1.0", "d_nlp.z", "d.ubdz") << "\n";
1833  g << g.clip_max("d.ubdz", nx_, "tr_rad", "d.tr_mask") << "\n";
1834 
1835  // // Initial guess
1836  // casadi_copy(d_nlp->lam, nx_+ng_, d->dlam);
1837  g.comment("Initial guess");
1838  g << g.copy("d_nlp.lam", nx_+ng_, "d.dlam") << "\n";
1839 
1840  // Increase counter
1841  // m->iter_count++;
1842  g.comment("Increase counter");
1843  g << "++iter_count;\n";
1844 
1845  // int ret = 0;
1846  // g << "ret = 0;\n";
1847 
1848  // Solve the QP
1849  // if (use_sqp_) {
1850  // ret = solve_QP(m, d->Bk, d->gf, d->lbdz, d->ubdz, d->Jk,
1851  // d->dx, d->dlam, 0);
1852  // } else {
1853  // ret = solve_LP(m, d->gf, d->lbdz, d->ubdz, d->Jk,
1854  // d->dx, d->dlam, 0);
1855  // }
1856  g.comment("Solve the QP");
1857  codegen_qp_solve(g, "d.Bk", "d.gf", "d.lbdz", "d.ubdz", "d.Jk", "d.dx", "d.dlam", 0);
1858 
1859  // // Eval quadratic model and check for convergence
1860  // m_k = eval_m_k(mem);
1861 
1862  g.comment("Eval quadratic model and check for convergence");
1863  codegen_eval_m_k(g);
1864 
1865  g.comment("Checking convergence criteria");
1866  g << "if (fabs(m_k) < " << optim_tol_ << ") {\n";
1867  g << "printf(\"MESSAGE(feasiblesqpmethod): Optimal Point Found? "
1868  "Quadratic model is zero. After %lld iterations.\\n\", iter_count-1);\n";
1869  g << "break;\n";
1870  g << "}\n";
1871 
1872  // uout() << "QP step: " << std::vector<double>(d->dx, d->dx+nx_) << std::endl;
1873  // Detecting indefiniteness
1874  // if (use_sqp_) {
1875  // double gain = casadi_bilin(d->Bk, Hsp_, d->dx, d->dx);
1876  // if (gain < 0) {
1877  // if (print_status_) print("WARNING(feasiblesqpmethod): Indefinite Hessian detected\n");
1878  // }
1879  // }
1880  g.comment("Detecting indefiniteness");
1881  g.comment("TBD");
1882 
1883  // Do the feasibility iterations here
1884  // ret = feasibility_iterations(mem, tr_rad);
1885  g.comment("Do the feasibility iterations here");
1886  codegen_feasibility_iterations(g, "tr_rad");
1887 
1888  g << "if (ret < 0) {\n";
1889  g << "printf(\"Rejected inner iterates\\n\");\n";
1890  g << "tr_rad = 0.5*" << g.masked_norm_inf(nx_, "d.dx", "d.tr_mask") << ";\n";
1891  g << "} else {\n";
1892  g.comment("Evaluate f");
1893  g << "m_arg[0] = d.z_feas;\n";
1894  g << "m_arg[1] = m_p;\n";
1895  g << "m_res[0] = &m_f_feas;\n";
1896  nlp_f = g(get_function("nlp_f"), "m_arg", "m_res", "m_iw", "m_w");
1897  g << "if (" + nlp_f + ") return 1;\n";
1898 
1899  codegen_eval_tr_ratio(g, "m_f", "m_f_feas", "m_k");
1900  codegen_tr_update(g, "tr_rad", "tr_ratio");
1901 
1902  g << "if (tr_rad < "<< feas_tol_ << ") {\n";
1903  g << "if (" << print_status_ << ") {\n";
1904  g << "printf(\"MESSAGE: Trust-Region radius smaller than feasibilty!!\\n\");\n";
1905  g << "}\n";
1906  g << "break;";
1907  g << "}\n";
1908 
1909  codegen_step_update(g, "tr_ratio");
1910  g.comment("Close the step acceptance loop");
1911  g << "}\n";
1912 
1913  // if (!exact_hessian_) {
1914  // // Evaluate the gradient of the Lagrangian with the old x but new lam (for BFGS)
1915  // casadi_copy(d->gf, nx_, d->gLag_old);
1916  // casadi_mv(d->Jk, Asp_, d_nlp->lam+nx_, d->gLag_old, true);
1917  // casadi_axpy(nx_, 1., d_nlp->lam, d->gLag_old);
1918  // }
1919  // }
1920  // g << "}\n";
1921  // g << "if (!" << exact_hessian_ << ") {\n";
1922  // g << g.copy("d.gf", nx_, "d.gLag_old") << "\n";
1923  // g << g.mv("d.Jk", Asp_, "d_nlp.lam+" + str(nx_), "d.gLag_old", true) << ";\n";
1924  // g << g.axpy(nx_, "1.", "d_nlp.lam", "d.gLag_old") << "\n";
1925  // g << "}\n";
1926 
1927  // return 0;
1928  // }
1929  //Close next loop
1930  // g << "}\n";
1931 
1932  // g << "return 0;\n"; // Do we need this??
1933  // Close the loop optimization problem
1934  g.comment("Close the loop optimization problem");
1935  g << "}\n";
1936 
1937  if (bound_consistency_) {
1938  g << g.bound_consistency(nx_+ng_, "d_nlp.z", "d_nlp.lam", "d_nlp.lbz", "d_nlp.ubz") << ";\n";
1939  }
1940  g.copy_check("d_nlp.z", nx_, g.res(NLPSOL_X), false, true);
1941  g.copy_check("d_nlp.z+" + str(nx_), ng_, g.res(NLPSOL_G), false, true);
1942  g.copy_check("d_nlp.lam", nx_, g.res(NLPSOL_LAM_X), false, true);
1943  g.copy_check("d_nlp.lam+"+str(nx_), ng_, g.res(NLPSOL_LAM_G), false, true);
1944  g.copy_check("d_nlp.lam_p", np_, g.res(NLPSOL_LAM_P), false, true);
1945  g.copy_check("&m_f", 1, g.res(NLPSOL_F), false, true);
1946  }
1947 
1948 
1950  const std::string& H, const std::string& g,
1951  const std::string& lbdz, const std::string& ubdz,
1952  const std::string& A, const std::string& x_opt,
1953  const std::string& dlam, int mode) const {
1954  for (casadi_int i=0;i<qpsol_.n_in();++i) cg << "m_arg[" << i << "] = 0;\n";
1955  cg << "m_arg[" << CONIC_H << "] = " << H << ";\n";
1956  cg << "m_arg[" << CONIC_G << "] = " << g << ";\n";
1957  cg << "m_arg[" << CONIC_X0 << "] = " << x_opt << ";\n";
1958  cg << "m_arg[" << CONIC_LAM_X0 << "] = " << dlam << ";\n";
1959  cg << "m_arg[" << CONIC_LAM_A0 << "] = " << dlam << "+" << nx_ << ";\n";
1960  cg << "m_arg[" << CONIC_LBX << "] = " << lbdz << ";\n";
1961  cg << "m_arg[" << CONIC_UBX << "] = " << ubdz << ";\n";
1962  cg << "m_arg[" << CONIC_A << "] = " << A << ";\n";
1963  cg << "m_arg[" << CONIC_LBA << "] = " << lbdz << "+" << nx_ << ";\n";
1964  cg << "m_arg[" << CONIC_UBA << "] = " << ubdz << "+" << nx_ << ";\n";
1965  for (casadi_int i=0;i<qpsol_.n_out();++i) cg << "m_res[" << i << "] = 0;\n";
1966  cg << "m_res[" << CONIC_X << "] = " << x_opt << ";\n";
1967  cg << "m_res[" << CONIC_LAM_X << "] = " << dlam << ";\n";
1968  cg << "m_res[" << CONIC_LAM_A << "] = " << dlam << "+" << nx_ << ";\n";
1969  std::string flag = cg(qpsol_, "m_arg", "m_res", "m_iw", "m_w");
1970  cg << "ret = " << flag << ";\n";
1971  cg << "if (ret == -1000) return -1000;\n"; // equivalent to raise Exception
1972  }
1973 
1975  const std::string& tr_rad, const std::string& tr_ratio) const {
1976  cg << "if (tr_ratio < " << tr_eta1_ << ") {\n";
1977  cg << "tr_rad = " << tr_alpha1_ <<"*" << cg.masked_norm_inf(nx_, "d.dx", "d.tr_mask") << ";\n";
1978  std::string tol = "fabs(" + cg.masked_norm_inf(nx_, "d.dx", "d.tr_mask") + " - tr_rad)";
1979  cg << "} else if (tr_ratio > " << tr_eta2_ << " && " << tol << " < " << optim_tol_ << " ) {\n";
1980  cg << "tr_rad = " << cg.fmin(str(tr_alpha2_)+"*tr_rad", str(tr_rad_max_)) << ";\n";
1981  cg << "}\n";
1982  cg.comment("else: keep trust-region as it is....");
1983  }
1984 
1986  // auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
1987  // auto d = &m->d;
1988  // if (use_sqp_) {
1989  // return 0.5*casadi_bilin(d->Bk, Hsp_, d->dx, d->dx) + casadi_dot(nx_, d->gf, d->dx);
1990  // } else {
1991  // return casadi_dot(nx_, d->gf, d->dx);
1992  // }
1993  cg << "m_k = 0.5*" << cg.bilin("d.Bk", Hsp_, "d.dx", "d.dx")
1994  << "+" << cg.dot(nx_, "d.gf", "d.dx") << ";\n";
1995 }
1996 
1998  const std::string& val_f, const std::string& val_f_corr, const std::string& val_m_k) const {
1999  // return (val_f - val_f_corr) / (-val_m_k);
2000  cg << "tr_ratio = (" + val_f + "-" + val_f_corr + ") / (-" + val_m_k + ");\n";
2001  }
2002 
2004  const std::string& tr_ratio) const {
2005  // auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
2006  // auto d_nlp = &m->d_nlp;
2007  // auto d = &m->d;
2008 
2009  // if (tr_ratio > tr_acceptance_) {
2010  // // This is not properly implemented yet: d_nlp->z_old = d_mlp->z;
2011  // casadi_copy(d->z_feas, nx_ + ng_, d_nlp->z);
2012  // d_nlp->f = d->f_feas;
2013  // casadi_copy(d->dlam_feas, nx_ + ng_, d_nlp->lam);
2014 
2015  // uout() << "ACCEPTED" << std::endl;
2016  // return 0;
2017  // } else {
2018  // uout() << "REJECTED" << std::endl;
2019  // return -1;
2020  // }
2021  cg << "if(" + tr_ratio + ">" << tr_acceptance_ << ") {\n";
2022  cg << cg.copy("d.z_feas", nx_ + ng_, "d_nlp.z") << "\n";
2023  cg << "m_f = m_f_feas;\n";
2024  cg << cg.copy("d.dlam_feas", nx_ + ng_, "d_nlp.lam") << "\n";
2025  cg << "printf(\"ACCEPTED\\n\");\n";
2026  cg << "ret = 0;\n";
2027  cg << "} else {\n";
2028  cg << "printf(\"REJECTED\\n\");\n";
2029  cg << "ret = -1;\n";
2030  cg << "}\n";
2031 }
2032 
2034  const std::string& tr_rad) const {
2035  // cg.local("ret", "casadi_int");
2036  cg.init_local("ret", "0");
2037 
2038  // casadi_copy(d->dx, nx_, d->dx_feas);
2039  cg << cg.copy("d.dx", nx_, "d.dx_feas") << "\n";
2040 
2041  // casadi_copy(d->dlam, nx_ + ng_, d->dlam_feas);
2042  cg << cg.copy("d.dlam", nx_, "d.dlam_feas") << "\n";
2043 
2044  // Why do we do this at the moment??
2045  // casadi_copy(d->dlam, nx_+ng_, d->z_tmp);
2046  // casadi_axpy(nx_+ng_, -1.0, d_nlp->lam, d->z_tmp);
2047  cg << cg.copy("d.dlam", nx_+ng_, "d.z_tmp") << "\n";
2048  cg << cg.axpy(nx_+ng_, "-1.0", "d_nlp.lam", "d.z_tmp") << "\n";
2049 
2050  // this is in solve in fslp.py
2051  // double step_inf_norm = casadi_masked_norm_inf(nx_, d->dx, d->tr_mask);
2052  // double prev_step_inf_norm = step_inf_norm;
2053  cg.local("step_inf_norm", "casadi_real");
2054  cg << "step_inf_norm = " << cg.masked_norm_inf(nx_, "d.dx", "d.tr_mask") << ";\n";
2055  cg.local("prev_step_inf_norm", "casadi_real");
2056  cg << "prev_step_inf_norm = step_inf_norm;\n";
2057  // cg.init_local("prev_step_inf_norm", "step_inf_norm");
2058 
2059  // self.x_tmp = self.x_k + p_tmp
2060  // casadi_copy(d_nlp->z, nx_+ng_, d->z_feas);
2061  // casadi_axpy(nx_, 1., d->dx_feas, d->z_feas);
2062  cg << cg.copy("d_nlp.z", nx_+ng_, "d.z_feas") << "\n";
2063  cg << cg.axpy(nx_, "1.0", "d.dx_feas", "d.z_feas") << "\n";
2064 
2065 
2066  // if (use_anderson_) {
2067  // // anderson_acc_init_memory(mem, d->dx_feas, d->z_feas);
2068  // anderson_acc_init_memory(mem, d->dx_feas, d_nlp->z);
2069  // }
2070  // cg << "if (" << use_anderson_ << ") {\n";
2071  // cg << cg.codegen_anderson_acc_init_memory(cg, "d.dx_feas", "d_nlp.z");
2072  // cg << "}\n";
2073 
2074  // Evaluate g
2075  // self.g_tmp = self.__eval_g(self.x_tmp)
2076  // m->arg[0] = d->z_feas;
2077  // m->arg[1] = d_nlp->p;
2078  // m->res[0] = d->z_feas + nx_;
2079  // if (calc_function(m, "nlp_g")) {
2080  // uout() << "What does it mean that calc_function fails here??" << std::endl;
2081  // }
2082  cg.comment("Evaluate g");
2083  cg << "m_arg[0] = d.z_feas;\n";
2084  cg << "m_arg[1] = m_p;\n";
2085  cg << "m_res[0] = d.z_feas+" + str(nx_) + ";\n";
2086  std::string nlp_g = cg(get_function("nlp_g"), "m_arg", "m_res", "m_iw", "m_w");
2087  // cg << "if (" + nlp_g + ") return 1;\n";
2088  cg << "if (" + nlp_g + ") return 100;\n";
2089 
2090 
2091  // int inner_iter = 0;
2092  cg.local("inner_iter", "casadi_int");
2093  cg.init_local("inner_iter", "0");
2094 
2095  // double prev_infeas = casadi_max_viol(nx_+ng_, d->z_feas, d_nlp->lbz, d_nlp->ubz);
2096  // double curr_infeas = prev_infeas;
2097  cg.local("prev_infeas", "casadi_real");
2098  cg << "prev_infeas =" << cg.max_viol(nx_+ng_, "d.z_feas", "d_nlp.lbz", "d_nlp.ubz") << ";\n";
2099  cg.local("curr_infeas", "casadi_real");
2100  cg << "curr_infeas = prev_infeas;\n";
2101 
2102 
2103  // Calculate asymptotic exactness of current step
2104  // casadi_copy(d->dx, nx_, d->z_tmp);
2105  // casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
2106  // casadi_axpy(nx_, 1., d_nlp->z, d->z_tmp);
2107  // double as_exac = casadi_norm_2(nx_, d->z_tmp) / casadi_norm_2(nx_, d->dx);
2108  cg << cg.copy("d.dx", nx_, "d.z_tmp") << "\n";
2109  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.z_tmp") << "\n";
2110  cg << cg.axpy(nx_, "1.0", "d_nlp.z", "d.z_tmp") << "\n";
2111  cg.local("as_exac", "casadi_real");
2112  cg << "as_exac =" << cg.norm_2(nx_, "d.z_tmp") << "/" << cg.norm_2(nx_, "d.dx") << ";\n";
2113 
2114  // double kappa_watchdog = 0.0;
2115  // double kappa = 0.0;
2116  // double acc_as_exac = 0.0;
2117  cg.local("kappa_watchdog", "casadi_real");
2118  cg.init_local("kappa_watchdog", "0.0");
2119  cg.local("kappa", "casadi_real");
2120  cg.init_local("kappa", "0.0");
2121  cg.local("acc_as_exac", "casadi_real");
2122  cg << "acc_as_exac = 0.0;\n";
2123 
2124  // double watchdog_prev_inf_norm = prev_step_inf_norm; // until here everything is correct!
2125  cg.local("watchdog_prev_inf_norm", "casadi_real");
2126  // cg.init_local("watchdog_prev_inf_norm", "prev_step_inf_norm");
2127  cg << "watchdog_prev_inf_norm = prev_step_inf_norm;\n";
2128 
2129  // for (int j=0; j<max_inner_iter_; ++j) {
2130  // if (curr_infeas < feas_tol_) {
2131  // inner_iter = j;
2132  // // kappa_acceptance = true;
2133  // if (as_exac < 0.5) {
2134  // return 0;
2135  // } else {
2136  // return -1;
2137  // }
2138  // } else if (j>0 && (curr_infeas > 1.0 || as_exac > 1.0)) {
2139  // // kappa_acceptance = false;
2140  // return -1;
2141  // }
2142  cg << "for (int j=0;j<" << max_inner_iter_ << "; ++j) {\n";
2143  cg << "if (curr_infeas < " << feas_tol_ << ") {\n";
2144  cg << "inner_iter = j;\n";
2145  cg << "if (as_exac < 0.5) {\n";
2146  cg << "ret = 0; \n";
2147  cg << "break; \n";
2148  cg << "} else {\n";
2149  cg << "ret = -1;\n";
2150  cg << "break; \n";
2151  cg << "}\n";
2152  cg << "} else if (j>0 && (curr_infeas > 1.0 || as_exac > 1.0)) {\n";
2153  cg << "ret = -1;\n";
2154  cg << "break; \n";
2155  cg << "}\n";
2156 
2157 
2158  // inner_iter = j+1;
2159  cg << "inner_iter =j+1;\n";
2160 
2161  // create corrected gradient here -----------------------------
2162  // casadi_copy(d->z_feas, nx_, d->z_tmp);
2163  // casadi_axpy(nx_, -1., d_nlp->z, d->z_tmp);
2164  // casadi_copy(d->gf, nx_, d->gf_feas);
2165  cg << cg.copy("d.z_feas", nx_, "d.z_tmp") << "\n";
2166  cg << cg.axpy(nx_, "-1.0", "d_nlp.z", "d.z_tmp") << "\n";
2167  cg << cg.copy("d.gf", nx_, "d.gf_feas") << "\n";
2168  // In case of SQP we need to multiply with
2169  // if (use_sqp_) {
2170  // casadi_mv(d->Bk, Hsp_, d->z_tmp, d->gf_feas, true);
2171  // }
2172  cg.comment("Just SQP implemented so far!");
2173  // cg << "if (" << use_sqp_ << ") {\n";
2174  cg << cg.mv("d.Bk", Hsp_, "d.z_tmp", "d.gf_feas", true) << "\n";
2175  // cg << "}\n";
2176 
2177  // create bounds of correction QP -----------------------------
2178  // upper bounds of constraints
2179  // casadi_copy(d_nlp->ubz + nx_, ng_, d->ubdz_feas + nx_);
2180  // casadi_axpy(ng_, -1., d->z_feas + nx_, d->ubdz_feas + nx_);
2181  cg << cg.copy("d_nlp.ubz+"+str(nx_), ng_, "d.ubdz_feas+"+str(nx_)) << "\n";
2182  cg << cg.axpy(ng_, "-1.0", "d.z_feas+"+str(nx_), "d.ubdz_feas+"+str(nx_)) << "\n";
2183 
2184  // lower bounds of constraints
2185  // casadi_copy(d_nlp->lbz + nx_, ng_, d->lbdz_feas + nx_);
2186  // casadi_axpy(ng_, -1., d->z_feas + nx_, d->lbdz_feas + nx_);
2187  cg << cg.copy("d_nlp.lbz+"+str(nx_), ng_, "d.lbdz_feas+"+str(nx_)) << "\n";
2188  cg << cg.axpy(ng_, "-1.0", "d.z_feas+"+str(nx_), "d.lbdz_feas+"+str(nx_)) << "\n";
2189 
2190 
2191  // casadi_copy(d_nlp->lbz, nx_, d->lbdz_feas);
2192  // casadi_clip_min(d->lbdz_feas, nx_, -tr_rad, d->tr_mask);
2193  cg << cg.copy("d_nlp.lbz", nx_, "d.lbdz_feas") << "\n";
2194  cg << cg.clip_min("d.lbdz_feas", nx_, "-tr_rad", "d.tr_mask") << "\n";
2195 
2196 
2197  // casadi_axpy(nx_, -1., d->z_feas, d->lbdz_feas);
2198  // casadi_axpy(nx_, 1., d_nlp->z, d->lbdz_feas);
2199  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.lbdz_feas") << "\n";
2200  cg << cg.axpy(nx_, "1.0", "d_nlp.z", "d.lbdz_feas") << "\n";
2201 
2202 
2203  // casadi_copy(d_nlp->lbz, nx_, d->z_tmp);
2204  // casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
2205  cg << cg.copy("d_nlp.lbz", nx_, "d.z_tmp") << "\n";
2206  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.z_tmp") << "\n";
2207 
2208  // comparison of both vectors
2209  // casadi_vector_fmax(nx_, d->z_tmp, d->lbdz_feas, d->lbdz_feas);
2210  cg << cg.vector_fmax(nx_, "d.z_tmp", "d.lbdz_feas", "d.lbdz_feas");
2211 
2212  // casadi_copy(d_nlp->ubz, nx_, d->ubdz_feas);
2213  // casadi_clip_max(d->ubdz_feas, nx_, tr_rad, d->tr_mask);
2214  cg << cg.copy("d_nlp.ubz", nx_, "d.ubdz_feas") << "\n";
2215  cg << cg.clip_max("d.ubdz_feas", nx_, "tr_rad", "d.tr_mask") << ";\n";
2216 
2217  // casadi_axpy(nx_, -1., d->z_feas, d->ubdz_feas);
2218  // casadi_axpy(nx_, 1., d_nlp->z, d->ubdz_feas);
2219  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.ubdz_feas") << "\n";
2220  cg << cg.axpy(nx_, "1.0", "d_nlp.z", "d.ubdz_feas") << "\n";
2221 
2222 
2223  // casadi_copy(d_nlp->ubz, nx_, d->z_tmp);
2224  // casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
2225  // casadi_vector_fmin(nx_, d->z_tmp, d->ubdz_feas, d->ubdz_feas);
2226  cg << cg.copy("d_nlp.ubz", nx_, "d.z_tmp") << "\n";
2227  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.z_tmp") << "\n";
2228  cg << cg.vector_fmin(nx_, "d.z_tmp", "d.ubdz_feas", "d.ubdz_feas");
2229 
2230  // if (use_sqp_) {
2231  // int ret = solve_QP(m, d->Bk, d->gf_feas, d->lbdz_feas, d->ubdz_feas,
2232  // d->Jk, d->dx_feas, d->dlam_feas, 0);
2233  // } else {
2234  // int ret = solve_LP(m, d->gf_feas, d->lbdz_feas, d->ubdz_feas,
2235  // d->Jk, d->dx_feas, d->dlam_feas, 0);
2236  // }
2237  cg.comment("Just SQP implemented. Solve the feasible QP");
2238  codegen_qp_solve(cg, "d.Bk", "d.gf_feas", "d.lbdz_feas", "d.ubdz_feas",
2239  "d.Jk", "d.dx_feas", "d.dlam_feas", 0);
2240 
2241 
2242  // step_inf_norm = casadi_masked_norm_inf(nx_, d->dx_feas, d->tr_mask);
2243  cg << "step_inf_norm = " << cg.masked_norm_inf(nx_, "d.dx_feas", "d.tr_mask") << ";\n";
2244 
2245  // if (use_anderson_) {
2246  // anderson_acc_step_update(mem, j);
2247  // } else {
2248  // casadi_axpy(nx_, 1., d->dx_feas, d->z_feas);
2249  // }
2250  cg.comment("No Anderson Acceleration implemented yet.");
2251  cg << cg.axpy(nx_, "1.0", "d.dx_feas", "d.z_feas") << "\n";
2252 
2253  // Evaluate g
2254  // m->arg[0] = d->z_feas;
2255  // m->arg[1] = d_nlp->p;
2256  // m->res[0] = d->z_feas + nx_;
2257  // if (calc_function(m, "nlp_g")) {
2258  // uout() << "What does it mean that calc_function fails here??" << std::endl;
2259  // }
2260  cg.comment("Evaluate g");
2261  cg << "m_arg[0] = d.z_feas;\n";
2262  cg << "m_arg[1] = m_p;\n";
2263  cg << "m_res[0] = d.z_feas+" + str(nx_) + ";\n";
2264  nlp_g = cg(get_function("nlp_g"), "m_arg", "m_res", "m_iw", "m_w");
2265  // cg << "if (" + nlp_g + ") return 1;\n";
2266  cg << "if (" + nlp_g + ") return 100;\n";
2267 
2268  // prev_infeas = casadi_max_viol(nx_+ng_, d->z_feas, d_nlp->lbz, d_nlp->ubz);
2269  // curr_infeas = prev_infeas;
2270  // kappa = step_inf_norm/prev_step_inf_norm;
2271  cg << "prev_infeas =" << cg.max_viol(nx_+ng_, "d.z_feas", "d_nlp.lbz", "d_nlp.ubz") << ";\n";
2272  cg << "curr_infeas = prev_infeas;\n";
2273  cg << "kappa = step_inf_norm/prev_step_inf_norm;";
2274 
2275  // casadi_copy(d->dx, nx_, d->z_tmp);
2276  // casadi_axpy(nx_, -1., d->z_feas, d->z_tmp);
2277  // casadi_axpy(nx_, 1., d_nlp->z, d->z_tmp);
2278  // as_exac = casadi_norm_2(nx_, d->z_tmp) / casadi_norm_2(nx_, d->dx);
2279  cg << cg.copy("d.dx", nx_, "d.z_tmp") << "\n";
2280  cg << cg.axpy(nx_, "-1.0", "d.z_feas", "d.z_tmp") << "\n";
2281  cg << cg.axpy(nx_, "1.0", "d_nlp.z", "d.z_tmp") << "\n";
2282  cg.local("as_exac", "casadi_real");
2283  cg << "as_exac =" << cg.norm_2(nx_, "d.z_tmp") << "/" << cg.norm_2(nx_, "d.dx") << ";\n";
2284 
2285  cg << "printf(\"Kappa: %9.10f, Infeasibility: %9.10f, "
2286  "AsymptoticExctness: %9.10f\\n\", kappa, curr_infeas, as_exac);\n";
2287 
2288  // acc_as_exac += as_exac;
2289  cg << "acc_as_exac += as_exac;\n";
2290 
2291  // if (inner_iter % watchdog_ == 0) {
2292  // kappa_watchdog = step_inf_norm / watchdog_prev_inf_norm;
2293  // watchdog_prev_inf_norm = step_inf_norm;
2294  // print("Kappa watchdog: %9.10f\n", kappa_watchdog);
2295  // if (curr_infeas < feas_tol_ && as_exac < 0.5) {
2296  // // kappa_acceptance = true;
2297  // return 0;
2298  // }
2299 
2300  // if (kappa_watchdog > contraction_acceptance_value_ || acc_as_exac/watchdog_ > 0.5) {
2301  // // kappa_acceptance = false;
2302  // return -1;
2303  // }
2304  // // accumulated_as_ex = 0
2305  // acc_as_exac = 0.0;
2306  // }
2307  cg << "if (inner_iter % " << watchdog_ << "== 0) {\n";
2308  cg << "kappa_watchdog = step_inf_norm / watchdog_prev_inf_norm;\n";
2309  cg << "watchdog_prev_inf_norm = step_inf_norm;\n";
2310  cg << "printf(\"Kappa watchdog: %9.10f\\n\", kappa_watchdog);\n";
2311  cg << "if (curr_infeas < "<< feas_tol_ << "&& as_exac < 0.5) {\n";
2312  cg << "ret = 0;\n";
2313  cg << "break; \n";
2314  cg << "}\n";
2315  cg << "if (kappa_watchdog > " << contraction_acceptance_value_ << " || "
2316  << "acc_as_exac/" << watchdog_ << "> 0.5) {\n";
2317  cg << "ret = -1;\n";
2318  cg << "break;\n";
2319  cg << "}\n";
2320 
2321  cg << "acc_as_exac = 0.0;\n";
2322  cg << "}\n"; //Added
2323 
2324  // prev_step_inf_norm = step_inf_norm;
2325  cg << "prev_step_inf_norm = step_inf_norm;\n";
2326  // }
2327  cg << "}\n";
2328  //maximum iterations reached
2329  // kappa_acceptance = false;
2330 // return -1;
2331 // }
2332  cg << "if (inner_iter >=" << max_inner_iter_ << ") {\n";
2333  cg << "ret = -1;\n";
2334  cg << "}\n";
2335 
2336  }
2337 
2339  Dict stats = Nlpsol::get_stats(mem);
2340  auto m = static_cast<FeasiblesqpmethodMemory*>(mem);
2341  stats["return_status"] = m->return_status;
2342  stats["iter_count"] = m->iter_count;
2343  return stats;
2344  }
2345 
2347  int version = s.version("Feasiblesqpmethod", 1, 3);
2348  s.unpack("Feasiblesqpmethod::qpsol", qpsol_);
2349  if (version>=3) {
2350  s.unpack("Feasiblesqpmethod::qpsol_ela", qpsol_ela_);
2351  }
2352  s.unpack("Feasiblesqpmethod::exact_hessian", exact_hessian_);
2353  s.unpack("Feasiblesqpmethod::max_iter", max_iter_);
2354  s.unpack("Feasiblesqpmethod::min_iter", min_iter_);
2355  s.unpack("Feasiblesqpmethod::lbfgs_memory", lbfgs_memory_);
2356  s.unpack("Feasiblesqpmethod::tol_pr_", tol_pr_);
2357  s.unpack("Feasiblesqpmethod::tol_du_", tol_du_);
2358  s.unpack("Feasiblesqpmethod::print_header", print_header_);
2359  s.unpack("Feasiblesqpmethod::print_iteration", print_iteration_);
2360  s.unpack("Feasiblesqpmethod::print_status", print_status_);
2361 
2362  // if (version>=3) {
2363  // s.unpack("Feasiblesqpmethod::elastic_mode", elastic_mode_);
2364  // s.unpack("Feasiblesqpmethod::gamma_0", gamma_0_);
2365  // s.unpack("Feasiblesqpmethod::gamma_max", gamma_max_);
2366  // s.unpack("Feasiblesqpmethod::gamma_1_min", gamma_1_min_);
2367  // s.unpack("Feasiblesqpmethod::init_feasible", init_feasible_);
2368  // s.unpack("Feasiblesqpmethod::so_corr", so_corr_);
2369  // } else {
2370  // // elastic_mode_ = false;
2371  // // gamma_0_ = 0;
2372  // // gamma_max_ = 0;
2373  // // gamma_1_min_ = 0;
2374  // init_feasible_ = false;
2375  // // so_corr_ = false;
2376  // }
2377 
2378  s.unpack("Feasiblesqpmethod::Hsp", Hsp_);
2379  if (version==1) {
2380  Sparsity Hrsp;
2381  s.unpack("Feasiblesqpmethod::Hrsp", Hrsp);
2382  }
2383  s.unpack("Feasiblesqpmethod::Asp", Asp_);
2384  if (version==1) {
2385  double convexify_margin;
2386  s.unpack("Feasiblesqpmethod::convexify_margin", convexify_margin);
2387  char convexify_strategy;
2388  s.unpack("Feasiblesqpmethod::convexify_strategy", convexify_strategy);
2389  casadi_assert(convexify_strategy==0, "deserializtion failed.");
2390  bool Hsp_project;
2391  s.unpack("Feasiblesqpmethod::Hsp_project", Hsp_project);
2392  bool scc_transform;
2393  s.unpack("Feasiblesqpmethod::scc_transform", scc_transform);
2394  std::vector<casadi_int> scc_offset;
2395  s.unpack("Feasiblesqpmethod::scc_offset", scc_offset);
2396  std::vector<casadi_int> scc_mapping;
2397  s.unpack("Feasiblesqpmethod::scc_mapping", scc_mapping);
2398  casadi_int max_iter_eig;
2399  s.unpack("Feasiblesqpmethod::max_iter_eig", max_iter_eig);
2400  casadi_int block_size;
2401  s.unpack("Feasiblesqpmethod::block_size", block_size);
2402  Sparsity scc_sp;
2403  s.unpack("Feasiblesqpmethod::scc_sp", scc_sp);
2404  convexify_ = false;
2405  }
2406  if (version>=2) {
2407  s.unpack("Feasiblesqpmethod::convexify", convexify_);
2408  if (convexify_) Convexify::deserialize(s, "Feasiblesqpmethod::", convexify_data_);
2409  }
2410  set_feasiblesqpmethod_prob();
2411  }
2412 
2415  s.version("Feasiblesqpmethod", 3);
2416  s.pack("Feasiblesqpmethod::qpsol", qpsol_);
2417  // s.pack("Feasiblesqpmethod::qpsol_ela", qpsol_ela_);
2418  s.pack("Feasiblesqpmethod::exact_hessian", exact_hessian_);
2419  s.pack("Feasiblesqpmethod::max_iter", max_iter_);
2420  s.pack("Feasiblesqpmethod::min_iter", min_iter_);
2421  s.pack("Feasiblesqpmethod::lbfgs_memory", lbfgs_memory_);
2422  s.pack("Feasiblesqpmethod::tol_pr_", tol_pr_);
2423  s.pack("Feasiblesqpmethod::tol_du_", tol_du_);
2424  s.pack("Feasiblesqpmethod::print_header", print_header_);
2425  s.pack("Feasiblesqpmethod::print_iteration", print_iteration_);
2426  s.pack("Feasiblesqpmethod::print_status", print_status_);
2427 
2428  s.pack("Feasiblesqpmethod::init_feasible", init_feasible_);
2429  s.pack("Feasiblesqpmethod::Hsp", Hsp_);
2430  s.pack("Feasiblesqpmethod::Asp", Asp_);
2431  s.pack("Feasiblesqpmethod::convexify", convexify_);
2432  if (convexify_) Convexify::serialize(s, "Feasiblesqpmethod::", convexify_data_);
2433  }
2434 } // namespace casadi
Helper class for C code generation.
std::string axpy(casadi_int n, const std::string &a, const std::string &x, const std::string &y)
Codegen axpy: y += a*x.
std::string clip_min(const std::string &x, casadi_int n, const std::string &min, const std::string &mask)
Codegen clip_min: Clips the smaller entries in a vector than min to the min.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string arg(casadi_int i) const
Refer to argument.
std::string norm_2(casadi_int n, const std::string &x)
norm_2
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
void comment(const std::string &s)
Write a comment line (ignored if not verbose)
std::string masked_norm_inf(casadi_int n, const std::string &x, const std::string &mask)
codegen masked_norm_inf: The mask tells what entry is used in the inf-norm.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
std::string fmin(const std::string &x, const std::string &y)
fmin
std::string printf(const std::string &str, const std::vector< std::string > &arg=std::vector< std::string >())
Printf.
std::string bilin(const std::string &A, const Sparsity &sp_A, const std::string &x, const std::string &y)
Codegen bilinear form.
std::string bound_consistency(casadi_int n, const std::string &x, const std::string &lam, const std::string &lbx, const std::string &ubx)
bound_consistency
std::string vector_fmax(casadi_int n, const std::string &x, const std::string &y, const std::string &z)
Codegen vector_fmax: Takes vectorwise max of a vector and writes the result to second vector.
std::string mv(const std::string &x, const Sparsity &sp_x, const std::string &y, const std::string &z, bool tr)
Codegen sparse matrix-vector multiplication.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string res(casadi_int i) const
Refer to resuly.
std::string norm_inf(casadi_int n, const std::string &x)
norm_inf
std::string vector_fmin(casadi_int n, const std::string &x, const std::string &y, const std::string &z)
Codegen vector_fmin: Takes vectorwise min of a vector and writes the result to second vector.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string dot(casadi_int n, const std::string &x, const std::string &y)
Codegen inner product.
std::string clip_max(const std::string &x, casadi_int n, const std::string &min, const std::string &mask)
Codegen clip_max: Clips the larger entries in a vector than max to the max.
void copy_check(const std::string &arg, std::size_t n, const std::string &res, bool check_lhs=true, bool check_rhs=true)
std::string max_viol(casadi_int n, const std::string &x, const std::string &lb, const std::string &ub)
max_viol
std::string sparsity(const Sparsity &sp, bool canonical=true)
void copy_default(const std::string &arg, std::size_t n, const std::string &res, const std::string &def, bool check_rhs=true)
std::string clear(const std::string &res, std::size_t n)
Create a fill operation.
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:112
static Sparsity setup(ConvexifyData &d, const Sparsity &H, const Dict &opts=Dict(), bool inplace=true)
Definition: convexify.cpp:167
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: convexify.hpp:105
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void codegen_eval_tr_ratio(CodeGenerator &cg, const std::string &val_f, const std::string &val_f_corr, const std::string &val_m_k) const
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
Feasiblesqpmethod(const std::string &name, const Function &nlp)
static const std::string meta_doc
A documentation string.
void codegen_eval_m_k(CodeGenerator &cg) const
int step_update(void *mem, double tr_ratio) const
static const Options options_
Options.
casadi_int lbfgs_memory_
Memory size of L-BFGS method.
void codegen_step_update(CodeGenerator &cg, const std::string &tr_ratio) const
int init_mem(void *mem) const override
Initalize memory block.
void print_iteration() const
Print iteration header.
bool init_feasible_
Initialize feasible qp's.
ConvexifyData convexify_data_
Data for convexification.
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
void codegen_feasibility_iterations(CodeGenerator &cg, const std::string &tr_rad) const
bool use_anderson_
Use Anderson Acceleration.
Dict get_stats(void *mem) const override
Get all statistics.
void init(const Dict &opts) override
Initialize.
int feasibility_iterations(void *mem, double tr_rad) const
int solve(void *mem) const override
virtual int solve_QP(FeasiblesqpmethodMemory *m, const double *H, const double *g, const double *lbdz, const double *ubdz, const double *A, double *x_opt, double *dlam, int mode) const
casadi_int max_iter_
Maximum, minimum number of SQP iterations.
virtual int solve_LP(FeasiblesqpmethodMemory *m, const double *g, const double *lbdz, const double *ubdz, const double *A, double *x_opt, double *dlam, int mode) const
casadi_feasiblesqpmethod_prob< double > p_
void tr_update(void *mem, double &tr_rad, double tr_ratio) const
std::vector< double > tr_scale_vector_
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
double eval_tr_ratio(double val_f, double val_f_corr, double val_m_k) const
void anderson_acc_step_update(void *mem, casadi_int iter_index) const
Function qpsol_ela_
QP solver for elastic mode subproblems.
Function qpsol_
QP solver for the subproblems.
void codegen_qp_solve(CodeGenerator &cg, const std::string &H, const std::string &g, const std::string &lbdz, const std::string &ubdz, const std::string &A, const std::string &x_opt, const std::string &dlam, int mode) const
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
bool exact_hessian_
Exact Hessian?
double eval_m_k(void *mem) const
void anderson_acc_init_memory(void *mem, double *step, double *iterate) const
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
void anderson_acc_update_memory(void *mem, double *step, double *iterate) const
double tol_pr_
Tolerance of primal and dual infeasibility.
void codegen_tr_update(CodeGenerator &cg, const std::string &tr_rad, const std::string &tr_ratio) const
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
size_t sz_w() const
Get required length of w field.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
size_t sz_iw() const
Get required length of iw field.
Function object.
Definition: function.hpp:60
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
NLP solver storage class.
Definition: nlpsol_impl.hpp:59
Dict get_stats(void *mem) const override
Get all statistics.
Definition: nlpsol.cpp:1251
static const Options options_
Options.
void codegen_body_enter(CodeGenerator &g) const override
Generate code for the function body.
Definition: nlpsol.cpp:1268
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
Definition: nlpsol.cpp:1348
void init(const Dict &opts) override
Initialize.
Definition: nlpsol.cpp:499
casadi_int ng_
Number of constraints.
Definition: nlpsol_impl.hpp:69
int init_mem(void *mem) const override
Initalize memory block.
Definition: nlpsol.cpp:692
casadi_nlpsol_prob< double > p_nlp_
Definition: nlpsol_impl.hpp:63
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: nlpsol.cpp:1409
casadi_int np_
Number of parameters.
Definition: nlpsol_impl.hpp:72
int callback(NlpsolMemory *m) const
Definition: nlpsol.cpp:1210
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:884
bool bound_consistency_
Options.
Definition: nlpsol_impl.hpp:98
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
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
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.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
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.
General sparsity class.
Definition: sparsity.hpp:106
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Definition: sparsity.cpp:1028
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
bool is_symmetric() const
Is symmetric?
Definition: sparsity.cpp:317
Function conic(const std::string &name, const std::string &solver, const SpDict &qp, const Dict &opts)
Definition: conic.cpp:44
The casadi namespace.
Definition: archiver.cpp:28
@ NLPSOL_P
Value of fixed parameters (np x 1)
Definition: nlpsol.hpp:198
@ NLPSOL_UBX
Decision variables upper bound (nx x 1), default +inf.
Definition: nlpsol.hpp:202
@ NLPSOL_X0
Decision variables, initial guess (nx x 1)
Definition: nlpsol.hpp:196
@ NLPSOL_LAM_G0
Lagrange multipliers for bounds on G, initial guess (ng x 1)
Definition: nlpsol.hpp:210
@ NLPSOL_LAM_X0
Lagrange multipliers for bounds on X, initial guess (nx x 1)
Definition: nlpsol.hpp:208
@ NLPSOL_NUM_IN
Definition: nlpsol.hpp:211
@ NLPSOL_LBG
Constraints lower bound (ng x 1), default -inf.
Definition: nlpsol.hpp:204
@ NLPSOL_LBX
Decision variables lower bound (nx x 1), default -inf.
Definition: nlpsol.hpp:200
T1 casadi_max_viol(casadi_int n, const T1 *x, const T1 *lb, const T1 *ub)
Largest bound violation.
@ 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_NUM_OUT
Definition: nlpsol.hpp:228
@ 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
@ CONIC_UBA
dense, (nc x 1)
Definition: conic.hpp:181
@ CONIC_X0
dense, (n x 1)
Definition: conic.hpp:187
@ CONIC_A
The matrix A: sparse, (nc x n) - product with x must be dense.
Definition: conic.hpp:177
@ CONIC_G
The vector g: dense, (n x 1)
Definition: conic.hpp:175
@ CONIC_LBA
dense, (nc x 1)
Definition: conic.hpp:179
@ CONIC_UBX
dense, (n x 1)
Definition: conic.hpp:185
@ CONIC_H
Definition: conic.hpp:173
@ CONIC_LAM_A0
dense
Definition: conic.hpp:191
@ CONIC_LBX
dense, (n x 1)
Definition: conic.hpp:183
@ CONIC_LAM_X0
dense
Definition: conic.hpp:189
T1 casadi_bilin(const T1 *A, const casadi_int *sp_A, const T1 *x, const T1 *y)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
void casadi_fill(T1 *x, casadi_int n, T1 alpha)
FILL: x <- alpha.
@ OT_DOUBLEVECTOR
T1 casadi_norm_2(casadi_int n, const T1 *x)
NORM_2: ||x||_2 -> return.
int CASADI_NLPSOL_FEASIBLESQPMETHOD_EXPORT casadi_register_nlpsol_feasiblesqpmethod(Nlpsol::Plugin *plugin)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T1 casadi_dot(casadi_int n, const T1 *x, const T1 *y)
Inner product.
void CASADI_NLPSOL_FEASIBLESQPMETHOD_EXPORT casadi_load_nlpsol_feasiblesqpmethod()
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
void casadi_axpy(casadi_int n, T1 alpha, const T1 *x, T1 *y)
AXPY: y <- a*x + y.
T1 casadi_norm_inf(casadi_int n, const T1 *x)
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
void casadi_mv(const T1 *x, const casadi_int *sp_x, const T1 *y, T1 *z, casadi_int tr)
Sparse matrix-vector multiplication: z <- z + x*y.
std::ostream & uout()
@ SOLVER_RET_NAN
@ SOLVER_RET_LIMITED
@ CONIC_X
The primal solution.
Definition: conic.hpp:201
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
Definition: conic.hpp:205
@ CONIC_COST
The optimal cost.
Definition: conic.hpp:203
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
Definition: conic.hpp:207
casadi_convexify_config< double > config
Definition: mx.hpp:61
casadi_int sz_iw
Definition: mx.hpp:62
casadi_int sz_w
Definition: mx.hpp:63
const char * return_status
Last return status.
casadi_feasiblesqpmethod_data< double > d
casadi_nlpsol_data< double > d_nlp
Definition: nlpsol_impl.hpp:42
Options metadata for a class.
Definition: options.hpp:40
std::map< std::string, FStats > fstats
void add_stat(const std::string &s)
const casadi_nlpsol_prob< T1 > * nlp