function.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 "function_internal.hpp"
27 #include "casadi_misc.hpp"
28 #include "sx_function.hpp"
29 #include "mx_function.hpp"
30 #include "switch.hpp"
31 #include "bspline.hpp"
32 #include "nlpsol.hpp"
33 #include "mapsum.hpp"
34 #include "conic.hpp"
35 #include "jit_function.hpp"
36 #include "serializing_stream.hpp"
37 #include "serializer.hpp"
38 #include "tools.hpp"
39 #include "filesystem_impl.hpp"
40 
41 #include <cctype>
42 #include <fstream>
43 #include <typeinfo>
44 
45 namespace casadi {
46  // Throw informative error message
47  #define THROW_ERROR(FNAME, WHAT) \
48  throw CasadiException("Error in Function::" FNAME " for '" + this->name() + "' "\
49  "[" + this->class_name() + "] at " + CASADI_WHERE + ":\n"\
50  + std::string(WHAT));
51 
52  // Throw informative error message from constructor
53  #define THROW_ERROR_NOOBJ(FNAME, WHAT, CLASS_NAME) \
54  throw CasadiException("Error in Function::" FNAME " for '" + name + "' "\
55  "[" CLASS_NAME "] at " + CASADI_WHERE + ":\n"\
56  + std::string(WHAT));
57 
59  }
60 
62  }
63 
64  bool Function::proceed_to(std::istream& file, const std::string& str) {
65  // Make sure that the file is ready for reading
66  if (!file.good()) return false;
67  // Have we already wrapped around once?
68  //bool wrapped_around = false;
69  // Read line-by-line
70  std::string tmp;
71  while (true) {
72  // Read a word
73  std::streampos cur_pos = file.tellg();
74  file >> tmp;
75  if (!file.good()) return false;
76 
77  // Check if match
78  if (str==tmp) return true;
79 
80  // If comment, continue to the end of the line
81  if (tmp.at(0)=='#') {
82  file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
83  continue;
84  }
85 
86  // If mismatching name, rewind and break
87  file.seekg(cur_pos);
88  return false;
89  }
90  }
91 
92  Function::Function(const std::string& fname) {
93  casadi_error("Not implemented");
94  }
95 
96  Function::Function(const std::string& name,
97  const std::vector<SX>& ex_in, const std::vector<SX>& ex_out,
98  const Dict& opts) {
99  construct(name, ex_in, ex_out, {}, {}, opts);
100  }
101 
102  Function::Function(const std::string& name,
103  const std::vector<SX>& ex_in, const std::vector<SX>& ex_out,
104  const std::vector<std::string>& name_in,
105  const std::vector<std::string>& name_out,
106  const Dict& opts) {
107  construct(name, ex_in, ex_out, name_in, name_out, opts);
108  }
109 
110  Function::Function(const std::string& name,
111  const std::vector<MX>& ex_in, const std::vector<MX>& ex_out,
112  const Dict& opts) {
113  construct(name, ex_in, ex_out, {}, {}, opts);
114  }
115 
116  Function::Function(const std::string& name,
117  const std::vector<MX>& ex_in, const std::vector<MX>& ex_out,
118  const std::vector<std::string>& name_in,
119  const std::vector<std::string>& name_out,
120  const Dict& opts) {
121  construct(name, ex_in, ex_out, name_in, name_out, opts);
122  }
123 
124  Function::Function(const std::string& name,
125  SXIList ex_in, const SXVector& ex_out, const Dict& opts) {
126  construct(name, SXVector(ex_in), ex_out, {}, {}, opts);
127  }
128 
129  Function::Function(const std::string& name,
130  const SXVector& ex_in, SXIList ex_out, const Dict& opts) {
131  construct(name, ex_in, SXVector(ex_out), {}, {}, opts);
132  }
133 
134  Function::Function(const std::string& name, SXIList ex_in, SXIList ex_out, const Dict& opts) {
135  construct(name, SXVector(ex_in), SXVector(ex_out), {}, {}, opts);
136  }
137 
138  Function::Function(const std::string& name, SXIList ex_in, const SXVector& ex_out,
139  const StringVector& name_in,
140  const StringVector& name_out, const Dict& opts) {
141  construct(name, SXVector(ex_in), ex_out, name_in, name_out, opts);
142  }
143 
144  Function::Function(const std::string& name, const SXVector& ex_in, SXIList ex_out,
145  const StringVector& name_in, const StringVector& name_out, const Dict& opts) {
146  construct(name, ex_in, SXVector(ex_out), name_in, name_out, opts);
147  }
148 
149  Function::Function(const std::string& name, SXIList ex_in, SXIList ex_out,
150  const StringVector& name_in, const StringVector& name_out, const Dict& opts) {
151  construct(name, SXVector(ex_in), SXVector(ex_out), name_in, name_out, opts);
152  }
153 
154  Function::Function(const std::string& name,
155  MXIList ex_in, const MXVector& ex_out, const Dict& opts) {
156  construct(name, MXVector(ex_in), ex_out, {}, {}, opts);
157  }
158 
159  Function::Function(const std::string& name,
160  const MXVector& ex_in, MXIList ex_out, const Dict& opts) {
161  construct(name, ex_in, MXVector(ex_out), {}, {}, opts);
162  }
163 
164  Function::Function(const std::string& name, MXIList ex_in, MXIList ex_out, const Dict& opts) {
165  construct(name, MXVector(ex_in), MXVector(ex_out), {}, {}, opts);
166  }
167 
168  Function::Function(const std::string& name, MXIList ex_in, const MXVector& ex_out,
169  const StringVector& name_in, const StringVector& name_out, const Dict& opts) {
170  construct(name, MXVector(ex_in), ex_out, name_in, name_out, opts);
171  }
172 
173  Function::Function(const std::string& name, const MXVector& ex_in, MXIList ex_out,
174  const StringVector& name_in, const StringVector& name_out, const Dict& opts) {
175  construct(name, ex_in, MXVector(ex_out), name_in, name_out, opts);
176  }
177 
178  Function::Function(const std::string& name, MXIList ex_in, MXIList ex_out,
179  const StringVector& name_in, const StringVector& name_out, const Dict& opts) {
180  construct(name, MXVector(ex_in), MXVector(ex_out), name_in, name_out, opts);
181  }
182 
183  Function::Function(const std::string& name, const std::map<std::string, SX>& dict,
184  const std::vector<std::string>& name_in, const std::vector<std::string>& name_out,
185  const Dict& opts) {
186  construct(name, dict, name_in, name_out, opts);
187  }
188 
189  Function::Function(const std::string& name, const std::map<std::string, MX>& dict,
190  const std::vector<std::string>& name_in, const std::vector<std::string>& name_out,
191  const Dict& opts) {
192  construct(name, dict, name_in, name_out, opts);
193  }
194 
195  template<typename M>
196  void Function::construct(const std::string& name, const std::map<std::string, M>& dict,
197  const std::vector<std::string>& name_in,
198  const std::vector<std::string>& name_out,
199  const Dict& opts) {
200  std::vector<M> ex_in(name_in.size()), ex_out(name_out.size());
201  for (auto&& i : dict) {
202  std::vector<std::string>::const_iterator it;
203  it = std::find(name_in.begin(), name_in.end(), i.first);
204  if (it!=name_in.end()) {
205  // Input expression
206  ex_in[it-name_in.begin()] = i.second;
207  } else {
208  it = std::find(name_out.begin(), name_out.end(), i.first);
209  if (it!=name_out.end()) {
210  // Output expression
211  ex_out[it-name_out.begin()] = i.second;
212  } else {
213  // Neither
214  casadi_error("Unknown dictionary entry: '" + i.first + "'");
215  }
216  }
217  }
218  construct(name, ex_in, ex_out, name_in, name_out, opts);
219  }
220 
221  void Function::construct(const std::string& name,
222  const std::vector<SX>& ex_in, const std::vector<SX>& ex_out,
223  const std::vector<std::string>& name_in,
224  const std::vector<std::string>& name_out,
225  const Dict& opts) {
226  try {
227  own(new SXFunction(name, ex_in, ex_out, name_in, name_out));
228  (*this)->construct(opts);
229 
230  // Perform external transformations
231  auto it = opts.find("external_transform");
232  if (it!=opts.end()) {
233  auto v = it->second.to_vector_vector();
234  for (const std::vector<GenericType>& vec : v) {
235  casadi_assert(vec.size()>=2, "external_transform: inner list must be length >=2");
236  casadi_assert(vec.size()<=3, "external_transform: inner list must be length <=3");
237  std::string name = vec[0].to_string();
238  std::string op = vec[1].to_string();
239  Dict opts = vec.size()==3 ? vec[2].to_dict() : Dict();
240  operator=(external_transform(name, op, (*this), opts));
241  }
242  }
243 
244  } catch(std::exception& e) {
245  THROW_ERROR_NOOBJ("Function", e.what(), "SXFunction");
246  }
247  }
248 
249  void Function::construct(const std::string& name,
250  const std::vector<MX>& ex_in, const std::vector<MX>& ex_out,
251  const std::vector<std::string>& name_in,
252  const std::vector<std::string>& name_out,
253  const Dict& opts) {
254  try {
255  own(new MXFunction(name, ex_in, ex_out, name_in, name_out));
256  (*this)->construct(opts);
257 
258  // Perform post-construction expand
259  auto it = opts.find("post_expand");
260  if (it!=opts.end()) {
261  if (!it->second) return;
262  auto it = opts.find("post_expand_options");
263  if (it==opts.end()) {
264  operator=((*this).expand());
265  } else {
266  operator=((*this).expand((*this).name(), it->second));
267  }
268  }
269 
270  // Perform external transformations
271  it = opts.find("external_transform");
272  if (it!=opts.end()) {
273  auto v = it->second.to_vector_vector();
274  for (const std::vector<GenericType>& vec : v) {
275  casadi_assert(vec.size()>=2, "external_transform: inner list must be length >=2");
276  casadi_assert(vec.size()<=3, "external_transform: inner list must be length <=3");
277  std::string name = vec[0].to_string();
278  std::string op = vec[1].to_string();
279  Dict opts = vec.size()==3 ? vec[2].to_dict() : Dict();
280  operator=(external_transform(name, op, (*this), opts));
281  }
282  }
283 
284  } catch(std::exception& e) {
285  THROW_ERROR_NOOBJ("Function", e.what(), "MXFunction");
286  }
287  }
288 
289  Function Function::jit(const std::string& name, const std::string& body,
290  const std::vector<std::string>& name_in,
291  const std::vector<std::string>& name_out,
292  const Dict& opts) {
293  // Pass empty vectors -> default values
294  std::vector<Sparsity> sparsity_in, sparsity_out;
295  return jit(name, body, name_in, name_out, sparsity_in, sparsity_out, opts);
296  }
297 
298  Function Function::jit(const std::string& name, const std::string& body,
299  const std::vector<std::string>& name_in,
300  const std::vector<std::string>& name_out,
301  const std::vector<Sparsity>& sparsity_in,
302  const std::vector<Sparsity>& sparsity_out,
303  const Dict& opts) {
304  try {
305  return create(new JitFunction(name, body, name_in, name_out,
306  sparsity_in, sparsity_out), opts);
307  } catch(std::exception& e) {
308  THROW_ERROR_NOOBJ("jit", e.what(), "JitFunction");
309  }
310  }
311 
313  Dict opts = (*this)->generate_options("clone");
314  return expand(name(), opts);
315  }
316 
317  Function Function::expand(const std::string& name, const Dict& opts) const {
318  casadi_assert(!has_free(),
319  "Function with free symbols cannot be expanded. "
320  "List of free variables in your Function: " +
321  join(get_free(), ","));
322 
323  Dict my_opts = (*this)->generate_options("clone");
324  update_dict(my_opts, opts);
325  std::vector<SX> ex_in = sx_in();
326  std::vector<SX> ex_out = Function(*this)(ex_in);
327  return Function(name, ex_in, ex_out, name_in(), name_out(), my_opts);
328  }
329 
330  // Stringify a single pass token (string, integer or dict) for copy-paste
331  std::string transform_token_str(const GenericType& g) {
332  if (g.is_int()) return str(g.to_int());
333  if (g.is_string()) return "\"" + g.to_string() + "\"";
334  if (g.is_dict()) return str(g.to_dict());
335  return "?";
336  }
337  // Stringify the whole pass list as a copy-pasteable literal
338  std::string transform_passes_str(const std::vector<std::vector<GenericType> >& ps) {
339  std::string s = "[";
340  for (size_t i=0; i<ps.size(); ++i) {
341  if (i) s += ", ";
342  s += "[";
343  for (size_t j=0; j<ps[i].size(); ++j) {
344  if (j) s += ", ";
345  s += transform_token_str(ps[i][j]);
346  }
347  s += "]";
348  }
349  return s + "]";
350  }
351  // A few cheap stats describing a function's graph size
352  std::string transform_stats(const Function& f) {
353  std::string s;
354  try { s += "n_nodes=" + str(f.n_nodes()); } catch (...) { s += "n_nodes=?"; }
355  try { s += ", n_instructions=" + str(f.n_instructions()); } catch (...) {}
356  return s;
357  }
358 
359  Function Function::transform(const Dict& opts) const {
360  return transform(name(), opts);
361  }
362 
363  Function Function::transform(const std::string& fname, const Dict& opts) const {
364  try {
365  // Boolean shorthands (defaults reproduce the meaningful default flow)
366  bool empty_inputs = true;
367  bool combine_terms = false;
368  bool cse = true;
369  bool ref_count = true;
370  bool const_folding = true;
371  bool verbose = false;
372  for (auto&& op : opts) {
373  if (op.first=="empty_inputs") {
374  empty_inputs = op.second;
375  } else if (op.first=="combine_terms") {
376  combine_terms = op.second;
377  } else if (op.first=="cse") {
378  cse = op.second;
379  } else if (op.first=="ref_count") {
380  ref_count = op.second;
381  } else if (op.first=="const_folding") {
382  const_folding = op.second;
383  } else if (op.first=="verbose") {
384  verbose = op.second;
385  } else {
386  casadi_error("transform: no such option: " + std::string(op.first) + ".\n");
387  }
388  }
389  std::vector<GenericType> simp = {std::string("simplify")};
390  if (empty_inputs) simp.push_back("empty_inputs");
391  if (combine_terms) simp.push_back("combine_terms");
392  if (cse) simp.push_back("cse");
393  if (ref_count) { simp.push_back(0); simp.push_back("ref_count"); } // 0 = fixed point
394  if (const_folding) simp.push_back("const_folding");
395  return transform(fname, std::vector<std::vector<GenericType> >{simp}, {{"verbose", verbose}});
396  } catch(std::exception& e) {
397  THROW_ERROR("transform", e.what());
398  }
399  }
400 
401  Function Function::transform(const std::vector<std::vector<GenericType> >& passes,
402  const Dict& opts) const {
403  return transform(name(), passes, opts);
404  }
405 
406  Function Function::transform(const std::string& fname,
407  const std::vector<std::vector<GenericType> >& passes,
408  const Dict& opts) const {
409  try {
410  // Only 'verbose' is accepted here; boolean simplify options belong to the
411  // dict-only overload
412  bool verbose = false;
413  for (auto&& op : opts) {
414  if (op.first=="verbose") {
415  verbose = op.second;
416  } else {
417  casadi_error("transform(passes, opts): unsupported option '" + std::string(op.first)
418  + "' (boolean simplify options are only allowed in the dict-only form).\n");
419  }
420  }
421 
422  if (verbose) {
423  uout() << "transform(" << transform_passes_str(passes) << ")" << std::endl;
424  uout() << " start: " << transform_stats(*this) << std::endl;
425  }
426 
427  // Run the pipeline
428  Function f = *this;
429  for (const auto& pass : passes) {
430  casadi_assert(!pass.empty(), "transform: each pass must be a non-empty list");
431  std::string verb = pass.front().to_string();
432  if (verb=="simplify") {
433  // Tasks are strings; an optional integer before a task sets its run
434  // count (N>0: run N times, 0: run until a fixed point). Default: 1.
435  std::vector<std::pair<std::string, casadi_int> > tasks;
436  casadi_int count = 1;
437  bool have_count = false;
438  for (size_t i=1; i<pass.size(); ++i) {
439  if (pass[i].is_int()) {
440  count = pass[i].to_int();
441  have_count = true;
442  } else {
443  tasks.push_back({pass[i].to_string(), count});
444  count = 1;
445  have_count = false;
446  }
447  }
448  casadi_assert(!have_count,
449  "transform 'simplify': trailing run count with no following task");
450  f = f->simplify_passes(tasks);
451  } else if (verb=="expand") {
452  casadi_assert(pass.size()==1, "transform: 'expand' pass takes no arguments");
453  f = f.expand();
454  } else if (verb=="external") {
455  casadi_assert(pass.size()>=3 && pass.size()<=4,
456  "transform: 'external' pass must be {\"external\", library, operation[, opts]}");
457  std::string lib = pass[1].to_string();
458  std::string op = pass[2].to_string();
459  Dict eopts = pass.size()==4 ? pass[3].to_dict() : Dict();
460  f = external_transform(lib, op, f, eopts);
461  } else {
462  casadi_error("transform: unknown pass verb '" + verb + "'");
463  }
464  if (verbose) {
465  uout() << " after " << transform_passes_str({pass}) << ": "
466  << transform_stats(f) << std::endl;
467  }
468  }
469 
470  // Optionally rename the result (type-preserving for SX/MX functions)
471  if (!fname.empty() && fname!=f.name()) {
472  Dict ropts{{"allow_free", true}, {"allow_duplicate_io_names", true}};
473  std::vector<std::string> ni = f.name_in(), no = f.name_out();
474  if (f.is_a("SXFunction", true)) {
475  std::vector<SX> arg = f.sx_in();
476  f = Function(fname, arg, f(arg), ni, no, ropts);
477  } else {
478  std::vector<MX> arg = f.mx_in();
479  f = Function(fname, arg, f(arg), ni, no, ropts);
480  }
481  }
482  return f;
483  } catch(std::exception& e) {
484  THROW_ERROR("transform", e.what());
485  }
486  }
487 
489  Function ret;
490  ret.own(node);
491  return ret;
492  }
493 
495  Function ret = create(node);
496  ret->construct(opts);
497  return ret;
498  }
499 
501  casadi_assert_dev(!is_null());
502  return get();
503  }
504 
506  return static_cast<FunctionInternal*>(SharedObject::get());
507  }
508 
509  void Function::call(const std::vector<DM> &arg, std::vector<DM> &res,
510  bool always_inline, bool never_inline) const {
511  try {
512  (*this)->call(arg, res, always_inline, never_inline);
513  } catch(std::exception& e) {
514  THROW_ERROR("call", e.what());
515  }
516  }
517 
518  void Function::call(const std::vector<SX> &arg, std::vector<SX>& res,
519  bool always_inline, bool never_inline) const {
520  try {
521  (*this)->call(arg, res, always_inline, never_inline);
522  } catch(std::exception& e) {
523  THROW_ERROR("call", e.what());
524  }
525  }
526 
527  void Function::call(const std::vector<MX> &arg, std::vector<MX>& res,
528  bool always_inline, bool never_inline) const {
529  try {
530  (*this)->call(arg, res, always_inline, never_inline);
531  } catch(std::exception& e) {
532  THROW_ERROR("call", e.what());
533  }
534  }
535 
536  std::vector<const double*> Function::buf_in(Function::VecArg arg) const {
537  casadi_assert_dev(arg.size()==n_in());
538  auto arg_it=arg.begin();
539  std::vector<const double*> buf_arg(sz_arg());
540  for (casadi_uint i=0; i<arg.size(); ++i) {
541  casadi_assert_dev(arg_it->size()==nnz_in(i));
542  buf_arg[i] = get_ptr(*arg_it++);
543  }
544  return buf_arg;
545  }
546 
547  std::vector<double*> Function::buf_out(Function::VecRes res) const {
548  res.resize(n_out());
549  auto res_it=res.begin();
550  std::vector<double*> buf_res(sz_res());
551  for (casadi_uint i=0; i<res.size(); ++i) {
552  res_it->resize(nnz_out(i));
553  buf_res[i] = get_ptr(*res_it++);
554  }
555  return buf_res;
556  }
557 
558  std::vector<double*> Function::buf_out(Function::VPrRes res) const {
559  casadi_assert_dev(res.size()==n_out());
560  auto res_it=res.begin();
561  std::vector<double*> buf_res(sz_res());
562  for (casadi_uint i=0; i<res.size(); ++i) {
563  casadi_assert_dev(*res_it!=0);
564  (*res_it)->resize(nnz_out(i));
565  buf_res[i] = get_ptr(**res_it++);
566  }
567  return buf_res;
568  }
569 
570  std::vector<const double*> Function::buf_in(Function::MapArg arg) const {
571  // Return value (RVO)
572  std::vector<const double*> ret(sz_arg(), nullptr);
573 
574  // Read inputs
575  for (auto i=arg.begin(); i!=arg.end(); ++i) {
576  casadi_int ind = index_in(i->first);
577  casadi_assert_dev(i->second.size()==nnz_in(ind));
578  ret[ind] = get_ptr(i->second);
579  }
580 
581  return ret;
582  }
583 
584  std::vector<double*> Function::buf_out(Function::MapRes res) const {
585  // Return value (RVO)
586  std::vector<double*> ret(sz_res(), nullptr);
587 
588  // Read outputs
589  for (auto i=res.begin(); i!=res.end(); ++i) {
590  casadi_int ind = index_out(i->first);
591  i->second.resize(nnz_out(ind));
592  ret[ind] = get_ptr(i->second);
593  }
594 
595  return ret;
596  }
597 
598  std::vector<double*> Function::buf_out(Function::MPrRes res) const {
599  // Return value (RVO)
600  std::vector<double*> ret(sz_res(), nullptr);
601 
602  // Read outputs
603  for (auto i=res.begin(); i!=res.end(); ++i) {
604  casadi_int ind = index_out(i->first);
605  casadi_assert_dev(i->second!=0);
606  i->second->resize(nnz_out(ind));
607  ret[ind] = get_ptr(*i->second);
608  }
609 
610  return ret;
611  }
612 
613  template<typename D>
614  void Function::call_gen(std::vector<const D*> arg, std::vector<D*> res) const {
615  // Input buffer
616  casadi_assert_dev(arg.size()>=n_in());
617  arg.resize(sz_arg());
618 
619  // Output buffer
620  casadi_assert_dev(res.size()>=n_out());
621  res.resize(sz_res());
622 
623  // Work vectors
624  std::vector<casadi_int> iw(sz_iw());
625  std::vector<D> w(sz_w());
626 
627  // Evaluate memoryless
628  (*this)(get_ptr(arg), get_ptr(res), get_ptr(iw), get_ptr(w), 0);
629  }
630 
631 
632  void Function::operator()(std::vector<const double*> arg, std::vector<double*> res) const {
633  call_gen(arg, res);
634  }
635 
636  void Function::operator()(std::vector<const bvec_t*> arg, std::vector<bvec_t*> res) const {
637  call_gen(arg, res);
638  }
639 
640  void Function::operator()(std::vector<const SXElem*> arg, std::vector<SXElem*> res) const {
641  call_gen(arg, res);
642  }
643 
644  int Function::rev(std::vector<bvec_t*> arg, std::vector<bvec_t*> res) const {
645  // Input buffer
646  casadi_assert_dev(arg.size()>=n_in());
647  arg.resize(sz_arg());
648 
649  // Output buffer
650  casadi_assert_dev(res.size()>=n_out());
651  res.resize(sz_res());
652 
653  // Work vectors
654  std::vector<casadi_int> iw(sz_iw());
655  std::vector<bvec_t> w(sz_w());
656 
657  // Evaluate memoryless
658  return rev(get_ptr(arg), get_ptr(res), get_ptr(iw), get_ptr(w), 0);
659  }
660 
661  Function Function::fold(casadi_int N, const Dict& opts) const {
662  Function base = mapaccum(N, opts);
663  std::vector<MX> base_in = base.mx_in();
664  std::vector<MX> out = base(base_in);
665  out[0] = out[0](Slice(), range((N-1)*size2_out(0), N*size2_out(0))); // NOLINT
666  return Function("fold_"+name(), base_in, out, name_in(), name_out(), opts);
667  }
668  Function Function::mapaccum(casadi_int N, const Dict& opts) const {
669  return mapaccum("mapaccum_"+name(), N, opts);
670  }
671  Function Function::mapaccum(const std::string& name, casadi_int N, const Dict& opts) const {
672  return mapaccum(name, N, 1, opts);
673  }
674  Function Function::mapaccum(const std::string& name, casadi_int N, casadi_int n_accum,
675  const Dict& opts) const {
676  Dict options = opts;
677 
678  // Default base
679  casadi_int base = 10;
680  auto it = options.find("base");
681  if (it!=options.end()) {
682  base = it->second;
683  options.erase(it);
684  }
685 
686  casadi_assert(N>0, "mapaccum: N must be positive");
687 
688  if (base==-1)
689  return mapaccum(name, std::vector<Function>(N, *this), n_accum, options);
690  casadi_assert(base>=2, "mapaccum: base must be positive");
691 
692  // Decompose N into
693  std::vector<Function> chain;
694  Function c = *this;
695  while (N!=0) {
696  casadi_int r = N % base;
697  chain.insert(chain.end(), r, c);
698  N = (N-r)/base;
699  c = c.mapaccum(c.name()+"_acc"+str(base), std::vector<Function>(base, c), n_accum, options);
700  }
701  return mapaccum(name, chain, n_accum, options);
702  }
703 
704  Function Function::mapaccum(const std::string& name,
705  const std::vector<Function>& chain, casadi_int n_accum,
706  const Dict& opts) const {
707  // Shorthands
708  casadi_int n_in = this->n_in(), n_out = this->n_out();
709  // Consistency checks
710  casadi_assert(!chain.empty(), "mapaccum: chain must be non-empty");
711  casadi_assert(n_accum<=std::min(n_in, n_out), "mapaccum: too many accumulators");
712  // Quick return?
713  if (chain.size()==1) return chain[0];
714  // Get symbolic expressions for inputs and outputs
715  std::vector<MX> arg = mx_in();
716  std::vector<MX> res;
717  // Vectorized inputs and outputs
718  std::vector<std::vector<MX>> varg(n_in), vres(n_out);
719  for (casadi_int i=0; i<n_accum; ++i) varg[i].push_back(arg[i]);
720  // For each function call
721  for (const auto& f : chain) {
722 
723  // Stacked input expressions
724  for (casadi_int i=n_accum; i<n_in; ++i) {
725  arg[i] = MX::sym(name_in(i) + "_" + str(i), f.sparsity_in(i));
726  varg[i].push_back(arg[i]);
727  }
728 
729  // Call f
730  res = f(arg);
731  // Save output expressions
732  for (casadi_int i=0; i<n_out; ++i) vres[i].push_back(res[i]);
733  // Copy function output to input
734  std::copy_n(res.begin(), n_accum, arg.begin());
735  for (casadi_int i=0; i<n_accum; ++i) {
736  // Ony get last component (allows nested calls)
737  casadi_int ncol_out=f.size2_out(i), ncol_in=size2_in(i);
738  if (ncol_out>ncol_in) {
739  arg[i] = horzsplit(arg[i], {0, ncol_out-ncol_in, ncol_out}).back();
740  }
741  }
742  }
743  // Construct return
744  for (casadi_int i=0; i<n_in; ++i) arg[i] = horzcat(varg[i]);
745  for (casadi_int i=0; i<n_out; ++i) res[i] = horzcat(vres[i]);
746  return Function(name, arg, res, name_in(), name_out(), opts);
747  }
748 
749  Function Function::mapaccum(const std::string& name, casadi_int n,
750  const std::vector<casadi_int>& accum_in,
751  const std::vector<casadi_int>& accum_out,
752  const Dict& opts) const {
753  // Shorthands
754  casadi_int n_in = this->n_in(), n_out = this->n_out();
755  // Consistency checks
756  casadi_assert_dev(in_range(accum_in, n_in) && isUnique(accum_in));
757  casadi_assert_dev(in_range(accum_out, n_out) && isUnique(accum_out));
758  casadi_assert_dev(accum_in.size()==accum_out.size());
759  casadi_int n_accum=accum_in.size();
760 
761  // Quick return if no need to reorder
762  if (accum_in==range(n_accum) && accum_out==range(n_accum)) {
763  return mapaccum(name, n, n_accum, opts);
764  }
765 
766  // Need to do some reordering
767  std::vector<casadi_int> temp_in = complement(accum_in, n_in);
768  std::vector<casadi_int> order_in = accum_in;
769  order_in.insert(order_in.end(), temp_in.begin(), temp_in.end());
770  std::vector<casadi_int> temp_out = complement(accum_out, n_out);
771  std::vector<casadi_int> order_out = accum_out;
772  order_out.insert(order_out.end(), temp_out.begin(), temp_out.end());
773  Function ret = slice("slice_" + name, order_in, order_out);
774  ret = ret.mapaccum("mapacc_" + name, n, n_accum, opts);
775  return ret.slice(name, lookupvector(order_in, n_in),
776  lookupvector(order_out, n_out), opts);
777  }
778 
779  Function Function::mapaccum(const std::string& name, casadi_int n,
780  const std::vector<std::string>& accum_in,
781  const std::vector<std::string>& accum_out,
782  const Dict& opts) const {
783  std::vector<casadi_int> accum_in_num, accum_out_num;
784  for (const std::string& s : accum_in) accum_in_num.push_back(index_in(s));
785  for (const std::string& s : accum_out) accum_out_num.push_back(index_out(s));
786  return mapaccum(name, n, accum_in_num, accum_out_num, opts);
787  }
788 
789  Function Function::map(casadi_int n,
790  const std::vector<bool>& reduce_in,
791  const std::vector<bool>& reduce_out,
792  const Dict& opts) const {
793  return MapSum::create("mapsum_" + str(n) + "_" + name(), "serial",
794  *this, n, reduce_in, reduce_out, opts);
795  }
796 
797  Function Function::map(const std::string& name, const std::string& parallelization, casadi_int n,
798  const std::vector<casadi_int>& reduce_in, const std::vector<casadi_int>& reduce_out,
799  const Dict& opts) const {
800  // Wrap in an MXFunction
801  Function f = map(n, parallelization);
802  // Start with the fully mapped inputs
803  std::vector<MX> arg = f.mx_in();
804  std::vector<MX> f_arg = arg;
805  // Replace reduced inputs
806  for (casadi_int i : reduce_in) {
807  arg[i] = mx_in(i);
808  f_arg[i] = repmat(arg[i], 1, n);
809  }
810  // Get fully mapped outputs
811  std::vector<MX> res = f(f_arg);
812  // Replace reduced outputs
813  for (casadi_int i : reduce_out) {
814  res[i] = repsum(res[i], 1, n);
815  }
816  // Construct return
817  return Function(name, arg, res, name_in(), name_out());
818  }
819 
820  Function Function::map(const std::string& name, const std::string& parallelization, casadi_int n,
821  const std::vector<std::string>& reduce_in, const std::vector<std::string>& reduce_out,
822  const Dict& opts) const {
823  std::vector<casadi_int> reduce_in_num, reduce_out_num;
824  for (const std::string& s : reduce_in) reduce_in_num.push_back(index_in(s));
825  for (const std::string& s : reduce_out) reduce_out_num.push_back(index_out(s));
826  return map(name, parallelization, n, reduce_in_num, reduce_out_num, opts);
827  }
828 
829  Function
830  Function::map(casadi_int n, const std::string& parallelization,
831  casadi_int max_num_threads) const {
832  casadi_assert(max_num_threads>=1, "max_num_threads invalid.");
833  // No need for logic when we are not saturating the limit
834  if (n<=max_num_threads) return map(n, parallelization);
835 
836  // Floored division
837  casadi_int d = n/max_num_threads;
838  if (d*max_num_threads==n) {
839  // Easy when n is divisable by max_num_threads
840  return map(d, "serial").map(max_num_threads, parallelization);
841  } else {
842  // Create a base map that computes a bit too much
843  Function base = map(d+1, "serial").map(max_num_threads, parallelization);
844  std::vector<MX> ret_in, base_in;
845  casadi_int rem = (d+1)*max_num_threads-n;
846  for (casadi_int i=0;i<n_in();++i) {
847  MX arg = MX::sym("arg", repmat(sparsity_in(i), 1, n));
848  ret_in.push_back(arg);
849  MX last_arg = arg(Slice(), range((n-1)*size2_in(i), n*size2_in(i))); // NOLINT
850  base_in.push_back(horzcat(arg, repmat(last_arg, 1, rem)));
851  }
852  std::vector<MX> ret_out = base(base_in);
853  for (casadi_int i=0;i<n_out();++i) {
854  ret_out[i] = horzsplit(ret_out[i], {0, n*size2_out(i), ret_out[i].size2()})[0];
855  }
856  return Function("helper", ret_in, ret_out, name_in(), name_out());
857  }
858  }
859 
860  Function
861  Function::map(casadi_int n, const std::string& parallelization) const {
862  // Make sure not degenerate
863  casadi_assert(n>0, "Degenerate map operation");
864  // Quick return if possible
865  if (n==1) return *this;
866  // Unroll?
867  if (parallelization=="unroll" || parallelization=="inline") {
868  // Construct symbolic inputs
869  std::vector<MX> arg(n_in());
870  std::vector<std::vector<MX>> v(n, arg);
871  std::vector<MX> tmp(n);
872  for (casadi_int i=0; i<arg.size(); ++i) {
873  for (casadi_int k=0; k<n; ++k) {
874  tmp[k] = v[k][i] = MX::sym(name_in(i)+"_"+str(k), sparsity_in(i));
875  }
876  arg[i] = horzcat(tmp);
877  }
878  // Evaluate
879  if (parallelization=="unroll") {
880  for (auto&& w : v) w = (*this)(w);
881  } else {
882  for (auto&& w : v) call(std::vector<MX>(w), w, !is_a("SXFunction"), false);
883  }
884  // Gather outputs
885  std::vector<MX> res(n_out());
886  for (casadi_int i=0; i<res.size(); ++i) {
887  for (casadi_int k=0; k<n; ++k) tmp[k] = v[k][i];
888  res[i] = horzcat(tmp);
889  }
890  // Construct function
891  return Function(name() + "_" + str(n), arg, res, name_in(), name_out());
892  } else {
893  // Generate/retrieve potentially cached map
894  return (*this)->map(n, parallelization);
895  }
896  }
897 
899  slice(const std::string& name, const std::vector<casadi_int>& order_in,
900  const std::vector<casadi_int>& order_out, const Dict& opts) const {
901  try {
902  return (*this)->slice(name, order_in, order_out, opts);
903  } catch(std::exception& e) {
904  THROW_ERROR("slice", e.what());
905  }
906  }
907 
908  std::vector<MX> Function::mapsum(const std::vector< MX > &x,
909  const std::string& parallelization) const {
910  try {
911  return (*this)->mapsum_mx(x, parallelization);
912  } catch(std::exception& e) {
913  THROW_ERROR("mapsum", e.what());
914  }
915  }
916 
917  Function Function::conditional(const std::string& name, const std::vector<Function>& f,
918  const Function& f_def, const Dict& opts) {
919  try {
920  return create(new Switch(name, f, f_def), opts);
921  } catch(std::exception& e) {
922  THROW_ERROR_NOOBJ("conditional", e.what(), "Switch");
923  }
924  }
925 
926  Function Function::conditional(const std::string& name,
927  const Function& f, const Dict& opts) {
928  try {
929  // Create a dummy function with the same signature as f
930  std::vector<MX> dummy_in = f.mx_in();
931  std::vector<MX> dummy_out(f.n_out());
932  for (casadi_int i = 0; i < dummy_out.size(); ++i) {
933  dummy_out.at(i) = MX::zeros(f.sparsity_out(i));
934  }
935  Function dummy("dummy_" + f.name(), dummy_in, dummy_out, f.name_in(), f.name_out());
936  // Form a conditional call
937  return if_else(name, f, dummy, opts);
938  } catch(std::exception& e) {
939  THROW_ERROR_NOOBJ("conditional", e.what(), "Switch");
940  }
941  }
942 
943  Function Function::bspline(const std::string &name,
944  const std::vector< std::vector<double> >& knots,
945  const std::vector<double>& coeffs, const std::vector<casadi_int>& degree,
946  casadi_int m, const Dict& opts) {
947  try {
948  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
949  "must match knot list length (" + str(knots.size()) + ").");
950  MX x = MX::sym("x", degree.size());
951  std::vector<std::string> lookup_mode;
952  Dict opts_remainder = extract_from_dict(opts, "lookup_mode", lookup_mode);
953  Dict opts_bspline;
954  opts_bspline["lookup_mode"] = lookup_mode;
955  MX y = MX::bspline(x, DM(coeffs), knots, degree, m, opts_bspline);
956  return Function(name, {x}, {y}, opts_remainder);
957  } catch(std::exception& e) {
958  THROW_ERROR_NOOBJ("bspline", e.what(), "BSpline");
959  }
960  }
961 
962  Function Function::if_else(const std::string& name, const Function& f_true,
963  const Function& f_false, const Dict& opts) {
964  try {
965  return create(new Switch(name, std::vector<Function>(1, f_false), f_true), opts);
966  } catch(std::exception& e) {
967  THROW_ERROR_NOOBJ("if_else", e.what(), "Switch");
968  }
969  }
970 
971  casadi_int Function::n_in() const {
972  return (*this)->n_in_;
973  }
974 
975  casadi_int Function::n_out() const {
976  return (*this)->n_out_;
977  }
978 
979  casadi_int Function::size1_in(casadi_int ind) const {
980  return (*this)->size1_in(ind);
981  }
982 
983  casadi_int Function::size2_in(casadi_int ind) const {
984  return (*this)->size2_in(ind);
985  }
986 
987  casadi_int Function::size1_out(casadi_int ind) const {
988  return (*this)->size1_out(ind);
989  }
990 
991  casadi_int Function::size2_out(casadi_int ind) const {
992  return (*this)->size2_out(ind);
993  }
994 
995  std::pair<casadi_int, casadi_int> Function::size_in(casadi_int ind) const {
996  return (*this)->size_in(ind);
997  }
998 
999  std::pair<casadi_int, casadi_int> Function::size_out(casadi_int ind) const {
1000  return (*this)->size_out(ind);
1001  }
1002 
1003  casadi_int Function::nnz_in() const {
1004  return (*this)->nnz_in();
1005  }
1006 
1007  casadi_int Function::nnz_out() const {
1008  return (*this)->nnz_out();
1009  }
1010 
1011  casadi_int Function::numel_in() const {
1012  return (*this)->numel_in();
1013  }
1014 
1015  casadi_int Function::numel_out() const {
1016  return (*this)->numel_out();
1017  }
1018 
1019  casadi_int Function::nnz_in(casadi_int ind) const {
1020  return (*this)->nnz_in(ind);
1021  }
1022 
1023  casadi_int Function::nnz_out(casadi_int ind) const {
1024  return (*this)->nnz_out(ind);
1025  }
1026 
1027  casadi_int Function::numel_in(casadi_int ind) const {
1028  return (*this)->numel_in(ind);
1029  }
1030 
1031  casadi_int Function::numel_out(casadi_int ind) const {
1032  return (*this)->numel_out(ind);
1033  }
1034 
1035  bool Function::uses_output() const {
1036  return (*this)->uses_output();
1037  }
1038 
1039 #ifdef WITH_DEPRECATED_FEATURES
1040  Function Function::jacobian_old(casadi_int iind, casadi_int oind) const {
1041  // Redirect to factory class
1042  std::vector<std::string> s_in = name_in();
1043  std::vector<std::string> s_out = name_out();
1044  s_out.insert(s_out.begin(), "jac:" + name_out(oind) + ":" + name_in(iind));
1045  return factory(name() + "_jac", s_in, s_out);
1046  }
1047 
1048  Function Function::hessian_old(casadi_int iind, casadi_int oind) const {
1049  // Redirect to factory class
1050  std::vector<std::string> s_in = name_in();
1051  std::vector<std::string> s_out = name_out();
1052  s_out.insert(s_out.begin(), "grad:" + name_out(oind) + ":" + name_in(iind));
1053  s_out.insert(s_out.begin(),
1054  "hess:" + name_out(oind) + ":" + name_in(iind) + ":" + name_in(iind));
1055  return factory(name() + "_hess", s_in, s_out);
1056  }
1057 
1059  sparsity_jac(casadi_int iind, casadi_int oind, bool compact, bool symmetric) const {
1060  try {
1061  return (*this)->jac_sparsity(oind, iind, compact, symmetric);
1062  } catch(std::exception& e) {
1063  THROW_ERROR("sparsity_jac", e.what());
1064  }
1065  }
1066 #endif // WITH_DEPRECATED_FEATURES
1067 
1069  try {
1070  return (*this)->jacobian();
1071  } catch(std::exception& e) {
1072  THROW_ERROR("jacobian", e.what());
1073  }
1074  }
1075 
1077  return dynamic_cast<const FunctionInternal*>(ptr)!=nullptr;
1078  }
1079 
1080  Dict Function::stats(int mem) const {
1081  if (!(*this)->has_memory(mem)) {
1082  THROW_ERROR("stats",
1083  "No stats available: Function/solver was not yet numerically evaluated.");
1084  }
1085  try {
1086  return (*this)->get_stats(memory(mem));
1087  } catch(std::exception& e) {
1088  THROW_ERROR("stats", e.what());
1089  }
1090  }
1091 
1092  const std::vector<Sparsity>& Function::jac_sparsity(bool compact) const {
1093  // Make sure all are calculated
1094  for (casadi_int oind = 0; oind < n_out(); ++oind) {
1095  for (casadi_int iind = 0; iind < n_in(); ++iind) {
1096  (void)jac_sparsity(oind, iind, compact);
1097  }
1098  }
1099  // Return reference to internal cache
1100  return (*this)->jac_sparsity_[compact];
1101  }
1102 
1103  Sparsity Function::jac_sparsity(casadi_int oind, casadi_int iind, bool compact) const {
1104  try {
1105  bool symm = (*this)->jac_is_symm(oind, iind);
1106  symm = symm && sparsity_out(oind).is_dense();
1107  return (*this)->jac_sparsity(oind, iind, compact, symm);
1108  } catch(std::exception& e) {
1109  THROW_ERROR("jac_sparsity", e.what());
1110  }
1111  }
1112 
1113  const std::vector<std::string>& Function::name_in() const {
1114  return (*this)->name_in_;
1115  }
1116 
1117  const std::vector<std::string>& Function::name_out() const {
1118  return (*this)->name_out_;
1119  }
1120 
1121  casadi_int Function::index_in(const std::string &name) const {
1122  try {
1123  return (*this)->index_in(name);
1124  } catch(std::exception& e) {
1125  THROW_ERROR("index_in", e.what());
1126  }
1127  }
1128 
1129  casadi_int Function::index_out(const std::string &name) const {
1130  try {
1131  return (*this)->index_out(name);
1132  } catch(std::exception& e) {
1133  THROW_ERROR("index_out", e.what());
1134  }
1135  }
1136 
1137  bool Function::has_in(const std::string &name) const {
1138  for (const std::string& s : (*this)->name_in_) {
1139  if (s==name) return true;
1140  }
1141  return false;
1142  }
1143 
1144  bool Function::has_out(const std::string &name) const {
1145  for (const std::string& s : (*this)->name_out_) {
1146  if (s==name) return true;
1147  }
1148  return false;
1149  }
1150 
1151  const std::string& Function::name_in(casadi_int ind) const {
1152  try {
1153  return (*this)->name_in_.at(ind);
1154  } catch(std::exception& e) {
1155  THROW_ERROR("name_in", e.what());
1156  }
1157  }
1158 
1159  const std::string& Function::name_out(casadi_int ind) const {
1160  try {
1161  return (*this)->name_out_.at(ind);
1162  } catch(std::exception& e) {
1163  THROW_ERROR("name_out", e.what());
1164  }
1165  }
1166 
1167  const Sparsity& Function::sparsity_in(casadi_int ind) const {
1168  try {
1169  return (*this)->sparsity_in_.at(ind);
1170  } catch(std::exception& e) {
1171  THROW_ERROR("sparsity_in", e.what());
1172  }
1173  }
1174 
1175  const Sparsity& Function::sparsity_in(const std::string &iname) const {
1176  try {
1177  return sparsity_in(index_in(iname));
1178  } catch(std::exception& e) {
1179  THROW_ERROR("sparsity_in", e.what());
1180  }
1181  }
1182 
1183  const Sparsity& Function::sparsity_out(casadi_int ind) const {
1184  try {
1185  return (*this)->sparsity_out_.at(ind);
1186  } catch(std::exception& e) {
1187  THROW_ERROR("sparsity_out", e.what());
1188  }
1189  }
1190 
1191  const Sparsity& Function::sparsity_out(const std::string &iname) const {
1192  try {
1193  return sparsity_out(index_out(iname));
1194  } catch(std::exception& e) {
1195  THROW_ERROR("sparsity_out", e.what());
1196  }
1197  }
1198 
1199  bool Function::is_diff_in(casadi_int ind) const {
1200  try {
1201  return (*this)->is_diff_in_.at(ind);
1202  } catch(std::exception& e) {
1203  THROW_ERROR("is_diff_in", e.what());
1204  }
1205  }
1206 
1207  bool Function::is_diff_out(casadi_int ind) const {
1208  try {
1209  return (*this)->is_diff_out_.at(ind);
1210  } catch(std::exception& e) {
1211  THROW_ERROR("is_diff_out", e.what());
1212  }
1213  }
1214 
1215  std::vector<bool> Function::is_diff_in() const {
1216  try {
1217  return (*this)->is_diff_in_;
1218  } catch(std::exception& e) {
1219  THROW_ERROR("is_diff_in", e.what());
1220  }
1221  }
1222 
1223  std::vector<bool> Function::is_diff_out() const {
1224  try {
1225  return (*this)->is_diff_out_;
1226  } catch(std::exception& e) {
1227  THROW_ERROR("is_diff_out", e.what());
1228  }
1229  }
1230 
1231  void Function::sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const {
1232  (*this)->sz_work(sz_arg, sz_res, sz_iw, sz_w);
1233  }
1234 
1235  size_t Function::sz_arg() const { return (*this)->sz_arg();}
1236 
1237  size_t Function::sz_res() const { return (*this)->sz_res();}
1238 
1239  size_t Function::sz_iw() const { return (*this)->sz_iw();}
1240 
1241  size_t Function::sz_w() const { return (*this)->sz_w();}
1242 
1243  int Function::operator()(const bvec_t** arg, bvec_t** res,
1244  casadi_int* iw, bvec_t* w, int mem) const {
1245  try {
1246  return (*this)->sp_forward(arg, res, iw, w, memory(mem));
1247  } catch(std::exception& e) {
1248  THROW_ERROR("operator()", e.what());
1249  }
1250  }
1251 
1252  int Function::rev(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, int mem) const {
1253  try {
1254  return (*this)->sp_reverse(arg, res, iw, w, memory(mem));
1255  } catch(std::exception& e) {
1256  THROW_ERROR("rev", e.what());
1257  }
1258  }
1259 
1260  int Function::eval_activity(const bvec_t** arg, bvec_t** res,
1261  casadi_int* iw, bvec_t* w, int mem) const {
1262  try {
1263  return (*this)->eval_activity(arg, res, iw, w, memory(mem));
1264  } catch(std::exception& e) {
1265  THROW_ERROR("eval_activity", e.what());
1266  }
1267  }
1268 
1269  std::vector<bool> Function::activity(const std::vector<bool>& arg) const {
1270  casadi_assert(arg.size()==static_cast<size_t>(nnz_in()),
1271  "activity: expected mask of size nnz_in()=" + str(nnz_in())
1272  + ", got " + str(arg.size()) + ".");
1273 
1274  // bvec buffers for the concatenated input/output nonzeros
1275  std::vector<bvec_t> in_buf(nnz_in()), out_buf(nnz_out(), 0);
1276  for (casadi_int k=0; k<nnz_in(); ++k) in_buf[k] = arg[k] ? ~static_cast<bvec_t>(0) : 0;
1277 
1278  // Per-input/output pointers into the buffers
1279  std::vector<const bvec_t*> argp(sz_arg(), nullptr);
1280  std::vector<bvec_t*> resp(sz_res(), nullptr);
1281  casadi_int off = 0;
1282  for (casadi_int i=0; i<n_in(); ++i) { argp[i] = get_ptr(in_buf)+off; off += nnz_in(i); }
1283  off = 0;
1284  for (casadi_int i=0; i<n_out(); ++i) { resp[i] = get_ptr(out_buf)+off; off += nnz_out(i); }
1285 
1286  // Work vectors
1287  std::vector<casadi_int> iw(sz_iw());
1288  std::vector<bvec_t> w(sz_w());
1289 
1290  eval_activity(get_ptr(argp), get_ptr(resp), get_ptr(iw), get_ptr(w));
1291 
1292  std::vector<bool> ret(nnz_out());
1293  for (casadi_int k=0; k<nnz_out(); ++k) ret[k] = out_buf[k]!=0;
1294  return ret;
1295  }
1296 
1297  void Function::set_work(const double**& arg, double**& res, casadi_int*& iw, double*& w,
1298  int mem) const {
1299  try {
1300  (*this)->set_work(memory(mem), arg, res, iw, w);
1301  } catch(std::exception& e) {
1302  THROW_ERROR("set_work", e.what());
1303  }
1304  }
1305 
1306  void Function::set_temp(const double** arg, double** res, casadi_int* iw, double* w,
1307  int mem) const {
1308  try {
1309  (*this)->set_temp(memory(mem), arg, res, iw, w);
1310  } catch(std::exception& e) {
1311  THROW_ERROR("set_temp", e.what());
1312  }
1313  }
1314 
1315  void Function::setup(const double** arg, double** res, casadi_int* iw, double* w,
1316  int mem) const {
1317  try {
1318  (*this)->setup(memory(mem), arg, res, iw, w);
1319  } catch(std::exception& e) {
1320  THROW_ERROR("setup", e.what());
1321  }
1322  }
1323 
1324  Function Function::forward(casadi_int nfwd) const {
1325  try {
1326  return (*this)->forward(nfwd);
1327  } catch(std::exception& e) {
1328  THROW_ERROR("forward", e.what());
1329  }
1330  }
1331 
1332  Function Function::reverse(casadi_int nadj) const {
1333  try {
1334  return (*this)->reverse(nadj);
1335  } catch(std::exception& e) {
1336  THROW_ERROR("reverse", e.what());
1337  }
1338  }
1339 
1340  void Function::print_dimensions(std::ostream &stream) const {
1341  (*this)->print_dimensions(stream);
1342  }
1343 
1344  void Function::print_options(std::ostream &stream) const {
1345  (*this)->print_options(stream);
1346  }
1347 
1348  void Function::print_option(const std::string &name, std::ostream &stream) const {
1349  (*this)->print_option(name, stream);
1350  }
1351 
1352  bool Function::has_option(const std::string &option_name) const {
1353  try {
1354  return (*this)->has_option(option_name);
1355  } catch(std::exception& e) {
1356  THROW_ERROR("has_option", e.what());
1357  return false; // never reached
1358  }
1359  }
1360 
1361  void Function::change_option(const std::string& option_name, const GenericType& option_value) {
1362  try {
1363  // Assert existance
1364  if (!has_option(option_name))
1365  casadi_error("Option '" + option_name + "' does not exist");
1366  // Call internal class
1367  (*this)->change_option(option_name, option_value);
1368  } catch(std::exception& e) {
1369  THROW_ERROR("change_option", e.what());
1370  }
1371  }
1372 
1374  try {
1375  (*this)->reset_dump_count();
1376  } catch(std::exception& e) {
1377  THROW_ERROR("reset_dump_count", e.what());
1378  }
1379  }
1380 
1381 
1382  std::vector<std::string> Function::get_free() const {
1383  return (*this)->get_free();
1384  }
1385 
1386  std::string Function::generate(const Dict& opts) const {
1387  return generate(name(), opts);
1388  }
1389 
1390  std::string Function::generate(const std::string& fname, const Dict& opts) const {
1391  CodeGenerator gen(fname, opts);
1392  gen.add(*this);
1393  return gen.generate();
1394  }
1395 
1396  std::string Function::generate_dependencies(const std::string& fname, const Dict& opts) const {
1397  return (*this)->generate_dependencies(fname, opts);
1398  }
1399 
1400  void Function::generate_in(const std::string& fname, const std::vector<DM>& arg) {
1401  std::vector<double> d = nz_from_in(arg);
1402 
1403  // Set up output stream
1404  auto of_ptr = Filesystem::ofstream_ptr(fname);
1405  std::ostream& of = *of_ptr;
1406  normalized_setup(of);
1407 
1408  // Encode each output
1409  for (casadi_int i=0; i<d.size(); ++i) {
1410  normalized_out(of, d[i]);
1411  of << std::endl;
1412  }
1413  }
1414 
1415  void Function::generate_out(const std::string& fname, const std::vector<DM>& res) {
1416  std::vector<double> d = nz_from_out(res);
1417 
1418  // Set up output stream
1419  auto of_ptr = Filesystem::ofstream_ptr(fname);
1420  std::ostream& of = *of_ptr;
1421  normalized_setup(of);
1422 
1423  // Encode each output
1424  for (casadi_int i=0; i<d.size(); ++i) {
1425  normalized_out(of, d[i]);
1426  of << std::endl;
1427  }
1428  }
1429 
1430  std::vector<DM> Function::generate_in(const std::string& fname) {
1431  DM data = DM::from_file(fname, "txt");
1432  // Empty files are okay
1433  if (data.is_empty(true)) data = DM(0, 1);
1434  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1435  casadi_assert(data.numel()==nnz_in(),
1436  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1437  + ", while size " + str(nnz_in()) + " was expected.");
1438 
1439  return nz_to_in(data.nonzeros());
1440  }
1441 
1442  std::vector<DM> Function::generate_out(const std::string& fname) {
1443  DM data = DM::from_file(fname, "txt");
1444  // Empty files are okay
1445  if (data.is_empty(true)) data = DM(0, 1);
1446  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1447  casadi_assert(data.numel()==nnz_out(),
1448  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1449  + ", while size " + str(nnz_out()) + " was expected.");
1450 
1451  return nz_to_out(data.nonzeros());
1452  }
1453 
1454  void Function::export_code(const std::string& lang,
1455  std::ostream &stream, const Dict& options) const {
1456  (*this)->export_code(lang, stream, options);
1457  }
1458 
1459  void Function::export_code(const std::string& lang,
1460  const std::string &fname, const Dict& options) const {
1461  auto stream_ptr = Filesystem::ofstream_ptr(fname);
1462  (*this)->export_code(lang, *stream_ptr, options);
1463  }
1464 
1465 
1466  void Function::save(const std::string &fname, const Dict& opts) const {
1467  FileSerializer fs(fname, opts);
1468  fs.pack(*this);
1469  }
1470 
1471  std::string Function::serialize(const Dict& opts) const {
1472  std::stringstream ss;
1473  serialize(ss, opts);
1474  return ss.str();
1475  }
1476 
1477  void Function::serialize(std::ostream &stream, const Dict& opts) const {
1478  SerializingStream s(stream, opts);
1479  serialize(s);
1480  }
1481 
1483  if (is_null()) {
1484  s.pack("Function::null", true);
1485  } else {
1486  s.pack("Function::null", false);
1487  (*this)->serialize(s);
1488  }
1489  }
1490 
1492  bool is_null;
1493  s.unpack("Function::null", is_null);
1494  if (is_null) return Function();
1496  }
1497 
1498  std::string Function::export_code(const std::string& lang, const Dict& options) const {
1499  std::stringstream ss;
1500  (*this)->export_code(lang, ss, options);
1501  return ss.str();
1502  }
1503 
1504  const std::string& Function::name() const {
1505  if (is_null()) {
1506  static std::string null = "null";
1507  return null;
1508  } else {
1509  return (*this)->name_;
1510  }
1511  }
1512 
1513  bool Function::check_name(const std::string& name) {
1514  // Check if empty
1515  if (name.empty()) return false;
1516 
1517  // Check if keyword
1518  for (const char* kw : {"null", "jac", "hess"}) {
1519  if (name==kw) return false;
1520  }
1521 
1522  // Make sure that the first character is a letter
1523  auto it=name.begin();
1524  if (!std::isalpha(*it++)) return false;
1525 
1526  // Check remain_ing characters
1527  for (; it!=name.end(); ++it) {
1528  if (*it=='_') {
1529  // Make sure that the next character isn't also an underscore
1530  if (it+1!=name.end() && *(it+1)=='_') return false;
1531  } else {
1532  // Make sure alphanumeric
1533  if (!std::isalnum(*it)) return false;
1534  }
1535  }
1536 
1537  // Valid function name if reached this point
1538  return true;
1539  }
1540 
1541  Function Function::deserialize(std::istream& stream) {
1542  DeserializingStream s(stream);
1543  return deserialize(s);
1544  }
1545 
1546  Function Function::load(const std::string& filename) {
1548  auto t = fs.pop_type();
1549  if (t==SerializerBase::SerializationType::SERIALIZED_FUNCTION) {
1550  return fs.blind_unpack_function();
1551  } else {
1552  casadi_error("File is not loadable with 'load'. Use 'FileDeserializer' instead.");
1553  }
1554  }
1555 
1556  Function Function::deserialize(const std::string& s) {
1557  std::stringstream ss;
1558  ss << s;
1559  return deserialize(ss);
1560  }
1561 
1562  std::string Function::fix_name(const std::string& name) {
1563  // Quick return if already valid name
1564  if (check_name(name)) return name;
1565 
1566  // If empty, name it "unnamed"
1567  if (name.empty()) return "unnamed";
1568 
1569  // Construct a sane name
1570  std::stringstream ss;
1571 
1572  // If the first character isn't a character, prepend an "a"
1573  if (!std::isalpha(name.front())) ss << "a";
1574 
1575  // Treat other characters
1576  bool previous_is_underscore = false;
1577  for (char c : name) {
1578  if (std::isalnum(c)) {
1579  // Alphanumeric characters
1580  ss << c;
1581  previous_is_underscore = false;
1582  } else if (!previous_is_underscore) {
1583  // Everything else becomes an underscore
1584  ss << '_';
1585  previous_is_underscore = true;
1586  }
1587  }
1588 
1589  // If name became a keyword, append 1
1590  for (const char* kw : {"null", "jac", "hess"}) {
1591  if (ss.str()==kw) ss << "1";
1592  }
1593 
1594  return ss.str();
1595  }
1596 
1597  std::vector<DM> Function::operator()(const std::vector<DM>& arg) const {
1598  std::vector<DM> res;
1599  call(arg, res);
1600  return res;
1601  }
1602 
1603  std::vector<SX> Function::operator()(const std::vector<SX>& arg) const {
1604  std::vector<SX> res;
1605  call(arg, res);
1606  return res;
1607  }
1608 
1609  std::vector<MX> Function::operator()(const std::vector<MX>& arg) const {
1610  std::vector<MX> res;
1611  call(arg, res);
1612  return res;
1613  }
1614 
1615  template<typename M>
1616  void Function::call_gen(const std::map<std::string, M>& arg, std::map<std::string, M>& res,
1617  bool always_inline, bool never_inline) const {
1618  // Convert to vector arguments
1619  std::vector<M> arg_v = (*this)->convert_arg(arg);
1620 
1621  // Make call
1622  std::vector<M> res_v;
1623  call(arg_v, res_v, always_inline, never_inline);
1624 
1625  // Save to map
1626  res.clear();
1627  for (casadi_int i=0; i<res_v.size(); ++i) {
1628  res[name_out(i)] = res_v[i];
1629  }
1630  }
1631 
1632  const DMDict Function::operator()(const DMDict& arg) const {
1633  DMDict res;
1634  call(arg, res);
1635  return res;
1636  }
1637 
1638  const SXDict Function::operator()(const SXDict& arg) const {
1639  SXDict res;
1640  call(arg, res);
1641  return res;
1642  }
1643 
1644  const MXDict Function::operator()(const MXDict& arg) const {
1645  MXDict res;
1646  call(arg, res);
1647  return res;
1648  }
1649 
1650  void Function::call(const DMDict& arg, DMDict& res,
1651  bool always_inline, bool never_inline) const {
1652  try {
1653  call_gen(arg, res, always_inline, never_inline);
1654  } catch(std::exception& e) {
1655  THROW_ERROR("call", e.what());
1656  }
1657  }
1658 
1659  void Function::call(const SXDict& arg, SXDict& res,
1660  bool always_inline, bool never_inline) const {
1661  try {
1662  call_gen(arg, res, always_inline, never_inline);
1663  } catch(std::exception& e) {
1664  THROW_ERROR("call", e.what());
1665  }
1666  }
1667 
1668  void Function::call(const MXDict& arg, MXDict& res,
1669  bool always_inline, bool never_inline) const {
1670  try {
1671  call_gen(arg, res, always_inline, never_inline);
1672  } catch(std::exception& e) {
1673  THROW_ERROR("call", e.what());
1674  }
1675  }
1676 
1677  double Function::default_in(casadi_int ind) const {
1678  return (*this)->get_default_in(ind);
1679  }
1680 
1681  double Function::max_in(casadi_int ind) const {
1682  return (*this)->get_max_in(ind);
1683  }
1684 
1685  double Function::min_in(casadi_int ind) const {
1686  return (*this)->get_min_in(ind);
1687  }
1688 
1689  std::vector<double> Function::nominal_in(casadi_int ind) const {
1690  return (*this)->get_nominal_in(ind);
1691  }
1692 
1693  std::vector<double> Function::nominal_out(casadi_int ind) const {
1694  return (*this)->get_nominal_out(ind);
1695  }
1696 
1697 #ifdef WITH_EXTRA_CHECKS
1698  // Initialize at zero depth
1699  thread_local casadi_int Function::call_depth_ = 0;
1700 #endif // WITH_EXTRA_CHECKS
1701 
1702  int Function::operator()(const double** arg, double** res,
1703  casadi_int* iw, double* w) const {
1704  scoped_checkout<Function> mem(*this);
1705  return operator()(arg, res, iw, w, mem);
1706  }
1707 
1708  int Function::operator()(const double** arg, double** res,
1709  casadi_int* iw, double* w, int mem) const {
1710  try {
1711 #ifdef WITH_EXTRA_CHECKS
1712  // Should never happen
1713  casadi_assert_dev(call_depth_>=0);
1714  call_depth_++;
1715  // For consistency check
1716  casadi_int depth = call_depth_;
1717 #endif // WITH_EXTRA_CHECKS
1718  int ret = (*this)->eval_gen(arg, res, iw, w, memory(mem), false, false);
1719 #ifdef WITH_EXTRA_CHECKS
1720  // Consitency check
1721  casadi_assert_dev(call_depth_==depth);
1722  call_depth_--;
1723 #endif // WITH_EXTRA_CHECKS
1724  return ret;
1725  } catch (KeyboardInterruptException& e) {
1726  (void)e; // unused
1727 #ifdef WITH_EXTRA_CHECKS
1728  call_depth_--;
1729 #endif // WITH_EXTRA_CHECKS
1730  throw;
1731  } catch(std::exception& e) {
1732 #ifdef WITH_EXTRA_CHECKS
1733  call_depth_--;
1734 #endif // WITH_EXTRA_CHECKS
1735  (*this)->print_in(uerr(), arg, true);
1736  THROW_ERROR("operator()", e.what());
1737  }
1738  }
1739 
1740  int Function::operator()(const SXElem** arg, SXElem** res,
1741  casadi_int* iw, SXElem* w, int mem) const {
1742  try {
1743  return (*this)->eval_sx(arg, res, iw, w, memory(mem), false, false);
1744  } catch(std::exception& e) {
1745  THROW_ERROR("operator()", e.what());
1746  }
1747  }
1748 
1749  const SX Function::sx_in(casadi_int iind) const {
1750  try {
1751  return (*this)->sx_in(iind);
1752  } catch(std::exception& e) {
1753  THROW_ERROR("sx_in", e.what());
1754  }
1755  }
1756 
1757  const SX Function::sx_out(casadi_int oind) const {
1758  try {
1759  return (*this)->sx_out(oind);
1760  } catch(std::exception& e) {
1761  THROW_ERROR("sx_out", e.what());
1762  }
1763  }
1764 
1765  const std::vector<SX> Function::sx_in() const {
1766  try {
1767  return (*this)->sx_in();
1768  } catch(std::exception& e) {
1769  THROW_ERROR("sx_in", e.what());
1770  }
1771  }
1772 
1773  const std::vector<SX> Function::sx_out() const {
1774  try {
1775  return (*this)->sx_out();
1776  } catch(std::exception& e) {
1777  THROW_ERROR("sx_out", e.what());
1778  }
1779  }
1780 
1781  const MX Function::mx_in(casadi_int ind) const {
1782  return (*this)->mx_in(ind);
1783  }
1784 
1785  const MX Function::mx_out(casadi_int ind) const {
1786  return (*this)->mx_out(ind);
1787  }
1788 
1789  const std::vector<MX> Function::mx_in() const {
1790  return (*this)->mx_in();
1791  }
1792 
1793  const std::vector<MX> Function::mx_out() const {
1794  return (*this)->mx_out();
1795  }
1796 
1797  std::vector<double> Function::nz_from_in(const std::vector<DM>& arg) const {
1798  return (*this)->nz_in(arg);
1799  }
1800 
1801  std::vector<double> Function::nz_from_out(const std::vector<DM>& res) const {
1802  return (*this)->nz_out(res);
1803  }
1804 
1805  std::vector<DM> Function::nz_to_in(const std::vector<double>& arg) const {
1806  return (*this)->nz_in(arg);
1807  }
1808 
1809  std::vector<DM> Function::nz_to_out(const std::vector<double>& res) const {
1810  return (*this)->nz_out(res);
1811  }
1812 
1813  DMDict Function::convert_in(const std::vector<DM>& arg) const {
1814  return (*this)->convert_arg(arg);
1815  }
1816 
1817  std::vector<DM> Function::convert_in(const DMDict& arg) const {
1818  return (*this)->convert_arg(arg);
1819  }
1820 
1821  DMDict Function::convert_out(const std::vector<DM>& arg) const {
1822  return (*this)->convert_res(arg);
1823  }
1824 
1825  std::vector<DM> Function::convert_out(const DMDict& arg) const {
1826  return (*this)->convert_res(arg);
1827  }
1828 
1829  SXDict Function::convert_in(const std::vector<SX>& arg) const {
1830  return (*this)->convert_arg(arg);
1831  }
1832 
1833  std::vector<SX> Function::convert_in(const SXDict& arg) const {
1834  return (*this)->convert_arg(arg);
1835  }
1836 
1837  SXDict Function::convert_out(const std::vector<SX>& arg) const {
1838  return (*this)->convert_res(arg);
1839  }
1840 
1841  std::vector<SX> Function::convert_out(const SXDict& arg) const {
1842  return (*this)->convert_res(arg);
1843  }
1844 
1845  MXDict Function::convert_in(const std::vector<MX>& arg) const {
1846  return (*this)->convert_arg(arg);
1847  }
1848 
1849  std::vector<MX> Function::convert_in(const MXDict& arg) const {
1850  return (*this)->convert_arg(arg);
1851  }
1852 
1853  MXDict Function::convert_out(const std::vector<MX>& arg) const {
1854  return (*this)->convert_res(arg);
1855  }
1856 
1857  std::vector<MX> Function::convert_out(const MXDict& arg) const {
1858  return (*this)->convert_res(arg);
1859  }
1860 
1861  bool Function::is_a(const std::string& type, bool recursive) const {
1862  return (*this)->is_a(type, recursive);
1863  }
1864 
1865  void Function::merge(const std::vector<MX>& arg,
1866  std::vector<MX>& subs_from, std::vector<MX>& subs_to) const {
1867  (*this)->merge(arg, subs_from, subs_to);
1868  }
1869 
1870  std::vector<SX> Function::free_sx() const {
1871  try {
1872  return (*this)->free_sx();
1873  } catch(std::exception& e) {
1874  THROW_ERROR("free_sx", e.what());
1875  }
1876  }
1877 
1878  std::vector<MX> Function::free_mx() const {
1879  try {
1880  return (*this)->free_mx();
1881  } catch(std::exception& e) {
1882  THROW_ERROR("free_mx", e.what());
1883  }
1884  }
1885 
1886  bool Function::has_spfwd() const {
1887  return (*this)->has_spfwd();
1888  }
1889 
1890  bool Function::has_sprev() const {
1891  return (*this)->has_sprev();
1892  }
1893 
1894  bool Function::has_free() const {
1895  return (*this)->has_free();
1896  }
1897 
1898  void Function::generate_lifted(Function& vdef_fcn, Function& vinit_fcn) const {
1899  try {
1900  (*this)->generate_lifted(vdef_fcn, vinit_fcn);
1901  } catch(std::exception& e) {
1902  THROW_ERROR("generate_lifted", e.what());
1903  }
1904  }
1905 
1906  casadi_int Function::n_instructions() const {
1907  try {
1908  return (*this)->n_instructions();
1909  } catch(std::exception& e) {
1910  THROW_ERROR("n_instructions", e.what());
1911  }
1912  }
1913 
1914  MX Function::instruction_MX(casadi_int k) const {
1915  try {
1916  return (*this)->instruction_MX(k);
1917  } catch(std::exception& e) {
1918  THROW_ERROR("instruction_MX", e.what());
1919  }
1920  }
1921 
1923  try {
1924  return (*this)->instructions_sx();
1925  } catch(std::exception& e) {
1926  THROW_ERROR("instructions_sx", e.what());
1927  }
1928  }
1929 
1930  casadi_int Function::instruction_id(casadi_int k) const {
1931  try {
1932  return (*this)->instruction_id(k);
1933  } catch(std::exception& e) {
1934  THROW_ERROR("instruction_id", e.what());
1935  }
1936  }
1937 
1938  std::vector<casadi_int> Function::instruction_input(casadi_int k) const {
1939  try {
1940  return (*this)->instruction_input(k);
1941  } catch(std::exception& e) {
1942  THROW_ERROR("instruction_input", e.what());
1943  }
1944  }
1945 
1946  double Function::instruction_constant(casadi_int k) const {
1947  try {
1948  return (*this)->instruction_constant(k);
1949  } catch(std::exception& e) {
1950  THROW_ERROR("instruction_constant", e.what());
1951  }
1952  }
1953 
1954  std::vector<casadi_int> Function::instruction_output(casadi_int k) const {
1955  try {
1956  return (*this)->instruction_output(k);
1957  } catch(std::exception& e) {
1958  THROW_ERROR("instruction_output", e.what());
1959  }
1960  }
1961 
1962  casadi_int Function::n_nodes() const {
1963  try {
1964  return (*this)->n_nodes();
1965  } catch(std::exception& e) {
1966  THROW_ERROR("n_nodes", e.what());
1967  }
1968  }
1969 
1970  casadi_int Function::checkout() const {
1971  return (*this)->checkout();
1972  }
1973 
1974  void Function::release(int mem) const {
1975  (*this)->release(mem);
1976  }
1977 
1978  void* Function::memory(int ind) const {
1979  return (*this)->memory(ind);
1980  }
1981 
1982  void Function::assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1983  casadi_assert(size1_in(i)==nrow && size2_in(i)==ncol,
1984  "Incorrect shape for " + str(*this) + " input " + str(i) + " \""
1985  + name_in(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1986  + " but got " + str(size1_in(i)) + "-by-" + str(size2_in(i)));
1987 
1988  }
1989 
1990  void Function::assert_size_out(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1991  casadi_assert(size1_out(i)==nrow && size2_out(i)==ncol,
1992  "Incorrect shape for " + str(*this) + " output " + str(i) + " \""
1993  + name_out(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1994  + " but got " + str(size1_out(i)) + "-by-" + str(size2_out(i)));
1995  }
1996 
1997  void Function::assert_sparsity_out(casadi_int i, const Sparsity& sp,
1998  casadi_int n, bool allow_all_zero_sparse) const {
1999  // Assert shape
2000  assert_size_out(i, sp.size1(), sp.size2() * n);
2001  // Quick return if empty sparse
2002  if (allow_all_zero_sparse && sparsity_out(i).nnz() == 0) return;
2003  // Check sparsities
2004  casadi_assert(sparsity_out(i).is_stacked(sp, n), "Mismatching sparsity "
2005  "(but correct dimensions) for " + str(*this) + " output " + name_out(i));
2006  }
2007 
2009  factory(const std::string& name,
2010  const std::vector<std::string>& s_in,
2011  const std::vector<std::string>& s_out,
2012  const AuxOut& aux,
2013  const Dict& opts) const {
2014  try {
2015  return (*this)->factory(name, s_in, s_out, aux, opts);
2016  } catch(std::exception& e) {
2017  THROW_ERROR("factory", "Failed to create " + name + ":" + str(s_in) + "->" + str(s_out)
2018  + " with " + str(aux) + ":\n" + str(e.what()));
2019  }
2020  }
2021 
2022  std::vector<bool> Function::
2023  which_depends(const std::string& s_in, const std::vector<std::string>& s_out,
2024  casadi_int order, bool tr) const {
2025  try {
2026  return (*this)->which_depends(s_in, s_out, order, tr);
2027  } catch(std::exception& e) {
2028  THROW_ERROR("which_depends", e.what());
2029  }
2030  }
2031 
2033  try {
2034  return (*this)->cache();
2035  } catch(std::exception& e) {
2036  THROW_ERROR("cache", e.what());
2037  return {};
2038  }
2039  }
2040 
2041  std::vector<std::string> Function::get_function() const {
2042  try {
2043  return (*this)->get_function();
2044  } catch(std::exception& e) {
2045  THROW_ERROR("get_function", e.what());
2046  return {};
2047  }
2048  }
2049 
2050  Function Function::get_function(const std::string &name) const {
2051  try {
2052  return (*this)->get_function(name);
2053  } catch(std::exception& e) {
2054  THROW_ERROR("get_function", e.what());
2055  }
2056  }
2057 
2058  bool Function::has_function(const std::string& fname) const {
2059  try {
2060  return (*this)->has_function(fname);
2061  } catch(std::exception& e) {
2062  THROW_ERROR("has_function", e.what());
2063  return false;
2064  }
2065  }
2066 
2067  std::vector<Function> Function::find_functions(casadi_int max_depth) const {
2068  try {
2069  // If negative, make largest positive number
2070  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
2071  // The internal routine uses a map to avoid duplicate functions
2072  std::map<FunctionInternal*, std::pair<Function, size_t> > all_fun;
2073  (*this)->find(all_fun, max_depth);
2074  // Create return object
2075  std::vector<Function> ret(all_fun.size());
2076  for (auto&& e : all_fun) ret[e.second.second] = e.second.first;
2077  return ret;
2078  } catch(std::exception& e) {
2079  THROW_ERROR("find", e.what());
2080  return {};
2081  }
2082  }
2083 
2084  Function Function::find_function(const std::string &name, casadi_int max_depth) const {
2085  try {
2086  // If negative, make largest positive number
2087  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
2088  // The internal routine uses a map to avoid duplicate functions
2089  std::map<FunctionInternal*, std::pair<Function, size_t> > all_fun;
2090  (*this)->find(all_fun, max_depth);
2091  // Search this map
2092  for (auto&& e : all_fun) {
2093  if (e.second.first.name() == name) return e.second.first;
2094  }
2095  // Not found
2096  casadi_error("'" + name + "' not found");
2097  } catch(std::exception& e) {
2098  THROW_ERROR("find", e.what());
2099  return Function();
2100  }
2101  }
2102 
2103 
2105  try {
2106  return (*this)->oracle();
2107  } catch(std::exception& e) {
2108  THROW_ERROR("oracle", e.what());
2109  }
2110  }
2111 
2113  return (*this)->wrap();
2114  }
2115 
2116  Function Function::wrap(const std::string& name) const {
2117  return (*this)->wrap(name);
2118  }
2119 
2121  return (*this)->wrap_as_needed(opts);
2122  }
2123 
2124  Function Function::wrap_as_needed(const std::string& name, const Dict& opts) const {
2125  return (*this)->wrap_as_needed(name, opts);
2126  }
2127 
2128  bool Function::operator==(const Function& f) const {
2129  try {
2130  casadi_assert(!is_null(), "lhs is null");
2131  casadi_assert(!f.is_null(), "rhs is null");
2132  return get()==f.get();
2133  } catch(std::exception& e) {
2134  THROW_ERROR("operator==", e.what());
2135  }
2136  }
2137 
2139  return (*this)->info();
2140  }
2141 
2142  std::vector<SX> Function::order(const std::vector<SX>& expr) {
2143  return SXFunction::order(expr);
2144  }
2145 
2146  std::vector<MX> Function::order(const std::vector<MX>& expr) {
2147  return MXFunction::order(expr);
2148  }
2149 
2151  w_.resize(f_.sz_w());
2152  iw_.resize(f_.sz_iw());
2153  arg_.resize(f_.sz_arg());
2154  res_.resize(f_.sz_res());
2155  if (f_->checkout_) {
2156  mem_ = f_->checkout_();
2157  } else {
2158  mem_ = f_.checkout();
2159  mem_internal_ = f_.memory(mem_);
2160  }
2161  f_node_ = f.operator->();
2162  }
2163 
2165  if (f_->release_) {
2166  f_->release_(mem_);
2167  } else {
2168  f_.release(mem_);
2169  }
2170  }
2171 
2173  : f_(f.f_), w_(f.w_), iw_(f.iw_), arg_(f.arg_), res_(f.res_), f_node_(f.f_node_) {
2174  if (f_->checkout_) {
2175  mem_ = f_->checkout_();
2176  } else {
2177  mem_ = f_.checkout();
2178  mem_internal_ = f_.memory(mem_);
2179  }
2180  }
2181 
2183  if (this == &f) return *this;
2184 
2185  if (f_->release_) {
2186  f_->release_(mem_);
2187  } else {
2188  f_.release(mem_);
2189  }
2190 
2191  f_ = f.f_;
2192  w_ = f.w_; iw_ = f.iw_; arg_ = f.arg_; res_ = f.res_; f_node_ = f.f_node_;
2193  // Checkout fresh memory
2194  if (f_->checkout_) {
2195  mem_ = f_->checkout_();
2196  } else {
2197  mem_ = f_.checkout();
2198  mem_internal_ = f_.memory(mem_);
2199  }
2200 
2201  return *this;
2202  }
2203 
2204  void FunctionBuffer::set_arg(casadi_int i, const double* a, casadi_int size) {
2205  casadi_assert(size>=f_.nnz_in(i)*sizeof(double),
2206  "Buffer is not large enough. Needed " + str(f_.nnz_in(i)*sizeof(double)) +
2207  " bytes, got " + str(size) + ".");
2208  arg_.at(i) = a;
2209  }
2210  void FunctionBuffer::set_res(casadi_int i, double* a, casadi_int size) {
2211  casadi_assert(size>=f_.nnz_out(i)*sizeof(double),
2212  "Buffer is not large enough. Needed " + str(f_.nnz_out(i)*sizeof(double)) +
2213  " bytes, got " + str(size) + ".");
2214  res_.at(i) = a;
2215  }
2217  if (f_node_->eval_) {
2218  ret_ = f_node_->eval_(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_);
2219  } else {
2220  ret_ = f_node_->eval(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_internal_);
2221  }
2222  }
2224  return ret_;
2225  }
2226 
2227  void CASADI_EXPORT _function_buffer_eval(void* raw) {
2228  static_cast<FunctionBuffer*>(raw)->_eval();
2229  }
2230 
2232  return f_.stats(mem_);
2233  }
2234 
2235 
2236  template<>
2237  const SX CASADI_EXPORT Function::sym_in(casadi_int iind) const {
2238  return sx_in(iind);
2239  }
2240  template<>
2241  const MX CASADI_EXPORT Function::sym_in(casadi_int iind) const {
2242  return mx_in(iind);
2243  }
2244 
2245  template<>
2246  const std::vector<SX> CASADI_EXPORT Function::sym_in() const {
2247  return sx_in();
2248  }
2249  template<>
2250  const std::vector<MX> CASADI_EXPORT Function::sym_in() const {
2251  return mx_in();
2252  }
2253 
2254 } // namespace casadi
const char * what() const override
Display error.
Definition: exception.hpp:90
Helper class for C code generation.
void add(const Function &f, bool with_jac_sparsity=false)
Add a function (name generated)
std::string generate(const std::string &prefix="")
Generate file(s)
Function blind_unpack_function()
SerializerBase::SerializationType pop_type()
Definition: serializer.cpp:134
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.cpp:115
Class to achieve minimal overhead function evaluations.
Definition: function.hpp:1384
void set_res(casadi_int i, double *a, casadi_int size)
Set output buffer for ouput i.
Definition: function.cpp:2210
void set_arg(casadi_int i, const double *a, casadi_int size)
Set input buffer for input i.
Definition: function.cpp:2204
FunctionBuffer & operator=(const FunctionBuffer &f)
Definition: function.cpp:2182
FunctionBuffer(const Function &f)
Main constructor.
Definition: function.cpp:2150
int ret()
Get last return value.
Definition: function.cpp:2223
Internal class for Function.
Function forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
virtual Function slice(const std::string &name, const std::vector< casadi_int > &order_in, const std::vector< casadi_int > &order_out, const Dict &opts) const
returns a new function with a selection of inputs/outputs of the original
static Function deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
virtual Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux, const Dict &opts) const
casadi_release_t release_
Release redirected to a C function.
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const
Evaluate numerically.
eval_t eval_
Numerical evaluation redirected to a C function.
virtual Function simplify_passes(const std::vector< std::pair< std::string, casadi_int > > &tasks) const
Apply an ordered list of simplify passes (used by transform)
casadi_checkout_t checkout_
Checkout redirected to a C function.
Function wrap_as_needed(const std::string &name, const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
Function reverse(casadi_int nadj) const
Return function that calculates adjoint derivatives.
virtual const Function & oracle() const
Get oracle.
Function jacobian() const
Return Jacobian of all input elements with respect to all output elements.
Function wrap(const std::string &name) const
Wrap in an Function instance consisting of only one MX call.
Dict generate_options(const std::string &target) const override
Reconstruct options dict.
Function object.
Definition: function.hpp:60
bool has_sprev() const
Is the class able to propagate seeds through the algorithm?
Definition: function.cpp:1890
std::vector< double * > buf_out(VecRes res) const
Supported arguments for numerical evaluation and converters.
Definition: function.cpp:547
casadi_int numel_in() const
Get number of input elements.
Definition: function.cpp:1011
Function forward(casadi_int nfwd) const
Get a function that calculates nfwd forward derivatives.
Definition: function.cpp:1324
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:1007
static Function if_else(const std::string &name, const Function &f_true, const Function &f_false, const Dict &opts=Dict())
Constructor (if-else)
Definition: function.cpp:962
void sz_work(size_t &sz_arg, size_t &sz_res, size_t &sz_iw, size_t &sz_w) const
Get number of temporary variables needed.
Definition: function.cpp:1231
const std::map< std::string, std::vector< double > > & MapArg
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:626
void print_options(std::ostream &stream=casadi::uout()) const
Print options to a stream.
Definition: function.cpp:1344
casadi_int n_instructions() const
Number of instruction in the algorithm (SXFunction/MXFunction)
Definition: function.cpp:1906
size_t sz_res() const
Get required length of res field.
Definition: function.cpp:1237
std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order=1, bool tr=false) const
Which variables enter with some order.
Definition: function.cpp:2023
void generate_in(const std::string &fname, const std::vector< DM > &arg)
Export an input file that can be passed to generate C code with a main.
Definition: function.cpp:1400
void print_option(const std::string &name, std::ostream &stream=casadi::uout()) const
Print all information there is to know about a certain option.
Definition: function.cpp:1348
void construct(const std::string &name, const std::vector< SX > &ex_in, const std::vector< SX > &ex_out, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts)
Called by constructors.
Definition: function.cpp:221
std::string generate_dependencies(const std::string &fname, const Dict &opts=Dict()) const
Export / Generate C code for the dependency function.
Definition: function.cpp:1396
static Function deserialize(std::istream &stream)
Build function from serialization.
Definition: function.cpp:1541
static Function conditional(const std::string &name, const std::vector< Function > &f, const Function &f_def, const Dict &opts=Dict())
Constuct a switch function.
Definition: function.cpp:917
void save(const std::string &fname, const Dict &opts=Dict()) const
Save Function to a file.
Definition: function.cpp:1466
std::vector< bool > is_diff_in() const
Get differentiability of inputs/output.
Definition: function.cpp:1215
std::vector< std::string > get_function() const
Get a list of all functions.
Definition: function.cpp:2041
std::vector< double > nz_from_in(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1797
void assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const
Assert that an input dimension is equal so some given value.
Definition: function.cpp:1982
casadi_int size2_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:991
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1781
bool has_spfwd() const
Is the class able to propagate seeds through the algorithm?
Definition: function.cpp:1886
void set_temp(const double **arg, double **res, casadi_int *iw, double *w, int mem=0) const
Set the (temporary) work vectors.
Definition: function.cpp:1306
const std::vector< std::vector< double > > & VecArg
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:619
double max_in(casadi_int ind) const
Get largest input value.
Definition: function.cpp:1681
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
Definition: function.cpp:1183
FunctionInternal * get() const
Definition: function.cpp:505
static bool proceed_to(std::istream &file, const std::string &str)
Helper function for parsing .casadi files.
Definition: function.cpp:64
casadi_int size1_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:979
std::vector< std::vector< double > * > VPrRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:623
Function fold(casadi_int N, const Dict &opts=Dict()) const
Create a mapaccumulated version of this function.
Definition: function.cpp:661
const std::vector< MX > mx_in() const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1789
Function mapaccum(const std::string &name, casadi_int N, const Dict &opts=Dict()) const
Create a mapaccumulated version of this function.
Definition: function.cpp:671
Function expand() const
Expand a function to SX.
Definition: function.cpp:312
Dict info() const
Definition: function.cpp:2138
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
Dict cache() const
Get all functions in the cache.
Definition: function.cpp:2032
casadi_int numel_out() const
Get number of output elements.
Definition: function.cpp:1015
std::vector< const double * > buf_in(VecArg arg) const
Supported arguments for numerical evaluation and converters.
Definition: function.cpp:536
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
Definition: function.cpp:2112
static std::string fix_name(const std::string &name)
Turn a string into a valid function name as defined by "check_name".
Definition: function.cpp:1562
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in the expression graphs.
Definition: function.cpp:2067
void reset_dump_count()
Reset the counter used to name dump files.
Definition: function.cpp:1373
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
Definition: function.cpp:1332
Function oracle() const
Get oracle.
Definition: function.cpp:2104
static bool test_cast(const SharedObjectInternal *ptr)
Check if a particular cast is allowed.
Definition: function.cpp:1076
Function jacobian() const
Calculate all Jacobian blocks.
Definition: function.cpp:1068
void call_gen(std::vector< const D * > arg, std::vector< D * > res) const
Evaluate with temporary memory allocation.
Definition: function.cpp:614
void release(int mem) const
Release a memory object.
Definition: function.cpp:1974
casadi_int index_in(const std::string &name) const
Find the index for a string describing a particular entry of an input scheme.
Definition: function.cpp:1121
std::vector< casadi_int > instruction_input(casadi_int k) const
Locations in the work vector for the inputs of the instruction.
Definition: function.cpp:1938
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:488
std::vector< double > nominal_in(casadi_int ind) const
Get nominal input value.
Definition: function.cpp:1689
std::vector< MX > mapsum(const std::vector< MX > &x, const std::string &parallelization="serial") const
Evaluate symbolically in parallel and sum (matrix graph)
Definition: function.cpp:908
static Function bspline(const std::string &name, const std::vector< std::vector< double > > &knots, const std::vector< double > &coeffs, const std::vector< casadi_int > &degree, casadi_int m=1, const Dict &opts=Dict())
BSpline evaluator function.
Definition: function.cpp:943
static bool check_name(const std::string &name)
Check if a string is a valid function name.
Definition: function.cpp:1513
casadi_int checkout() const
Checkout a memory object.
Definition: function.cpp:1970
std::vector< MX > free_mx() const
Get all the free variables of the function.
Definition: function.cpp:1878
Function hessian_old(casadi_int iind, casadi_int oind) const
[DEPRECATED] Replaced by Function::factory.
Definition: function.cpp:1048
casadi_int n_nodes() const
Number of nodes in the algorithm.
Definition: function.cpp:1962
const Sparsity sparsity_jac(casadi_int iind, casadi_int oind, bool compact=false, bool symmetric=false) const
Definition: function.cpp:1059
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:999
std::map< std::string, std::vector< double > > & MapRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:628
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
void setup(const double **arg, double **res, casadi_int *iw, double *w, int mem=0) const
Set the (persistent and temporary) work vectors.
Definition: function.cpp:1315
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1167
~Function()
Destructor.
Definition: function.cpp:61
Function find_function(const std::string &name, casadi_int max_depth=-1) const
Get a specific function embedded in the expression graphs.
Definition: function.cpp:2084
std::vector< casadi_int > instruction_output(casadi_int k) const
Location in the work vector for the output of the instruction.
Definition: function.cpp:1954
std::vector< double > nz_from_out(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1801
SX instructions_sx() const
Get the SX node corresponding to all instructions (SXFunction)
Definition: function.cpp:1922
void assert_sparsity_out(casadi_int i, const Sparsity &sp, casadi_int n=1, bool allow_all_zero_sparse=true) const
Assert that an output sparsity is a multiple of some given sparsity.
Definition: function.cpp:1997
MX instruction_MX(casadi_int k) const
Get the MX node corresponding to an instruction (MXFunction)
Definition: function.cpp:1914
const SX sx_in(casadi_int iind) const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1749
static Function jit(const std::string &name, const std::string &body, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts=Dict())
Create a just-in-time compiled function from a C language string.
Definition: function.cpp:289
const std::vector< T > sym_in() const
Get symbolic primitives equivalent to the input expressions.
std::vector< double > nominal_out(casadi_int ind) const
Get nominal output value.
Definition: function.cpp:1693
size_t sz_iw() const
Get required length of iw field.
Definition: function.cpp:1239
const std::vector< SX > sx_out() const
Get symbolic primitives equivalent to the output expressions.
Definition: function.cpp:1773
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:975
std::vector< bool > is_diff_out() const
Get differentiability of inputs/output.
Definition: function.cpp:1223
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
bool has_out(const std::string &name) const
Does the function have a particularly named output?
Definition: function.cpp:1144
void * memory(int ind) const
Get memory object.
Definition: function.cpp:1978
static std::vector< SX > order(const std::vector< SX > &expr)
Definition: function.cpp:2142
std::vector< std::string > get_free() const
Get free variables as a string.
Definition: function.cpp:1382
DMDict convert_in(const std::vector< DM > &arg) const
Convert from/to input/output lists/map.
Definition: function.cpp:1813
Function map(casadi_int n, const std::string &parallelization="serial") const
Create a mapped version of this function.
Definition: function.cpp:861
DMDict convert_out(const std::vector< DM > &arg) const
Convert from/to input/output lists/map.
Definition: function.cpp:1821
size_t sz_w() const
Get required length of w field.
Definition: function.cpp:1241
size_t sz_arg() const
Get required length of arg field.
Definition: function.cpp:1235
void generate_out(const std::string &fname, const std::vector< DM > &arg)
Export an output file that can be checked with generated C code output.
Definition: function.cpp:1415
std::string generate(const std::string &fname, const Dict &opts=Dict()) const
Export / Generate C code for the function.
Definition: function.cpp:1390
bool is_a(const std::string &type, bool recursive=true) const
Check if the function is of a particular type.
Definition: function.cpp:1861
Function transform(const Dict &opts=Dict()) const
Apply transformation passes.
Definition: function.cpp:359
double min_in(casadi_int ind) const
Get smallest input value.
Definition: function.cpp:1685
bool has_in(const std::string &name) const
Does the function have a particularly named input?
Definition: function.cpp:1137
Function slice(const std::string &name, const std::vector< casadi_int > &order_in, const std::vector< casadi_int > &order_out, const Dict &opts=Dict()) const
returns a new function with a selection of inputs/outputs of the original
Definition: function.cpp:899
bool has_free() const
Does the function have free variables.
Definition: function.cpp:1894
const std::vector< SX > sx_in() const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1765
Function wrap_as_needed(const Dict &opts) const
Wrap in a Function with options.
Definition: function.cpp:2120
bool operator==(const Function &f) const
Check if same as another function.
Definition: function.cpp:2128
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:1003
void generate_lifted(Function &vdef_fcn, Function &vinit_fcn) const
Extract the functions needed for the Lifted Newton method.
Definition: function.cpp:1898
double instruction_constant(casadi_int k) const
Get the floating point output argument of an instruction (SXFunction)
Definition: function.cpp:1946
bool uses_output() const
Do the derivative functions need nondifferentiated outputs?
Definition: function.cpp:1035
bool has_function(const std::string &fname) const
Check if a particular dependency exists.
Definition: function.cpp:2058
Function()
Default constructor, null pointer.
Definition: function.cpp:58
static Function load(const std::string &filename)
Build function from serialization.
Definition: function.cpp:1546
void print_dimensions(std::ostream &stream=casadi::uout()) const
Print dimensions of inputs and outputs.
Definition: function.cpp:1340
void merge(const std::vector< MX > &arg, std::vector< MX > &subs_from, std::vector< MX > &subs_to) const
List merge opportunitities.
Definition: function.cpp:1865
std::vector< DM > operator()(const std::vector< DM > &arg) const
Definition: function.cpp:1597
std::map< std::string, std::vector< double > * > MPrRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:630
casadi_int size1_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:987
std::vector< DM > nz_to_in(const std::vector< double > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1805
void export_code(const std::string &lang, const std::string &fname, const Dict &options=Dict()) const
Export function in specific language.
Definition: function.cpp:1459
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:995
int eval_activity(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate signal activity forward (bit set = active (possibly nonzero))
Definition: function.cpp:1260
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate the function symbolically or numerically.
Definition: function.cpp:509
casadi_int index_out(const std::string &name) const
Find the index for a string describing a particular entry of an output scheme.
Definition: function.cpp:1129
std::vector< DM > nz_to_out(const std::vector< double > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1809
Dict stats(int mem=0) const
Get all statistics obtained at the end of the last evaluate call.
Definition: function.cpp:1080
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity of all Jacobian blocks.
Definition: function.cpp:1092
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:447
std::vector< std::vector< double > > & VecRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:621
void set_work(const double **&arg, double **&res, casadi_int *&iw, double *&w, int mem=0) const
Set the (persistent) work vectors.
Definition: function.cpp:1297
void serialize(std::ostream &stream, const Dict &opts=Dict()) const
Serialize.
Definition: function.cpp:1477
std::vector< SX > free_sx() const
Get all the free variables of the function.
Definition: function.cpp:1870
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
casadi_int size2_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:983
casadi_int instruction_id(casadi_int k) const
Identifier index of the instruction (SXFunction/MXFunction)
Definition: function.cpp:1930
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:1117
std::vector< bool > activity(const std::vector< bool > &arg) const
Output signal activity induced by a given input activity.
Definition: function.cpp:1269
void assert_size_out(casadi_int i, casadi_int nrow, casadi_int ncol) const
Assert that an output dimension is equal so some given value.
Definition: function.cpp:1990
void change_option(const std::string &option_name, const GenericType &option_value)
Change option after object creation for debugging.
Definition: function.cpp:1361
const std::vector< MX > mx_out() const
Get symbolic primitives equivalent to the output expressions.
Definition: function.cpp:1793
Function jacobian_old(casadi_int iind, casadi_int oind) const
[DEPRECATED] Replaced by Function::factory.
Definition: function.cpp:1040
FunctionInternal * operator->() const
Const access functions of the node.
Definition: function.cpp:500
double default_in(casadi_int ind) const
Get default input value.
Definition: function.cpp:1677
bool has_option(const std::string &option_name) const
Does a particular option exist.
Definition: function.cpp:1352
casadi_int numel() const
Get the number of elements.
bool is_dense() const
Check if the matrix expression is dense.
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
bool is_vector() const
Check if the matrix is a row or column vector.
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
static MX zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
GenericShared & operator=(const GenericShared &ref)
Assignment operator.
SharedObjectInternal * get() const
Get a const pointer to the node.
Generic data type, can hold different types such as bool, casadi_int, std::string etc.
bool is_string() const
Check if a particular type.
std::string to_string() const
Convert to a type.
Dict to_dict() const
Convert to a type.
casadi_int to_int() const
Convert to a type.
bool is_dict() const
Check if a particular type.
bool is_int() const
Check if a particular type.
Internal node class for MXFunction.
Definition: mx_function.hpp:67
static std::vector< MX > order(const std::vector< MX > &expr)
MX - Matrix expression.
Definition: mx.hpp:92
static MX bspline(const MX &x, const DM &coeffs, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > &degree, casadi_int m, const Dict &opts=Dict())
Definition: mx.cpp:2224
static Function create(const std::string &name, const std::string &parallelization, const Function &f, casadi_int n, const std::vector< bool > &reduce_in, const std::vector< bool > &reduce_out, const Dict &opts=Dict())
Definition: mapsum.cpp:31
std::vector< Scalar > & nonzeros()
static Matrix< double > from_file(const std::string &filename, const std::string &format_hint="")
void construct(const Dict &opts)
Construct.
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Internal node class for SXFunction.
Definition: sx_function.hpp:54
static std::vector< SX > order(const std::vector< SX > &expr)
void pack(const Sparsity &e)
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
Definition: slice.hpp:48
General sparsity class.
Definition: sparsity.hpp:106
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
bool is_dense() const
Is dense?
Definition: sparsity.cpp:273
The casadi namespace.
Definition: archiver.cpp:28
std::map< std::string, MX > MXDict
Definition: mx.hpp:1110
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
std::string join(const std::vector< std::string > &l, const std::string &delim)
std::ostream & uerr()
unsigned long long bvec_t
std::string transform_token_str(const GenericType &g)
Definition: function.cpp:331
bool isUnique(const std::vector< T > &v)
std::string transform_stats(const Function &f)
Definition: function.cpp:352
std::vector< SX > SXVector
Definition: sx_fwd.hpp:37
std::vector< MX > MXVector
Definition: mx.hpp:1107
std::map< std::string, SX > SXDict
Definition: sx_fwd.hpp:40
std::string transform_passes_str(const std::vector< std::vector< GenericType > > &ps)
Definition: function.cpp:338
std::string str(const T &v)
String representation, any type.
std::vector< casadi_int > lookupvector(const std::vector< casadi_int > &v, casadi_int size)
Returns a vector for quickly looking up entries of supplied list.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
std::vector< std::string > StringVector
void normalized_setup(std::istream &stream)
void update_dict(Dict &target, const Dict &source, bool recurse)
Update the target dictionary in place with source elements.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
std::initializer_list< SX > SXIList
Definition: sx_fwd.hpp:38
std::initializer_list< MX > MXIList
Definition: mx.hpp:1108
bool in_range(const std::vector< T > &v, casadi_int upper)
Check if for each element of v holds: v_i < upper.
Matrix< double > DM
Definition: dm_fwd.hpp:33
std::vector< casadi_int > complement(const std::vector< casadi_int > &v, casadi_int size)
Returns the list of all i in [0, size[ not found in supplied list.
void CASADI_EXPORT _function_buffer_eval(void *raw)
Definition: function.cpp:2227
Dict extract_from_dict(const Dict &d, const std::string &key, T &value)
std::ostream & uout()
std::map< std::string, DM > DMDict
Definition: dm_fwd.hpp:36
std::string filename(const std::string &path)
Definition: ghc.cpp:55
Function external_transform(const std::string &name, const std::string &op, const Function &f, const Dict &opts)
Apply a transformation defined externally.
Definition: tools.cpp:44
void normalized_out(std::ostream &stream, double val)