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 if ((it=opts.find("verbose")) != opts.end()) {
144  // "oracle_options" has not been set, but "verbose" has
145  oracle_options["verbose"] = it->second;
146  }
147 
148  // Create oracle
149  return Function("rfp", rfp_in, rfp_out, {"x", "p"}, {"g"}, oracle_options);
150  }
151 
152  Function rootfinder(const std::string& name, const std::string& solver,
153  const Function& f, const Dict& opts) {
154  // Make sure that residual function is sound
155  if (f.has_free()) {
156  casadi_error("Cannot create '" + name + "' since " + str(f.get_free()) + " are free.");
157  }
158  return Function::create(Rootfinder::instantiate(name, solver, f), opts);
159  }
160 
161  Rootfinder::Rootfinder(const std::string& name, const Function& oracle)
162  : OracleFunction(name, oracle) {
163 
164  // Default options
165  iin_ = 0;
166  iout_ = 0;
167  error_on_fail_ = true;
168  }
169 
171  }
172 
175  {{"linear_solver",
176  {OT_STRING,
177  "User-defined linear solver class. Needed for sensitivities."}},
178  {"linear_solver_options",
179  {OT_DICT,
180  "Options to be passed to the linear solver."}},
181  {"constraints",
182  {OT_INTVECTOR,
183  "Constrain the unknowns. 0 (default): no constraint on ui, "
184  "1: ui >= 0.0, -1: ui <= 0.0, 2: ui > 0.0, -2: ui < 0.0."}},
185  {"implicit_input",
186  {OT_INT,
187  "Index of the input that corresponds to the actual root-finding"}},
188  {"implicit_output",
189  {OT_INT,
190  "Index of the output that corresponds to the actual root-finding"}},
191  {"jacobian_function",
192  {OT_FUNCTION,
193  "Function object for calculating the Jacobian (autogenerated by default)"}},
194  }
195  };
196 
197  void Rootfinder::init(const Dict& opts) {
198 
199  // Default (temporary) options
200  Dict linear_solver_options;
201  std::string linear_solver = "qr";
202  Function jac; // Jacobian of f with respect to z
203 
204  // Read options
205  for (auto&& op : opts) {
206  if (op.first=="implicit_input") {
207  iin_ = op.second;
208  } else if (op.first=="implicit_output") {
209  iout_ = op.second;
210  } else if (op.first=="jacobian_function") {
211  jac = op.second;
212  } else if (op.first=="linear_solver_options") {
213  linear_solver_options = op.second;
214  } else if (op.first=="linear_solver") {
215  linear_solver = op.second.to_string();
216  } else if (op.first=="constraints") {
217  u_c_ = op.second;
218  }
219  }
220 
221  // Get the number of equations and check consistency
222  casadi_assert(iin_>=0 && iin_<oracle_.n_in() && oracle_.n_in()>0,
223  "Implicit input not in range");
224  casadi_assert(iout_>=0 && iout_<oracle_.n_out() && oracle_.n_out()>0,
225  "Implicit output not in range");
226  casadi_assert(oracle_.sparsity_out(iout_).is_dense()
228  "Residual must be a dense vector");
229  casadi_assert(oracle_.sparsity_in(iin_).is_dense()
231  "Unknown must be a dense vector");
232  n_ = oracle_.nnz_out(iout_);
233  casadi_assert(n_ == oracle_.nnz_in(iin_),
234  "Dimension mismatch. Input size is " + str(oracle_.nnz_in(iin_)) + ", "
235  "while output size is " + str(oracle_.nnz_out(iout_)));
236 
237  // Call the base class initializer
238  OracleFunction::init(opts);
239 
240  // Generate Jacobian if not provided
241  if (jac.is_null()) {
242  std::vector<std::string> s_in = oracle_.name_in();
243  std::vector<std::string> s_out = oracle_.name_out();
244  s_out.insert(s_out.begin(), "jac:" + oracle_.name_out(iout_) + ":" + oracle_.name_in(iin_));
245  jac = oracle_.factory(oracle_.name() + "_jac", s_in, s_out);
246  }
247  set_function(jac, "jac_g_x");
248  sp_jac_ = jac.sparsity_out(0);
249  // Check for structural singularity in the Jacobian
250  casadi_assert(!sp_jac_.is_singular(),
251  "Rootfinder::init: singularity - the jacobian is structurally rank-deficient. "
252  "sprank(J)=" + str(sprank(sp_jac_)) + " (instead of " + str(sp_jac_.size1()) + ")");
253 
254  // Get the linear solver creator function
255  linsol_ = Linsol("linsol", linear_solver, sp_jac_, linear_solver_options);
256 
257  // Constraints
258  casadi_assert(u_c_.size()==n_ || u_c_.empty(),
259  "Constraint vector if supplied, must be of length n, but got "
260  + str(u_c_.size()) + " and n = " + str(n_));
261 
262  // Allocate sufficiently large work vectors
263  alloc(oracle_);
264  size_t sz_w = oracle_.sz_w();
265  if (!jac.is_null()) {
266  sz_w = std::max(sz_w, jac.sz_w());
267  }
268  alloc_w(sz_w + 2*static_cast<size_t>(n_));
269  }
270 
271  int Rootfinder::init_mem(void* mem) const {
272  if (OracleFunction::init_mem(mem)) return 1;
273 
274  auto m = static_cast<RootfinderMemory*>(mem);
275 
276  // Problem has not been solved at this point
277  m->success = false;
278  m->unified_return_status = SOLVER_RET_UNKNOWN;
279 
280  return 0;
281  }
282 
283  int Rootfinder::eval(const double** arg, double** res,
284  casadi_int* iw, double* w, void* mem) const {
285  // Reset the solver, prepare for solution
286  setup(mem, arg, res, iw, w);
287 
288  // Solve the NLP
289  int ret = solve(mem);
290  auto m = static_cast<RootfinderMemory*>(mem);
291  if (error_on_fail_ && !m->success)
292  casadi_error("rootfinder process failed. "
293  "Set 'error_on_fail' option to false to ignore this error.");
294 
295  return ret;
296  }
297 
298  void Rootfinder::set_work(void* mem, const double**& arg, double**& res,
299  casadi_int*& iw, double*& w) const {
300  auto m = static_cast<RootfinderMemory*>(mem);
301 
302  // Problem has not been solved at this point
303  m->success = false;
304  m->unified_return_status = SOLVER_RET_UNKNOWN;
305 
306  // Get input pointers
307  m->iarg = arg;
308  arg += n_in_;
309 
310  // Get output pointers
311  m->ires = res;
312  res += n_out_;
313  }
314 
316  ::get_forward(casadi_int nfwd, const std::string& name,
317  const std::vector<std::string>& inames,
318  const std::vector<std::string>& onames,
319  const Dict& opts) const {
320  // Symbolic expression for the input
321  std::vector<MX> arg = mx_in(), res = mx_out();
322  std::vector<std::vector<MX>> fseed = fwd_seed<MX>(nfwd), fsens;
323  arg[iin_] = MX::sym(arg[iin_].name(), Sparsity(arg[iin_].size()));
324  for (auto&& e : fseed) e[iin_] = MX::sym(e[iin_].name(), e[iin_].size());
325  ad_forward(arg, res, fseed, fsens, false, false);
326 
327  // Construct return function
328  arg.insert(arg.end(), res.begin(), res.end());
329  std::vector<MX> v(nfwd);
330  for (casadi_int i=0; i<n_in_; ++i) {
331  for (casadi_int d=0; d<nfwd; ++d) v[d] = fseed[d][i];
332  arg.push_back(horzcat(v));
333  }
334  res.clear();
335  for (casadi_int i=0; i<n_out_; ++i) {
336  for (casadi_int d=0; d<nfwd; ++d) v[d] = fsens[d][i];
337  res.push_back(ensure_stacked(horzcat(v), sparsity_out(i), nfwd));
338  }
339 
340  Dict options = opts;
341  options["allow_duplicate_io_names"] = true;
342 
343  return Function(name, arg, res, inames, onames, options);
344  }
345 
347  ::get_reverse(casadi_int nadj, const std::string& name,
348  const std::vector<std::string>& inames,
349  const std::vector<std::string>& onames,
350  const Dict& opts) const {
351  // Symbolic expression for the input
352  std::vector<MX> arg = mx_in();
353  arg[iin_] = MX::sym(arg[iin_].name() + "_guess",
354  Sparsity(arg[iin_].size()));
355  std::vector<MX> res = mx_out();
356  std::vector<std::vector<MX> > aseed = symbolicAdjSeed(nadj, res), asens;
357  ad_reverse(arg, res, aseed, asens, false, false);
358 
359  // Construct return function
360  arg.insert(arg.end(), res.begin(), res.end());
361  std::vector<MX> v(nadj);
362  for (casadi_int i=0; i<n_out_; ++i) {
363  for (casadi_int d=0; d<nadj; ++d) v[d] = aseed[d][i];
364  arg.push_back(horzcat(v));
365  }
366  res.clear();
367  for (casadi_int i=0; i<n_in_; ++i) {
368  for (casadi_int d=0; d<nadj; ++d) v[d] = asens[d][i];
369  res.push_back(ensure_stacked(horzcat(v), sparsity_in(i), nadj));
370  }
371 
372  Dict options = opts;
373  options["allow_duplicate_io_names"] = true;
374  return Function(name, arg, res, inames, onames, options);
375  }
376 
378  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, void* mem) const {
379  bvec_t* tmp1 = w; w += n_;
380  bvec_t* tmp2 = w; w += n_;
381 
382  // Propagate dependencies through the function
383  const bvec_t** arg1 = arg+n_in_;
384  std::copy(arg, arg+n_in_, arg1);
385  arg1[iin_] = nullptr;
386  bvec_t** res1 = res+n_out_;
387  std::fill_n(res1, n_out_, static_cast<bvec_t*>(nullptr));
388  res1[iout_] = tmp1;
389  oracle_(arg1, res1, iw, w, 0);
390 
391  // "Solve" in order to propagate to z
392  std::fill_n(tmp2, n_, 0);
393  sp_jac_.spsolve(tmp2, tmp1, false);
394  if (res[iout_]) std::copy(tmp2, tmp2+n_, res[iout_]);
395 
396  // Propagate to auxiliary outputs
397  if (n_out_>1) {
398  arg1[iin_] = tmp2;
399  std::copy(res, res+n_out_, res1);
400  res1[iout_] = nullptr;
401  oracle_(arg1, res1, iw, w, 0);
402  }
403  return 0;
404  }
405 
407  casadi_int* iw, bvec_t* w, void* mem) const {
408  bvec_t* tmp1 = w; w += n_;
409  bvec_t* tmp2 = w; w += n_;
410 
411  // Get & clear seed corresponding to implicitly defined variable
412  if (res[iout_]) {
413  std::copy(res[iout_], res[iout_]+n_, tmp1);
414  std::fill_n(res[iout_], n_, 0);
415  } else {
416  std::fill_n(tmp1, n_, 0);
417  }
418 
419  // Propagate dependencies from auxiliary outputs to z
420  bvec_t** res1 = res+n_out_;
421  std::copy(res, res+n_out_, res1);
422  res1[iout_] = nullptr;
423  bvec_t** arg1 = arg+n_in_;
424  std::copy(arg, arg+n_in_, arg1);
425  arg1[iin_] = tmp1;
426  if (n_out_>1) {
427  if (oracle_.rev(arg1, res1, iw, w, 0)) return 1;
428  }
429 
430  // "Solve" in order to get seed
431  std::fill_n(tmp2, n_, 0);
432  sp_jac_.spsolve(tmp2, tmp1, true);
433 
434  // Propagate dependencies through the function
435  for (casadi_int i=0; i<n_out_; ++i) res1[i] = nullptr;
436  res1[iout_] = tmp2;
437  arg1[iin_] = nullptr; // just a guess
438  if (oracle_.rev(arg1, res1, iw, w, 0)) return 1;
439  return 0;
440  }
441 
442  std::map<std::string, Rootfinder::Plugin> Rootfinder::solvers_;
443 
444 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
445  std::mutex Rootfinder::mutex_solvers_;
446 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
447 
448  const std::string Rootfinder::infix_ = "rootfinder";
449 
451  ad_forward(const std::vector<MX>& arg, const std::vector<MX>& res,
452  const std::vector<std::vector<MX> >& fseed,
453  std::vector<std::vector<MX> >& fsens,
454  bool always_inline, bool never_inline) const {
455  // Number of directional derivatives
456  casadi_int nfwd = fseed.size();
457  fsens.resize(nfwd);
458 
459  // Quick return if no seeds
460  if (nfwd==0) return;
461 
462  // Propagate through f_
463  std::vector<MX> f_arg(arg);
464  f_arg.at(iin_) = res.at(iout_);
465  std::vector<MX> f_res(res);
466  f_res.at(iout_) = MX(size_in(iin_)); // zero residual
467  std::vector<std::vector<MX> > f_fseed(fseed);
468  for (casadi_int d=0; d<nfwd; ++d) {
469  f_fseed[d].at(iin_) = MX(size_in(iin_)); // ignore seeds for guess
470  }
471  oracle_->call_forward(f_arg, f_res, f_fseed, fsens,
472  always_inline, never_inline);
473 
474  // Get expression of Jacobian
475  Function jac = get_function("jac_g_x");
476  MX J = jac(f_arg).front();
477 
478  // Solve for all the forward derivatives at once
479  std::vector<MX> rhs(nfwd);
480  for (casadi_int d=0; d<nfwd; ++d) rhs[d] = vec(fsens[d][iout_]);
481  rhs = horzsplit(J->get_solve(-horzcat(rhs), false, linsol_));
482  for (casadi_int d=0; d<nfwd; ++d) fsens[d][iout_] = reshape(rhs[d], size_in(iin_));
483 
484  // Propagate to auxiliary outputs
485  if (n_out_>1) {
486  for (casadi_int d=0; d<nfwd; ++d) f_fseed[d][iin_] = fsens[d][iout_];
487  oracle_->call_forward(f_arg, f_res, f_fseed, fsens,
488  always_inline, never_inline);
489  for (casadi_int d=0; d<nfwd; ++d) fsens[d][iout_] = f_fseed[d][iin_]; // Otherwise overwritten
490  }
491  }
492 
494  ad_reverse(const std::vector<MX>& arg, const std::vector<MX>& res,
495  const std::vector<std::vector<MX> >& aseed,
496  std::vector<std::vector<MX> >& asens,
497  bool always_inline, bool never_inline) const {
498 
499  // Number of directional derivatives
500  casadi_int nadj = aseed.size();
501  asens.resize(nadj);
502 
503  // Quick return if no seeds
504  if (nadj==0) return;
505 
506  // Get expression of Jacobian
507  std::vector<MX> f_arg(arg);
508  f_arg[iin_] = res.at(iout_);
509  Function jac = get_function("jac_g_x");
510  MX J = jac(f_arg).front();
511 
512  // Get adjoint seeds for calling f
513  std::vector<MX> f_res(res);
514  f_res[iout_] = MX(size_in(iin_)); // zero residual
515  std::vector<std::vector<MX> > f_aseed(nadj);
516  for (casadi_int d=0; d<nadj; ++d) {
517  f_aseed[d].resize(n_out_);
518  for (casadi_int i=0; i<n_out_; ++i) f_aseed[d][i] = i==iout_ ? f_res[iout_] : aseed[d][i];
519  }
520 
521  // Propagate dependencies from auxiliary outputs
522  std::vector<MX> rhs(nadj);
523  std::vector<std::vector<MX> > asens_aux;
524  if (n_out_>1) {
525  oracle_->call_reverse(f_arg, f_res, f_aseed, asens_aux, always_inline, never_inline);
526  for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(asens_aux[d][iin_] + aseed[d][iout_]);
527  } else {
528  for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(aseed[d][iout_]);
529  }
530 
531  // Solve for all the adjoint seeds at once
532  rhs = horzsplit(J->get_solve(-horzcat(rhs), true, linsol_));
533  for (casadi_int d=0; d<nadj; ++d) {
534  for (casadi_int i=0; i<n_out_; ++i) {
535  if (i==iout_) {
536  f_aseed[d][i] = reshape(rhs[d], size_out(i));
537  } else {
538  // Avoid counting the auxiliary seeds twice
539  f_aseed[d][i] = MX(size_out(i));
540  }
541  }
542  }
543 
544  // No dependency on guess (1)
545  std::vector<MX> tmp(nadj);
546  for (casadi_int d=0; d<nadj; ++d) {
547  asens[d].resize(n_in_);
548  tmp[d] = asens[d][iin_].is_empty(true) ? MX(size_in(iin_)) : asens[d][iin_];
549  }
550 
551  // Propagate through f_
552  oracle_->call_reverse(f_arg, f_res, f_aseed, asens, always_inline, never_inline);
553 
554  // No dependency on guess (2)
555  for (casadi_int d=0; d<nadj; ++d) {
556  asens[d][iin_] = tmp[d];
557  }
558 
559  // Add contribution from auxiliary outputs
560  if (n_out_>1) {
561  for (casadi_int d=0; d<nadj; ++d) {
562  for (casadi_int i=0; i<n_in_; ++i) if (i!=iin_) asens[d][i] += asens_aux[d][i];
563  }
564  }
565  }
566 
567  Dict Rootfinder::get_stats(void* mem) const {
568  Dict stats = OracleFunction::get_stats(mem);
569  auto m = static_cast<RootfinderMemory*>(mem);
570  stats["success"] = m->success;
571  stats["unified_return_status"] = string_from_UnifiedReturnStatus(m->unified_return_status);
572  return stats;
573  }
574 
577 
578  s.version("Rootfinder", 3);
579  s.pack("Rootfinder::n", n_);
580  s.pack("Rootfinder::linsol", linsol_);
581  s.pack("Rootfinder::sp_jac", sp_jac_);
582  s.pack("Rootfinder::u_c", u_c_);
583  s.pack("Rootfinder::iin", iin_);
584  s.pack("Rootfinder::iout", iout_);
585  }
586 
590  }
591 
594  }
595 
597  s.version("Rootfinder", 3);
598  s.unpack("Rootfinder::n", n_);
599  s.unpack("Rootfinder::linsol", linsol_);
600  s.unpack("Rootfinder::sp_jac", sp_jac_);
601  s.unpack("Rootfinder::u_c", u_c_);
602  s.unpack("Rootfinder::iin", iin_);
603  s.unpack("Rootfinder::iout", iout_);
604  }
605 
606 } // 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:855
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
Definition: function.cpp:1031
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:961
const std::string & name() const
Name of the function.
Definition: function.cpp:1307
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:336
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
Definition: function.cpp:1100
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1015
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:823
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:819
std::vector< std::string > get_free() const
Get free variables as a string.
Definition: function.cpp:1184
size_t sz_w() const
Get required length of w field.
Definition: function.cpp:1089
bool has_free() const
Does the function have free variables.
Definition: function.cpp:1697
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:851
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:1812
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:965
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:649
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:271
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: rootfinder.cpp:575
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Definition: rootfinder.cpp:592
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:316
~Rootfinder() override=0
Destructor.
Definition: rootfinder.cpp:170
Rootfinder(const std::string &name, const Function &oracle)
Constructor.
Definition: rootfinder.cpp:161
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:494
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:567
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: rootfinder.cpp:587
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:298
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:283
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:451
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:378
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:347
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:406
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:197
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:723
bool is_singular() const
Check whether the sparsity-pattern indicates structural singularity.
Definition: sparsity.cpp:1299
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:1009
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