rootfinder.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "rootfinder_impl.hpp"
27 #include "mx_node.hpp"
28 #include <iterator>
29 #include "linsol.hpp"
30 
31 #include "global_options.hpp"
32 
33 namespace casadi {
34 
35  std::vector<std::string> rootfinder_in() {
36  std::vector<std::string> ret(rootfinder_n_in());
37  for (size_t i=0; i<ret.size(); ++i) ret[i]=rootfinder_in(i);
38  return ret;
39  }
40 
41  std::vector<std::string> rootfinder_out() {
42  std::vector<std::string> ret(rootfinder_n_out());
43  for (size_t i=0; i<ret.size(); ++i) ret[i]=rootfinder_out(i);
44  return ret;
45  }
46 
47  std::string rootfinder_in(casadi_int ind) {
48  switch (static_cast<RootfinderInput>(ind)) {
49  case ROOTFINDER_X0: return "x0";
50  case ROOTFINDER_P: return "p";
51  case ROOTFINDER_NUM_IN: break;
52  }
53  return std::string();
54  }
55 
56  std::string rootfinder_out(casadi_int ind) {
57  switch (static_cast<RootfinderOutput>(ind)) {
58  case ROOTFINDER_X: return "x";
59  case ROOTFINDER_NUM_OUT: break;
60  }
61  return std::string();
62  }
63 
64  casadi_int rootfinder_n_in() {
65  return ROOTFINDER_NUM_IN;
66  }
67 
68  casadi_int rootfinder_n_out() {
69  return ROOTFINDER_NUM_OUT;
70  }
71 
72  std::string Rootfinder::get_name_in(casadi_int i) {
73  if (i==iin_) return oracle_.name_in(i) + "0";
74  return oracle_.name_in(i);
75  }
76 
77  std::string Rootfinder::get_name_out(casadi_int i) {
78  if (i==iout_) return oracle_.name_in(iin_);
79  return oracle_.name_out(i);
80  }
81 
83  if (i==iout_) return oracle_.sparsity_in(iin_);
84  return oracle_.sparsity_out(i);
85  }
86 
87  std::vector<std::string> rootfinder_options(const std::string& name) {
88  return Rootfinder::plugin_options(name).all();
89  }
90 
91  std::string rootfinder_option_type(const std::string& name, const std::string& op) {
92  return Rootfinder::plugin_options(name).type(op);
93  }
94 
95  std::string rootfinder_option_info(const std::string& name, const std::string& op) {
96  return Rootfinder::plugin_options(name).info(op);
97  }
98 
99  bool has_rootfinder(const std::string& name) {
100  return Rootfinder::has_plugin(name);
101  }
102 
103  void load_rootfinder(const std::string& name) {
105  }
106 
107  std::string doc_rootfinder(const std::string& name) {
108  return Rootfinder::getPlugin(name).doc;
109  }
110 
111  Function rootfinder(const std::string& name, const std::string& solver,
112  const SXDict& rfp, const Dict& opts) {
113  return rootfinder(name, solver, Rootfinder::create_oracle(rfp, opts), opts);
114  }
115 
116  Function rootfinder(const std::string& name, const std::string& solver,
117  const MXDict& rfp, const Dict& opts) {
118  return rootfinder(name, solver, Rootfinder::create_oracle(rfp, opts), opts);
119  }
120 
121  template<typename XType>
122  Function Rootfinder::create_oracle(const std::map<std::string, XType>& d,
123  const Dict& opts) {
124  std::vector<XType> rfp_in(RFP_NUM_IN), rfp_out(RFP_NUM_OUT);
125  for (auto&& i : d) {
126  if (i.first=="x") {
127  rfp_in[RFP_X]=i.second;
128  } else if (i.first=="p") {
129  rfp_in[RFP_P]=i.second;
130  } else if (i.first=="g") {
131  rfp_out[RFP_G]=i.second;
132  } else {
133  casadi_error("No such field: " + i.first);
134  }
135  }
136 
137  // Options for the oracle
138  Dict oracle_options;
139  Dict::const_iterator it = opts.find("oracle_options");
140  if (it!=opts.end()) {
141  // "oracle_options" has been set
142  oracle_options = it->second;
143  } else {
144  it=opts.find("verbose");
145  if (it != opts.end()) {
146  // "oracle_options" has not been set, but "verbose" has
147  oracle_options["verbose"] = it->second;
148  }
149  }
150 
151  // Create oracle
152  return Function("rfp", rfp_in, rfp_out, {"x", "p"}, {"g"}, oracle_options);
153  }
154 
155  Function rootfinder(const std::string& name, const std::string& solver,
156  const Function& f, const Dict& opts) {
157  // Make sure that residual function is sound
158  if (f.has_free()) {
159  casadi_error("Cannot create '" + name + "' since " + str(f.get_free()) + " are free.");
160  }
161  return Function::create(Rootfinder::instantiate(name, solver, f), opts);
162  }
163 
164  Rootfinder::Rootfinder(const std::string& name, const Function& oracle)
165  : OracleFunction(name, oracle) {
166 
167  // Default options
168  iin_ = 0;
169  iout_ = 0;
170  error_on_fail_ = true;
171  }
172 
174  }
175 
178  {{"linear_solver",
179  {OT_STRING,
180  "User-defined linear solver class. Needed for sensitivities."}},
181  {"linear_solver_options",
182  {OT_DICT,
183  "Options to be passed to the linear solver."}},
184  {"constraints",
185  {OT_INTVECTOR,
186  "Constrain the unknowns. 0 (default): no constraint on ui, "
187  "1: ui >= 0.0, -1: ui <= 0.0, 2: ui > 0.0, -2: ui < 0.0."}},
188  {"implicit_input",
189  {OT_INT,
190  "Index of the input that corresponds to the actual root-finding"}},
191  {"implicit_output",
192  {OT_INT,
193  "Index of the output that corresponds to the actual root-finding"}},
194  {"jacobian_function",
195  {OT_FUNCTION,
196  "Function object for calculating the Jacobian (autogenerated by default)"}},
197  }
198  };
199 
200  void Rootfinder::init(const Dict& opts) {
201 
202  // Default (temporary) options
203  Dict linear_solver_options;
204  std::string linear_solver = "qr";
205  Function jac; // Jacobian of f with respect to z
206 
207  // Read options
208  for (auto&& op : opts) {
209  if (op.first=="implicit_input") {
210  iin_ = op.second;
211  } else if (op.first=="implicit_output") {
212  iout_ = op.second;
213  } else if (op.first=="jacobian_function") {
214  jac = op.second;
215  } else if (op.first=="linear_solver_options") {
216  linear_solver_options = op.second;
217  } else if (op.first=="linear_solver") {
218  linear_solver = op.second.to_string();
219  } else if (op.first=="constraints") {
220  u_c_ = op.second;
221  }
222  }
223 
224  // Get the number of equations and check consistency
225  casadi_assert(iin_>=0 && iin_<oracle_.n_in() && oracle_.n_in()>0,
226  "Implicit input not in range");
227  casadi_assert(iout_>=0 && iout_<oracle_.n_out() && oracle_.n_out()>0,
228  "Implicit output not in range");
229  casadi_assert(oracle_.sparsity_out(iout_).is_dense()
231  "Residual must be a dense vector");
232  casadi_assert(oracle_.sparsity_in(iin_).is_dense()
234  "Unknown must be a dense vector");
235  n_ = oracle_.nnz_out(iout_);
236  casadi_assert(n_ == oracle_.nnz_in(iin_),
237  "Dimension mismatch. Input size is " + str(oracle_.nnz_in(iin_)) + ", "
238  "while output size is " + str(oracle_.nnz_out(iout_)));
239 
240  // Call the base class initializer
241  OracleFunction::init(opts);
242 
243  // Generate Jacobian if not provided
244  if (jac.is_null()) {
245  std::vector<std::string> s_in = oracle_.name_in();
246  std::vector<std::string> s_out = oracle_.name_out();
247  s_out.insert(s_out.begin(), "jac:" + oracle_.name_out(iout_) + ":" + oracle_.name_in(iin_));
248  jac = oracle_.factory(oracle_.name() + "_jac", s_in, s_out);
249  }
250  set_function(jac, "jac_g_x");
251  sp_jac_ = jac.sparsity_out(0);
252  // Check for structural singularity in the Jacobian
253  casadi_assert(!sp_jac_.is_singular(),
254  "Rootfinder::init: singularity - the jacobian is structurally rank-deficient. "
255  "sprank(J)=" + str(sprank(sp_jac_)) + " (instead of " + str(sp_jac_.size1()) + ")");
256 
257  // Get the linear solver creator function
258  linsol_ = Linsol("linsol", linear_solver, sp_jac_, linear_solver_options);
259 
260  // Constraints
261  casadi_assert(u_c_.size()==n_ || u_c_.empty(),
262  "Constraint vector if supplied, must be of length n, but got "
263  + str(u_c_.size()) + " and n = " + str(n_));
264 
265  // Allocate sufficiently large work vectors
266  alloc(oracle_);
267  size_t sz_w = oracle_.sz_w();
268  if (!jac.is_null()) {
269  sz_w = std::max(sz_w, jac.sz_w());
270  }
271  alloc_w(sz_w + 2*static_cast<size_t>(n_));
272  }
273 
274  int Rootfinder::init_mem(void* mem) const {
275  if (OracleFunction::init_mem(mem)) return 1;
276 
277  auto *m = static_cast<RootfinderMemory*>(mem);
278 
279  // Problem has not been solved at this point
280  m->success = false;
281  m->unified_return_status = SOLVER_RET_UNKNOWN;
282 
283  return 0;
284  }
285 
286  int Rootfinder::eval(const double** arg, double** res,
287  casadi_int* iw, double* w, void* mem) const {
288  // Reset the solver, prepare for solution
289  setup(mem, arg, res, iw, w);
290 
291  // Solve the NLP
292  int ret = solve(mem);
293  auto *m = static_cast<RootfinderMemory*>(mem);
294  if (error_on_fail_ && !m->success)
295  casadi_error("rootfinder process failed. "
296  "Set 'error_on_fail' option to false to ignore this error.");
297 
298  return ret;
299  }
300 
301  void Rootfinder::set_work(void* mem, const double**& arg, double**& res,
302  casadi_int*& iw, double*& w) const {
303  auto *m = static_cast<RootfinderMemory*>(mem);
304 
305  // Problem has not been solved at this point
306  m->success = false;
307  m->unified_return_status = SOLVER_RET_UNKNOWN;
308 
309  // Get input pointers
310  m->iarg = arg;
311  arg += n_in_;
312 
313  // Get output pointers
314  m->ires = res;
315  res += n_out_;
316  }
317 
319  ::get_forward(casadi_int nfwd, const std::string& name,
320  const std::vector<std::string>& inames,
321  const std::vector<std::string>& onames,
322  const Dict& opts) const {
323  // Symbolic expression for the input
324  std::vector<MX> arg = mx_in(), res = mx_out();
325  std::vector<std::vector<MX>> fseed = fwd_seed<MX>(nfwd), fsens;
326  arg[iin_] = MX::sym(arg[iin_].name(), Sparsity(arg[iin_].size()));
327  for (auto&& e : fseed) e[iin_] = MX::sym(e[iin_].name(), e[iin_].size());
328  ad_forward(arg, res, fseed, fsens, false, false);
329 
330  // Construct return function
331  arg.insert(arg.end(), res.begin(), res.end());
332  std::vector<MX> v(nfwd);
333  for (casadi_int i=0; i<n_in_; ++i) {
334  for (casadi_int d=0; d<nfwd; ++d) v[d] = fseed[d][i];
335  arg.push_back(horzcat(v));
336  }
337  res.clear();
338  for (casadi_int i=0; i<n_out_; ++i) {
339  for (casadi_int d=0; d<nfwd; ++d) v[d] = fsens[d][i];
340  res.push_back(ensure_stacked(horzcat(v), sparsity_out(i), nfwd));
341  }
342 
343  Dict options = opts;
344  options["allow_duplicate_io_names"] = true;
345 
346  return Function(name, arg, res, inames, onames, options);
347  }
348 
350  ::get_reverse(casadi_int nadj, const std::string& name,
351  const std::vector<std::string>& inames,
352  const std::vector<std::string>& onames,
353  const Dict& opts) const {
354  // Symbolic expression for the input
355  std::vector<MX> arg = mx_in();
356  arg[iin_] = MX::sym(arg[iin_].name() + "_guess",
357  Sparsity(arg[iin_].size()));
358  std::vector<MX> res = mx_out();
359  std::vector<std::vector<MX> > aseed = symbolicAdjSeed(nadj, res), asens;
360  ad_reverse(arg, res, aseed, asens, false, false);
361 
362  // Construct return function
363  arg.insert(arg.end(), res.begin(), res.end());
364  std::vector<MX> v(nadj);
365  for (casadi_int i=0; i<n_out_; ++i) {
366  for (casadi_int d=0; d<nadj; ++d) v[d] = aseed[d][i];
367  arg.push_back(horzcat(v));
368  }
369  res.clear();
370  for (casadi_int i=0; i<n_in_; ++i) {
371  for (casadi_int d=0; d<nadj; ++d) v[d] = asens[d][i];
372  res.push_back(ensure_stacked(horzcat(v), sparsity_in(i), nadj));
373  }
374 
375  Dict options = opts;
376  options["allow_duplicate_io_names"] = true;
377  return Function(name, arg, res, inames, onames, options);
378  }
379 
381  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, void* mem) const {
382  bvec_t* tmp1 = w; w += n_;
383  bvec_t* tmp2 = w; w += n_;
384 
385  // Propagate dependencies through the function
386  const bvec_t** arg1 = arg+n_in_;
387  std::copy(arg, arg+n_in_, arg1);
388  arg1[iin_] = nullptr;
389  bvec_t** res1 = res+n_out_;
390  std::fill_n(res1, n_out_, static_cast<bvec_t*>(nullptr));
391  res1[iout_] = tmp1;
392  oracle_(arg1, res1, iw, w, 0);
393 
394  // "Solve" in order to propagate to z
395  std::fill_n(tmp2, n_, 0);
396  sp_jac_.spsolve(tmp2, tmp1, false);
397  if (res[iout_]) std::copy(tmp2, tmp2+n_, res[iout_]);
398 
399  // Propagate to auxiliary outputs
400  if (n_out_>1) {
401  arg1[iin_] = tmp2;
402  std::copy(res, res+n_out_, res1);
403  res1[iout_] = nullptr;
404  oracle_(arg1, res1, iw, w, 0);
405  }
406  return 0;
407  }
408 
410  casadi_int* iw, bvec_t* w, void* mem) const {
411  bvec_t* tmp1 = w; w += n_;
412  bvec_t* tmp2 = w; w += n_;
413 
414  // Get & clear seed corresponding to implicitly defined variable
415  if (res[iout_]) {
416  std::copy(res[iout_], res[iout_]+n_, tmp1);
417  std::fill_n(res[iout_], n_, 0);
418  } else {
419  std::fill_n(tmp1, n_, 0);
420  }
421 
422  // Propagate dependencies from auxiliary outputs to z
423  bvec_t** res1 = res+n_out_;
424  std::copy(res, res+n_out_, res1);
425  res1[iout_] = nullptr;
426  bvec_t** arg1 = arg+n_in_;
427  std::copy(arg, arg+n_in_, arg1);
428  arg1[iin_] = tmp1;
429  if (n_out_>1) {
430  if (oracle_.rev(arg1, res1, iw, w, 0)) return 1;
431  }
432 
433  // "Solve" in order to get seed
434  std::fill_n(tmp2, n_, 0);
435  sp_jac_.spsolve(tmp2, tmp1, true);
436 
437  // Propagate dependencies through the function
438  for (casadi_int i=0; i<n_out_; ++i) res1[i] = nullptr;
439  res1[iout_] = tmp2;
440  arg1[iin_] = nullptr; // just a guess
441  if (oracle_.rev(arg1, res1, iw, w, 0)) return 1;
442  return 0;
443  }
444 
445  std::map<std::string, Rootfinder::Plugin> Rootfinder::solvers_;
446 
447 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
448  std::mutex Rootfinder::mutex_solvers_;
449 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
450 
451  const std::string Rootfinder::infix_ = "rootfinder";
452 
454  ad_forward(const std::vector<MX>& arg, const std::vector<MX>& res,
455  const std::vector<std::vector<MX> >& fseed,
456  std::vector<std::vector<MX> >& fsens,
457  bool always_inline, bool never_inline) const {
458  // Number of directional derivatives
459  casadi_int nfwd = fseed.size();
460  fsens.resize(nfwd);
461 
462  // Quick return if no seeds
463  if (nfwd==0) return;
464 
465  // Propagate through f_
466  std::vector<MX> f_arg(arg);
467  f_arg.at(iin_) = res.at(iout_);
468  std::vector<MX> f_res(res);
469  f_res.at(iout_) = MX(size_in(iin_)); // zero residual
470  std::vector<std::vector<MX> > f_fseed(fseed);
471  for (casadi_int d=0; d<nfwd; ++d) {
472  f_fseed[d].at(iin_) = MX(size_in(iin_)); // ignore seeds for guess
473  }
474  oracle_->call_forward(f_arg, f_res, f_fseed, fsens,
475  always_inline, never_inline);
476 
477  // Get expression of Jacobian
478  Function jac = get_function("jac_g_x");
479  MX J = jac(f_arg).front();
480 
481  // Solve for all the forward derivatives at once
482  std::vector<MX> rhs(nfwd);
483  for (casadi_int d=0; d<nfwd; ++d) rhs[d] = vec(fsens[d][iout_]);
484  rhs = horzsplit(J->get_solve(-horzcat(rhs), false, linsol_));
485  for (casadi_int d=0; d<nfwd; ++d) fsens[d][iout_] = reshape(rhs[d], size_in(iin_));
486 
487  // Propagate to auxiliary outputs
488  if (n_out_>1) {
489  for (casadi_int d=0; d<nfwd; ++d) f_fseed[d][iin_] = fsens[d][iout_];
490  oracle_->call_forward(f_arg, f_res, f_fseed, fsens,
491  always_inline, never_inline);
492  for (casadi_int d=0; d<nfwd; ++d) fsens[d][iout_] = f_fseed[d][iin_]; // Otherwise overwritten
493  }
494  }
495 
497  ad_reverse(const std::vector<MX>& arg, const std::vector<MX>& res,
498  const std::vector<std::vector<MX> >& aseed,
499  std::vector<std::vector<MX> >& asens,
500  bool always_inline, bool never_inline) const {
501 
502  // Number of directional derivatives
503  casadi_int nadj = aseed.size();
504  asens.resize(nadj);
505 
506  // Quick return if no seeds
507  if (nadj==0) return;
508 
509  // Get expression of Jacobian
510  std::vector<MX> f_arg(arg);
511  f_arg[iin_] = res.at(iout_);
512  Function jac = get_function("jac_g_x");
513  MX J = jac(f_arg).front();
514 
515  // Get adjoint seeds for calling f
516  std::vector<MX> f_res(res);
517  f_res[iout_] = MX(size_in(iin_)); // zero residual
518  std::vector<std::vector<MX> > f_aseed(nadj);
519  for (casadi_int d=0; d<nadj; ++d) {
520  f_aseed[d].resize(n_out_);
521  for (casadi_int i=0; i<n_out_; ++i) f_aseed[d][i] = i==iout_ ? f_res[iout_] : aseed[d][i];
522  }
523 
524  // Propagate dependencies from auxiliary outputs
525  std::vector<MX> rhs(nadj);
526  std::vector<std::vector<MX> > asens_aux;
527  if (n_out_>1) {
528  oracle_->call_reverse(f_arg, f_res, f_aseed, asens_aux, always_inline, never_inline);
529  for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(asens_aux[d][iin_] + aseed[d][iout_]);
530  } else {
531  for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(aseed[d][iout_]);
532  }
533 
534  // Solve for all the adjoint seeds at once
535  rhs = horzsplit(J->get_solve(-horzcat(rhs), true, linsol_));
536  for (casadi_int d=0; d<nadj; ++d) {
537  for (casadi_int i=0; i<n_out_; ++i) {
538  if (i==iout_) {
539  f_aseed[d][i] = reshape(rhs[d], size_out(i));
540  } else {
541  // Avoid counting the auxiliary seeds twice
542  f_aseed[d][i] = MX(size_out(i));
543  }
544  }
545  }
546 
547  // No dependency on guess (1)
548  std::vector<MX> tmp(nadj);
549  for (casadi_int d=0; d<nadj; ++d) {
550  asens[d].resize(n_in_);
551  tmp[d] = asens[d][iin_].is_empty(true) ? MX(size_in(iin_)) : asens[d][iin_];
552  }
553 
554  // Propagate through f_
555  oracle_->call_reverse(f_arg, f_res, f_aseed, asens, always_inline, never_inline);
556 
557  // No dependency on guess (2)
558  for (casadi_int d=0; d<nadj; ++d) {
559  asens[d][iin_] = tmp[d];
560  }
561 
562  // Add contribution from auxiliary outputs
563  if (n_out_>1) {
564  for (casadi_int d=0; d<nadj; ++d) {
565  for (casadi_int i=0; i<n_in_; ++i) if (i!=iin_) asens[d][i] += asens_aux[d][i];
566  }
567  }
568  }
569 
570  Dict Rootfinder::get_stats(void* mem) const {
571  Dict stats = OracleFunction::get_stats(mem);
572  auto *m = static_cast<RootfinderMemory*>(mem);
573  stats["success"] = m->success;
574  stats["unified_return_status"] = string_from_UnifiedReturnStatus(m->unified_return_status);
575  return stats;
576  }
577 
580 
581  s.version("Rootfinder", 3);
582  s.pack("Rootfinder::n", n_);
583  s.pack("Rootfinder::linsol", linsol_);
584  s.pack("Rootfinder::sp_jac", sp_jac_);
585  s.pack("Rootfinder::u_c", u_c_);
586  s.pack("Rootfinder::iin", iin_);
587  s.pack("Rootfinder::iout", iout_);
588  }
589 
593  }
594 
597  }
598 
600  s.version("Rootfinder", 3);
601  s.unpack("Rootfinder::n", n_);
602  s.unpack("Rootfinder::linsol", linsol_);
603  s.unpack("Rootfinder::sp_jac", sp_jac_);
604  s.unpack("Rootfinder::u_c", u_c_);
605  s.unpack("Rootfinder::iin", iin_);
606  s.unpack("Rootfinder::iout", iout_);
607  }
608 
609 } // namespace casadi
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
virtual void call_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Forward mode AD, virtual functions overloaded in derived classes.
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Input/output dimensions.
virtual void call_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Reverse mode, virtual functions overloaded in derived classes.
size_t n_in_
Number of inputs and outputs.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Input/output dimensions.
void serialize_type(SerializingStream &s) const override
Serialize type information.
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 setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
static std::string string_from_UnifiedReturnStatus(UnifiedReturnStatus status)
Function object.
Definition: function.hpp:60
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:1007
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
Definition: function.cpp:1183
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:1113
const std::string & name() const
Name of the function.
Definition: function.cpp:1504
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:488
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
Definition: function.cpp:1252
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1167
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
std::vector< std::string > get_free() const
Get free variables as a string.
Definition: function.cpp:1382
size_t sz_w() const
Get required length of w field.
Definition: function.cpp:1241
bool has_free() const
Does the function have free variables.
Definition: function.cpp:1894
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:1003
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
Definition: function.cpp:2009
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:1117
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
bool is_null() const
Is a null pointer?
Linear solver.
Definition: linsol.hpp:55
virtual MX get_solve(const MX &r, bool tr, const Linsol &linear_solver) const
Solve a system of linear equations.
Definition: mx_node.cpp:652
MX - Matrix expression.
Definition: mx.hpp:92
Base class for functions that perform calculation with an oracle.
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
Function oracle_
Oracle: Used to generate other functions.
void init(const Dict &opts) override
int init_mem(void *mem) const override
Initalize memory block.
std::vector< std::string > get_function() const override
Get list of dependency functions.
static const Options options_
Options.
Dict get_stats(void *mem) const override
Get all statistics.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
static Rootfinder * instantiate(const std::string &fname, const std::string &pname, Problem problem)
void serialize_type(SerializingStream &s) const
Serialize type information.
static const Options & plugin_options(const std::string &pname)
Get the plugin options.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.
Base class for FunctionInternal and LinsolInternal.
bool error_on_fail_
Throw an exception on failure?
virtual int solve(void *mem) const =0
int init_mem(void *mem) const override
Initalize memory block.
Definition: rootfinder.cpp:274
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: rootfinder.cpp:578
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Definition: rootfinder.cpp:595
casadi_int n_
Number of equations.
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nfwd forward derivatives.
Definition: rootfinder.cpp:319
~Rootfinder() override=0
Destructor.
Definition: rootfinder.cpp:173
Rootfinder(const std::string &name, const Function &oracle)
Constructor.
Definition: rootfinder.cpp:164
virtual void ad_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Create call to (cached) derivative function, reverse mode.
Definition: rootfinder.cpp:497
std::vector< casadi_int > u_c_
Constraints on decision variables.
Sparsity get_sparsity_out(casadi_int i) override
Sparsities of function inputs and outputs.
Definition: rootfinder.cpp:82
Dict get_stats(void *mem) const override
Get all statistics.
Definition: rootfinder.cpp:570
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: rootfinder.cpp:590
static std::map< std::string, Plugin > solvers_
Collection of solvers.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Definition: rootfinder.cpp:301
static const std::string infix_
Infix.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
Definition: rootfinder.cpp:286
virtual void ad_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Create call to (cached) derivative function, forward mode.
Definition: rootfinder.cpp:454
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity forward.
Definition: rootfinder.cpp:381
casadi_int iin_
Indices of the input and output that correspond to the actual root-finding.
static const Options options_
Options.
Linsol linsol_
Linear solver.
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nadj adjoint derivatives.
Definition: rootfinder.cpp:350
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity backwards.
Definition: rootfinder.cpp:409
std::string get_name_in(casadi_int i) override
Names of function input and outputs.
Definition: rootfinder.cpp:72
static Function create_oracle(const std::map< std::string, XType > &d, const Dict &opts)
Convert dictionary to Problem.
Definition: rootfinder.cpp:122
void init(const Dict &opts) override
Initialize.
Definition: rootfinder.cpp:200
std::string get_name_out(casadi_int i) override
Names of function input and outputs.
Definition: rootfinder.cpp:77
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
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
bool is_column() const
Check if the pattern is a column vector (i.e. size2()==1)
Definition: sparsity.cpp:285
void spsolve(bvec_t *X, bvec_t *B, bool tr) const
Propagate sparsity through a linear solve.
Definition: sparsity.cpp:725
bool is_singular() const
Check whether the sparsity-pattern indicates structural singularity.
Definition: sparsity.cpp:1315
bool is_dense() const
Is dense?
Definition: sparsity.cpp:273
std::string rootfinder_option_type(const std::string &name, const std::string &op)
Get type info for a particular option.
Definition: rootfinder.cpp:91
std::vector< std::string > rootfinder_in()
Get rootfinder input scheme.
Definition: rootfinder.cpp:35
casadi_int rootfinder_n_out()
Number of rootfinder outputs.
Definition: rootfinder.cpp:68
casadi_int rootfinder_n_in()
Number of rootfinder inputs.
Definition: rootfinder.cpp:64
void load_rootfinder(const std::string &name)
Explicitly load a plugin dynamically.
Definition: rootfinder.cpp:103
RootfinderInput
Input arguments of a rootfinder.
Definition: rootfinder.hpp:156
std::string rootfinder_option_info(const std::string &name, const std::string &op)
Get documentation for a particular option.
Definition: rootfinder.cpp:95
std::vector< std::string > rootfinder_options(const std::string &name)
Get all options for a plugin.
Definition: rootfinder.cpp:87
std::string doc_rootfinder(const std::string &name)
Get the documentation string for a plugin.
Definition: rootfinder.cpp:107
bool has_rootfinder(const std::string &name)
Check if a particular plugin is available.
Definition: rootfinder.cpp:99
std::vector< std::string > rootfinder_out()
Get rootfinder output scheme.
Definition: rootfinder.cpp:41
Function rootfinder(const std::string &name, const std::string &solver, const SXDict &rfp, const Dict &opts)
Definition: rootfinder.cpp:111
RootfinderOutput
Output arguments of a rootfinder.
Definition: rootfinder.hpp:166
@ RFP_NUM_OUT
Definition: rootfinder.hpp:150
@ RFP_NUM_IN
Definition: rootfinder.hpp:142
@ ROOTFINDER_NUM_IN
Number of input arguments of a rootfinder.
Definition: rootfinder.hpp:162
@ ROOTFINDER_P
Parameters.
Definition: rootfinder.hpp:160
@ ROOTFINDER_X0
Initial guess for the solution.
Definition: rootfinder.hpp:158
@ ROOTFINDER_X
Solution to the system of equations.
Definition: rootfinder.hpp:168
@ ROOTFINDER_NUM_OUT
Number of output arguments of a rootfinder.
Definition: rootfinder.hpp:170
The casadi namespace.
Definition: archiver.cpp:28
std::map< std::string, MX > MXDict
Definition: mx.hpp:1110
unsigned long long bvec_t
@ OT_INTVECTOR
std::map< std::string, SX > SXDict
Definition: sx_fwd.hpp:40
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
@ SOLVER_RET_UNKNOWN
Options metadata for a class.
Definition: options.hpp:40
std::string type(const std::string &name) const
Definition: options.cpp:289
std::vector< std::string > all() const
Definition: options.cpp:283
std::string info(const std::string &name) const
Definition: options.cpp:295