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  if ((it = std::find(name_in.begin(), name_in.end(), i.first))!=name_in.end()) {
204  // Input expression
205  ex_in[it-name_in.begin()] = i.second;
206  } else if ((it = std::find(name_out.begin(), name_out.end(), i.first))!=name_out.end()) {
207  // Output expression
208  ex_out[it-name_out.begin()] = i.second;
209  } else {
210  // Neither
211  casadi_error("Unknown dictionary entry: '" + i.first + "'");
212  }
213  }
214  construct(name, ex_in, ex_out, name_in, name_out, opts);
215  }
216 
217  void Function::construct(const std::string& name,
218  const std::vector<SX>& ex_in, const std::vector<SX>& ex_out,
219  const std::vector<std::string>& name_in,
220  const std::vector<std::string>& name_out,
221  const Dict& opts) {
222  try {
223  own(new SXFunction(name, ex_in, ex_out, name_in, name_out));
224  (*this)->construct(opts);
225 
226  // Perform external transformations
227  auto it = opts.find("external_transform");
228  if (it!=opts.end()) {
229  auto v = it->second.to_vector_vector();
230  for (const std::vector<GenericType>& vec : v) {
231  casadi_assert(vec.size()>=2, "external_transform: inner list must be length >=2");
232  casadi_assert(vec.size()<=3, "external_transform: inner list must be length <=3");
233  std::string name = vec[0].to_string();
234  std::string op = vec[1].to_string();
235  Dict opts = vec.size()==3 ? vec[2].to_dict() : Dict();
236  operator=(external_transform(name, op, (*this), opts));
237  }
238  }
239 
240  } catch(std::exception& e) {
241  THROW_ERROR_NOOBJ("Function", e.what(), "SXFunction");
242  }
243  }
244 
245  void Function::construct(const std::string& name,
246  const std::vector<MX>& ex_in, const std::vector<MX>& ex_out,
247  const std::vector<std::string>& name_in,
248  const std::vector<std::string>& name_out,
249  const Dict& opts) {
250  try {
251  own(new MXFunction(name, ex_in, ex_out, name_in, name_out));
252  (*this)->construct(opts);
253 
254  // Perform post-construction expand
255  auto it = opts.find("post_expand");
256  if (it!=opts.end()) {
257  if (!it->second) return;
258  auto it = opts.find("post_expand_options");
259  if (it==opts.end()) {
260  operator=((*this).expand());
261  } else {
262  operator=((*this).expand((*this).name(), it->second));
263  }
264  }
265 
266  // Perform external transformations
267  it = opts.find("external_transform");
268  if (it!=opts.end()) {
269  auto v = it->second.to_vector_vector();
270  for (const std::vector<GenericType>& vec : v) {
271  casadi_assert(vec.size()>=2, "external_transform: inner list must be length >=2");
272  casadi_assert(vec.size()<=3, "external_transform: inner list must be length <=3");
273  std::string name = vec[0].to_string();
274  std::string op = vec[1].to_string();
275  Dict opts = vec.size()==3 ? vec[2].to_dict() : Dict();
276  operator=(external_transform(name, op, (*this), opts));
277  }
278  }
279 
280  } catch(std::exception& e) {
281  THROW_ERROR_NOOBJ("Function", e.what(), "MXFunction");
282  }
283  }
284 
285  Function Function::jit(const std::string& name, const std::string& body,
286  const std::vector<std::string>& name_in,
287  const std::vector<std::string>& name_out,
288  const Dict& opts) {
289  // Pass empty vectors -> default values
290  std::vector<Sparsity> sparsity_in, sparsity_out;
291  return jit(name, body, name_in, name_out, sparsity_in, sparsity_out, opts);
292  }
293 
294  Function Function::jit(const std::string& name, const std::string& body,
295  const std::vector<std::string>& name_in,
296  const std::vector<std::string>& name_out,
297  const std::vector<Sparsity>& sparsity_in,
298  const std::vector<Sparsity>& sparsity_out,
299  const Dict& opts) {
300  try {
301  return create(new JitFunction(name, body, name_in, name_out,
302  sparsity_in, sparsity_out), opts);
303  } catch(std::exception& e) {
304  THROW_ERROR_NOOBJ("jit", e.what(), "JitFunction");
305  }
306  }
307 
309  Dict opts;
310  opts["ad_weight"] = (*this)->ad_weight();
311  opts["ad_weight_sp"] = (*this)->sp_weight();
312  opts["max_num_dir"] = (*this)->max_num_dir_;
313  opts["is_diff_in"] = (*this)->is_diff_in_;
314  opts["is_diff_out"] = (*this)->is_diff_out_;
315  return expand(name(), opts);
316  }
317 
318  Function Function::expand(const std::string& name, const Dict& opts) const {
319  casadi_assert(!has_free(),
320  "Function with free symbols cannot be expanded. "
321  "List of free variables in your Function: " +
322  join(get_free(), ","));
323 
324  Dict my_opts;
325  my_opts["ad_weight"] = (*this)->ad_weight();
326  my_opts["ad_weight_sp"] = (*this)->sp_weight();
327  my_opts["max_num_dir"] = (*this)->max_num_dir_;
328  my_opts["is_diff_in"] = (*this)->is_diff_in_;
329  my_opts["is_diff_out"] = (*this)->is_diff_out_;
330  update_dict(my_opts, opts);
331  std::vector<SX> ex_in = sx_in();
332  std::vector<SX> ex_out = Function(*this)(ex_in);
333  return Function(name, ex_in, ex_out, name_in(), name_out(), my_opts);
334  }
335 
337  Function ret;
338  ret.own(node);
339  return ret;
340  }
341 
343  Function ret = create(node);
344  ret->construct(opts);
345  return ret;
346  }
347 
349  casadi_assert_dev(!is_null());
350  return get();
351  }
352 
354  return static_cast<FunctionInternal*>(SharedObject::get());
355  }
356 
357  void Function::call(const std::vector<DM> &arg, std::vector<DM> &res,
358  bool always_inline, bool never_inline) const {
359  try {
360  (*this)->call(arg, res, always_inline, never_inline);
361  } catch(std::exception& e) {
362  THROW_ERROR("call", e.what());
363  }
364  }
365 
366  void Function::call(const std::vector<SX> &arg, std::vector<SX>& res,
367  bool always_inline, bool never_inline) const {
368  try {
369  (*this)->call(arg, res, always_inline, never_inline);
370  } catch(std::exception& e) {
371  THROW_ERROR("call", e.what());
372  }
373  }
374 
375  void Function::call(const std::vector<MX> &arg, std::vector<MX>& res,
376  bool always_inline, bool never_inline) const {
377  try {
378  (*this)->call(arg, res, always_inline, never_inline);
379  } catch(std::exception& e) {
380  THROW_ERROR("call", e.what());
381  }
382  }
383 
384  std::vector<const double*> Function::buf_in(Function::VecArg arg) const {
385  casadi_assert_dev(arg.size()==n_in());
386  auto arg_it=arg.begin();
387  std::vector<const double*> buf_arg(sz_arg());
388  for (casadi_uint i=0; i<arg.size(); ++i) {
389  casadi_assert_dev(arg_it->size()==nnz_in(i));
390  buf_arg[i] = get_ptr(*arg_it++);
391  }
392  return buf_arg;
393  }
394 
395  std::vector<double*> Function::buf_out(Function::VecRes res) const {
396  res.resize(n_out());
397  auto res_it=res.begin();
398  std::vector<double*> buf_res(sz_res());
399  for (casadi_uint i=0; i<res.size(); ++i) {
400  res_it->resize(nnz_out(i));
401  buf_res[i] = get_ptr(*res_it++);
402  }
403  return buf_res;
404  }
405 
406  std::vector<double*> Function::buf_out(Function::VPrRes res) const {
407  casadi_assert_dev(res.size()==n_out());
408  auto res_it=res.begin();
409  std::vector<double*> buf_res(sz_res());
410  for (casadi_uint i=0; i<res.size(); ++i) {
411  casadi_assert_dev(*res_it!=0);
412  (*res_it)->resize(nnz_out(i));
413  buf_res[i] = get_ptr(**res_it++);
414  }
415  return buf_res;
416  }
417 
418  std::vector<const double*> Function::buf_in(Function::MapArg arg) const {
419  // Return value (RVO)
420  std::vector<const double*> ret(sz_arg(), nullptr);
421 
422  // Read inputs
423  for (auto i=arg.begin(); i!=arg.end(); ++i) {
424  casadi_int ind = index_in(i->first);
425  casadi_assert_dev(i->second.size()==nnz_in(ind));
426  ret[ind] = get_ptr(i->second);
427  }
428 
429  return ret;
430  }
431 
432  std::vector<double*> Function::buf_out(Function::MapRes res) const {
433  // Return value (RVO)
434  std::vector<double*> ret(sz_res(), nullptr);
435 
436  // Read outputs
437  for (auto i=res.begin(); i!=res.end(); ++i) {
438  casadi_int ind = index_out(i->first);
439  i->second.resize(nnz_out(ind));
440  ret[ind] = get_ptr(i->second);
441  }
442 
443  return ret;
444  }
445 
446  std::vector<double*> Function::buf_out(Function::MPrRes res) const {
447  // Return value (RVO)
448  std::vector<double*> ret(sz_res(), nullptr);
449 
450  // Read outputs
451  for (auto i=res.begin(); i!=res.end(); ++i) {
452  casadi_int ind = index_out(i->first);
453  casadi_assert_dev(i->second!=0);
454  i->second->resize(nnz_out(ind));
455  ret[ind] = get_ptr(*i->second);
456  }
457 
458  return ret;
459  }
460 
461  template<typename D>
462  void Function::call_gen(std::vector<const D*> arg, std::vector<D*> res) const {
463  // Input buffer
464  casadi_assert_dev(arg.size()>=n_in());
465  arg.resize(sz_arg());
466 
467  // Output buffer
468  casadi_assert_dev(res.size()>=n_out());
469  res.resize(sz_res());
470 
471  // Work vectors
472  std::vector<casadi_int> iw(sz_iw());
473  std::vector<D> w(sz_w());
474 
475  // Evaluate memoryless
476  (*this)(get_ptr(arg), get_ptr(res), get_ptr(iw), get_ptr(w), 0);
477  }
478 
479 
480  void Function::operator()(std::vector<const double*> arg, std::vector<double*> res) const {
481  return call_gen(arg, res);
482  }
483 
484  void Function::operator()(std::vector<const bvec_t*> arg, std::vector<bvec_t*> res) const {
485  return call_gen(arg, res);
486  }
487 
488  void Function::operator()(std::vector<const SXElem*> arg, std::vector<SXElem*> res) const {
489  return call_gen(arg, res);
490  }
491 
492  int Function::rev(std::vector<bvec_t*> arg, std::vector<bvec_t*> res) const {
493  // Input buffer
494  casadi_assert_dev(arg.size()>=n_in());
495  arg.resize(sz_arg());
496 
497  // Output buffer
498  casadi_assert_dev(res.size()>=n_out());
499  res.resize(sz_res());
500 
501  // Work vectors
502  std::vector<casadi_int> iw(sz_iw());
503  std::vector<bvec_t> w(sz_w());
504 
505  // Evaluate memoryless
506  return rev(get_ptr(arg), get_ptr(res), get_ptr(iw), get_ptr(w), 0);
507  }
508 
509  Function Function::fold(casadi_int N, const Dict& opts) const {
510  Function base = mapaccum(N, opts);
511  std::vector<MX> base_in = base.mx_in();
512  std::vector<MX> out = base(base_in);
513  out[0] = out[0](Slice(), range((N-1)*size2_out(0), N*size2_out(0))); // NOLINT
514  return Function("fold_"+name(), base_in, out, name_in(), name_out(), opts);
515  }
516  Function Function::mapaccum(casadi_int N, const Dict& opts) const {
517  return mapaccum("mapaccum_"+name(), N, opts);
518  }
519  Function Function::mapaccum(const std::string& name, casadi_int N, const Dict& opts) const {
520  return mapaccum(name, N, 1, opts);
521  }
522  Function Function::mapaccum(const std::string& name, casadi_int N, casadi_int n_accum,
523  const Dict& opts) const {
524  Dict options = opts;
525 
526  // Default base
527  casadi_int base = 10;
528  auto it = options.find("base");
529  if (it!=options.end()) {
530  base = it->second;
531  options.erase(it);
532  }
533 
534  casadi_assert(N>0, "mapaccum: N must be positive");
535 
536  if (base==-1)
537  return mapaccum(name, std::vector<Function>(N, *this), n_accum, options);
538  casadi_assert(base>=2, "mapaccum: base must be positive");
539 
540  // Decompose N into
541  std::vector<Function> chain;
542  Function c = *this;
543  while (N!=0) {
544  casadi_int r = N % base;
545  chain.insert(chain.end(), r, c);
546  N = (N-r)/base;
547  c = c.mapaccum(c.name()+"_acc"+str(base), std::vector<Function>(base, c), n_accum, options);
548  }
549  return mapaccum(name, chain, n_accum, options);
550  }
551 
552  Function Function::mapaccum(const std::string& name,
553  const std::vector<Function>& chain, casadi_int n_accum,
554  const Dict& opts) const {
555  // Shorthands
556  casadi_int n_in = this->n_in(), n_out = this->n_out();
557  // Consistency checks
558  casadi_assert(!chain.empty(), "mapaccum: chain must be non-empty");
559  casadi_assert(n_accum<=std::min(n_in, n_out), "mapaccum: too many accumulators");
560  // Quick return?
561  if (chain.size()==1) return chain[0];
562  // Get symbolic expressions for inputs and outputs
563  std::vector<MX> arg = mx_in();
564  std::vector<MX> res;
565  // Vectorized inputs and outputs
566  std::vector<std::vector<MX>> varg(n_in), vres(n_out);
567  for (casadi_int i=0; i<n_accum; ++i) varg[i].push_back(arg[i]);
568  // For each function call
569  for (const auto& f : chain) {
570 
571  // Stacked input expressions
572  for (casadi_int i=n_accum; i<n_in; ++i) {
573  arg[i] = MX::sym(name_in(i) + "_" + str(i), f.sparsity_in(i));
574  varg[i].push_back(arg[i]);
575  }
576 
577  // Call f
578  res = f(arg);
579  // Save output expressions
580  for (casadi_int i=0; i<n_out; ++i) vres[i].push_back(res[i]);
581  // Copy function output to input
582  std::copy_n(res.begin(), n_accum, arg.begin());
583  for (casadi_int i=0; i<n_accum; ++i) {
584  // Ony get last component (allows nested calls)
585  casadi_int ncol_out=f.size2_out(i), ncol_in=size2_in(i);
586  if (ncol_out>ncol_in) {
587  arg[i] = horzsplit(arg[i], {0, ncol_out-ncol_in, ncol_out}).back();
588  }
589  }
590  }
591  // Construct return
592  for (casadi_int i=0; i<n_in; ++i) arg[i] = horzcat(varg[i]);
593  for (casadi_int i=0; i<n_out; ++i) res[i] = horzcat(vres[i]);
594  return Function(name, arg, res, name_in(), name_out(), opts);
595  }
596 
597  Function Function::mapaccum(const std::string& name, casadi_int n,
598  const std::vector<casadi_int>& accum_in,
599  const std::vector<casadi_int>& accum_out,
600  const Dict& opts) const {
601  // Shorthands
602  casadi_int n_in = this->n_in(), n_out = this->n_out();
603  // Consistency checks
604  casadi_assert_dev(in_range(accum_in, n_in) && isUnique(accum_in));
605  casadi_assert_dev(in_range(accum_out, n_out) && isUnique(accum_out));
606  casadi_assert_dev(accum_in.size()==accum_out.size());
607  casadi_int n_accum=accum_in.size();
608 
609  // Quick return if no need to reorder
610  if (accum_in==range(n_accum) && accum_out==range(n_accum)) {
611  return mapaccum(name, n, n_accum, opts);
612  }
613 
614  // Need to do some reordering
615  std::vector<casadi_int> temp_in = complement(accum_in, n_in);
616  std::vector<casadi_int> order_in = accum_in;
617  order_in.insert(order_in.end(), temp_in.begin(), temp_in.end());
618  std::vector<casadi_int> temp_out = complement(accum_out, n_out);
619  std::vector<casadi_int> order_out = accum_out;
620  order_out.insert(order_out.end(), temp_out.begin(), temp_out.end());
621  Function ret = slice("slice_" + name, order_in, order_out);
622  ret = ret.mapaccum("mapacc_" + name, n, n_accum, opts);
623  return ret.slice(name, lookupvector(order_in, n_in),
624  lookupvector(order_out, n_out), opts);
625  }
626 
627  Function Function::mapaccum(const std::string& name, casadi_int n,
628  const std::vector<std::string>& accum_in,
629  const std::vector<std::string>& accum_out,
630  const Dict& opts) const {
631  std::vector<casadi_int> accum_in_num, accum_out_num;
632  for (const std::string& s : accum_in) accum_in_num.push_back(index_in(s));
633  for (const std::string& s : accum_out) accum_out_num.push_back(index_out(s));
634  return mapaccum(name, n, accum_in_num, accum_out_num, opts);
635  }
636 
637  Function Function::map(casadi_int n,
638  const std::vector<bool>& reduce_in,
639  const std::vector<bool>& reduce_out,
640  const Dict& opts) const {
641  return MapSum::create("mapsum_" + str(n) + "_" + name(), "serial",
642  *this, n, reduce_in, reduce_out, opts);
643  }
644 
645  Function Function::map(const std::string& name, const std::string& parallelization, casadi_int n,
646  const std::vector<casadi_int>& reduce_in, const std::vector<casadi_int>& reduce_out,
647  const Dict& opts) const {
648  // Wrap in an MXFunction
649  Function f = map(n, parallelization);
650  // Start with the fully mapped inputs
651  std::vector<MX> arg = f.mx_in();
652  std::vector<MX> f_arg = arg;
653  // Replace reduced inputs
654  for (casadi_int i : reduce_in) {
655  arg[i] = mx_in(i);
656  f_arg[i] = repmat(arg[i], 1, n);
657  }
658  // Get fully mapped outputs
659  std::vector<MX> res = f(f_arg);
660  // Replace reduced outputs
661  for (casadi_int i : reduce_out) {
662  res[i] = repsum(res[i], 1, n);
663  }
664  // Construct return
665  return Function(name, arg, res, name_in(), name_out());
666  }
667 
668  Function Function::map(const std::string& name, const std::string& parallelization, casadi_int n,
669  const std::vector<std::string>& reduce_in, const std::vector<std::string>& reduce_out,
670  const Dict& opts) const {
671  std::vector<casadi_int> reduce_in_num, reduce_out_num;
672  for (const std::string& s : reduce_in) reduce_in_num.push_back(index_in(s));
673  for (const std::string& s : reduce_out) reduce_out_num.push_back(index_out(s));
674  return map(name, parallelization, n, reduce_in_num, reduce_out_num, opts);
675  }
676 
677  Function
678  Function::map(casadi_int n, const std::string& parallelization,
679  casadi_int max_num_threads) const {
680  casadi_assert(max_num_threads>=1, "max_num_threads invalid.");
681  // No need for logic when we are not saturating the limit
682  if (n<=max_num_threads) return map(n, parallelization);
683 
684  // Floored division
685  casadi_int d = n/max_num_threads;
686  if (d*max_num_threads==n) {
687  // Easy when n is divisable by max_num_threads
688  return map(d, "serial").map(max_num_threads, parallelization);
689  } else {
690  // Create a base map that computes a bit too much
691  Function base = map(d+1, "serial").map(max_num_threads, parallelization);
692  std::vector<MX> ret_in, base_in;
693  casadi_int rem = (d+1)*max_num_threads-n;
694  for (casadi_int i=0;i<n_in();++i) {
695  MX arg = MX::sym("arg", repmat(sparsity_in(i), 1, n));
696  ret_in.push_back(arg);
697  MX last_arg = arg(Slice(), range((n-1)*size2_in(i), n*size2_in(i))); // NOLINT
698  base_in.push_back(horzcat(arg, repmat(last_arg, 1, rem)));
699  }
700  std::vector<MX> ret_out = base(base_in);
701  for (casadi_int i=0;i<n_out();++i) {
702  ret_out[i] = horzsplit(ret_out[i], {0, n*size2_out(i), ret_out[i].size2()})[0];
703  }
704  return Function("helper", ret_in, ret_out, name_in(), name_out());
705  }
706  }
707 
708  Function
709  Function::map(casadi_int n, const std::string& parallelization) const {
710  // Make sure not degenerate
711  casadi_assert(n>0, "Degenerate map operation");
712  // Quick return if possible
713  if (n==1) return *this;
714  // Unroll?
715  if (parallelization=="unroll" || parallelization=="inline") {
716  // Construct symbolic inputs
717  std::vector<MX> arg(n_in());
718  std::vector<std::vector<MX>> v(n, arg);
719  std::vector<MX> tmp(n);
720  for (casadi_int i=0; i<arg.size(); ++i) {
721  for (casadi_int k=0; k<n; ++k) {
722  tmp[k] = v[k][i] = MX::sym(name_in(i)+"_"+str(k), sparsity_in(i));
723  }
724  arg[i] = horzcat(tmp);
725  }
726  // Evaluate
727  if (parallelization=="unroll") {
728  for (auto&& w : v) w = (*this)(w);
729  } else {
730  for (auto&& w : v) call(std::vector<MX>(w), w, !is_a("SXFunction"), false);
731  }
732  // Gather outputs
733  std::vector<MX> res(n_out());
734  for (casadi_int i=0; i<res.size(); ++i) {
735  for (casadi_int k=0; k<n; ++k) tmp[k] = v[k][i];
736  res[i] = horzcat(tmp);
737  }
738  // Construct function
739  return Function(name() + "_" + str(n), arg, res, name_in(), name_out());
740  } else {
741  // Generate/retrieve potentially cached map
742  return (*this)->map(n, parallelization);
743  }
744  }
745 
747  slice(const std::string& name, const std::vector<casadi_int>& order_in,
748  const std::vector<casadi_int>& order_out, const Dict& opts) const {
749  try {
750  return (*this)->slice(name, order_in, order_out, opts);
751  } catch(std::exception& e) {
752  THROW_ERROR("slice", e.what());
753  }
754  }
755 
756  std::vector<MX> Function::mapsum(const std::vector< MX > &x,
757  const std::string& parallelization) const {
758  try {
759  return (*this)->mapsum_mx(x, parallelization);
760  } catch(std::exception& e) {
761  THROW_ERROR("mapsum", e.what());
762  }
763  }
764 
765  Function Function::conditional(const std::string& name, const std::vector<Function>& f,
766  const Function& f_def, const Dict& opts) {
767  try {
768  return create(new Switch(name, f, f_def), opts);
769  } catch(std::exception& e) {
770  THROW_ERROR_NOOBJ("conditional", e.what(), "Switch");
771  }
772  }
773 
774  Function Function::conditional(const std::string& name,
775  const Function& f, const Dict& opts) {
776  try {
777  // Create a dummy function with the same signature as f
778  std::vector<MX> dummy_in = f.mx_in();
779  std::vector<MX> dummy_out(f.n_out());
780  for (casadi_int i = 0; i < dummy_out.size(); ++i) {
781  dummy_out.at(i) = MX::zeros(f.sparsity_out(i));
782  }
783  Function dummy("dummy_" + f.name(), dummy_in, dummy_out, f.name_in(), f.name_out());
784  // Form a conditional call
785  return if_else(name, f, dummy, opts);
786  } catch(std::exception& e) {
787  THROW_ERROR_NOOBJ("conditional", e.what(), "Switch");
788  }
789  }
790 
791  Function Function::bspline(const std::string &name,
792  const std::vector< std::vector<double> >& knots,
793  const std::vector<double>& coeffs, const std::vector<casadi_int>& degree,
794  casadi_int m, const Dict& opts) {
795  try {
796  casadi_assert(degree.size()==knots.size(), "Degree list length (" + str(degree.size()) + ") "
797  "must match knot list length (" + str(knots.size()) + ").");
798  MX x = MX::sym("x", degree.size());
799  std::vector<std::string> lookup_mode;
800  Dict opts_remainder = extract_from_dict(opts, "lookup_mode", lookup_mode);
801  Dict opts_bspline;
802  opts_bspline["lookup_mode"] = lookup_mode;
803  MX y = MX::bspline(x, DM(coeffs), knots, degree, m, opts_bspline);
804  return Function(name, {x}, {y}, opts_remainder);
805  } catch(std::exception& e) {
806  THROW_ERROR_NOOBJ("bspline", e.what(), "BSpline");
807  }
808  }
809 
810  Function Function::if_else(const std::string& name, const Function& f_true,
811  const Function& f_false, const Dict& opts) {
812  try {
813  return create(new Switch(name, std::vector<Function>(1, f_false), f_true), opts);
814  } catch(std::exception& e) {
815  THROW_ERROR_NOOBJ("if_else", e.what(), "Switch");
816  }
817  }
818 
819  casadi_int Function::n_in() const {
820  return (*this)->n_in_;
821  }
822 
823  casadi_int Function::n_out() const {
824  return (*this)->n_out_;
825  }
826 
827  casadi_int Function::size1_in(casadi_int ind) const {
828  return (*this)->size1_in(ind);
829  }
830 
831  casadi_int Function::size2_in(casadi_int ind) const {
832  return (*this)->size2_in(ind);
833  }
834 
835  casadi_int Function::size1_out(casadi_int ind) const {
836  return (*this)->size1_out(ind);
837  }
838 
839  casadi_int Function::size2_out(casadi_int ind) const {
840  return (*this)->size2_out(ind);
841  }
842 
843  std::pair<casadi_int, casadi_int> Function::size_in(casadi_int ind) const {
844  return (*this)->size_in(ind);
845  }
846 
847  std::pair<casadi_int, casadi_int> Function::size_out(casadi_int ind) const {
848  return (*this)->size_out(ind);
849  }
850 
851  casadi_int Function::nnz_in() const {
852  return (*this)->nnz_in();
853  }
854 
855  casadi_int Function::nnz_out() const {
856  return (*this)->nnz_out();
857  }
858 
859  casadi_int Function::numel_in() const {
860  return (*this)->numel_in();
861  }
862 
863  casadi_int Function::numel_out() const {
864  return (*this)->numel_out();
865  }
866 
867  casadi_int Function::nnz_in(casadi_int ind) const {
868  return (*this)->nnz_in(ind);
869  }
870 
871  casadi_int Function::nnz_out(casadi_int ind) const {
872  return (*this)->nnz_out(ind);
873  }
874 
875  casadi_int Function::numel_in(casadi_int ind) const {
876  return (*this)->numel_in(ind);
877  }
878 
879  casadi_int Function::numel_out(casadi_int ind) const {
880  return (*this)->numel_out(ind);
881  }
882 
883  bool Function::uses_output() const {
884  return (*this)->uses_output();
885  }
886 
887 #ifdef WITH_DEPRECATED_FEATURES
888  Function Function::jacobian_old(casadi_int iind, casadi_int oind) const {
889  // Redirect to factory class
890  std::vector<std::string> s_in = name_in();
891  std::vector<std::string> s_out = name_out();
892  s_out.insert(s_out.begin(), "jac:" + name_out(oind) + ":" + name_in(iind));
893  return factory(name() + "_jac", s_in, s_out);
894  }
895 
896  Function Function::hessian_old(casadi_int iind, casadi_int oind) const {
897  // Redirect to factory class
898  std::vector<std::string> s_in = name_in();
899  std::vector<std::string> s_out = name_out();
900  s_out.insert(s_out.begin(), "grad:" + name_out(oind) + ":" + name_in(iind));
901  s_out.insert(s_out.begin(),
902  "hess:" + name_out(oind) + ":" + name_in(iind) + ":" + name_in(iind));
903  return factory(name() + "_hess", s_in, s_out);
904  }
905 
907  sparsity_jac(casadi_int iind, casadi_int oind, bool compact, bool symmetric) const {
908  try {
909  return (*this)->jac_sparsity(oind, iind, compact, symmetric);
910  } catch(std::exception& e) {
911  THROW_ERROR("sparsity_jac", e.what());
912  }
913  }
914 #endif // WITH_DEPRECATED_FEATURES
915 
917  try {
918  return (*this)->jacobian();
919  } catch(std::exception& e) {
920  THROW_ERROR("jacobian", e.what());
921  }
922  }
923 
925  return dynamic_cast<const FunctionInternal*>(ptr)!=nullptr;
926  }
927 
928  Dict Function::stats(int mem) const {
929  if (!(*this)->has_memory(mem)) {
930  THROW_ERROR("stats",
931  "No stats available: Function/solver was not yet numerically evaluated.");
932  }
933  try {
934  return (*this)->get_stats(memory(mem));
935  } catch(std::exception& e) {
936  THROW_ERROR("stats", e.what());
937  }
938  }
939 
940  const std::vector<Sparsity>& Function::jac_sparsity(bool compact) const {
941  // Make sure all are calculated
942  for (casadi_int oind = 0; oind < n_out(); ++oind) {
943  for (casadi_int iind = 0; iind < n_in(); ++iind) {
944  (void)jac_sparsity(oind, iind, compact);
945  }
946  }
947  // Return reference to internal cache
948  return (*this)->jac_sparsity_[compact];
949  }
950 
951  Sparsity Function::jac_sparsity(casadi_int oind, casadi_int iind, bool compact) const {
952  try {
953  bool symm = (*this)->jac_is_symm(oind, iind);
954  symm = symm && sparsity_out(oind).is_dense();
955  return (*this)->jac_sparsity(oind, iind, compact, symm);
956  } catch(std::exception& e) {
957  THROW_ERROR("jac_sparsity", e.what());
958  }
959  }
960 
961  const std::vector<std::string>& Function::name_in() const {
962  return (*this)->name_in_;
963  }
964 
965  const std::vector<std::string>& Function::name_out() const {
966  return (*this)->name_out_;
967  }
968 
969  casadi_int Function::index_in(const std::string &name) const {
970  try {
971  return (*this)->index_in(name);
972  } catch(std::exception& e) {
973  THROW_ERROR("index_in", e.what());
974  }
975  }
976 
977  casadi_int Function::index_out(const std::string &name) const {
978  try {
979  return (*this)->index_out(name);
980  } catch(std::exception& e) {
981  THROW_ERROR("index_out", e.what());
982  }
983  }
984 
985  bool Function::has_in(const std::string &name) const {
986  for (const std::string& s : (*this)->name_in_) {
987  if (s==name) return true;
988  }
989  return false;
990  }
991 
992  bool Function::has_out(const std::string &name) const {
993  for (const std::string& s : (*this)->name_out_) {
994  if (s==name) return true;
995  }
996  return false;
997  }
998 
999  const std::string& Function::name_in(casadi_int ind) const {
1000  try {
1001  return (*this)->name_in_.at(ind);
1002  } catch(std::exception& e) {
1003  THROW_ERROR("name_in", e.what());
1004  }
1005  }
1006 
1007  const std::string& Function::name_out(casadi_int ind) const {
1008  try {
1009  return (*this)->name_out_.at(ind);
1010  } catch(std::exception& e) {
1011  THROW_ERROR("name_out", e.what());
1012  }
1013  }
1014 
1015  const Sparsity& Function::sparsity_in(casadi_int ind) const {
1016  try {
1017  return (*this)->sparsity_in_.at(ind);
1018  } catch(std::exception& e) {
1019  THROW_ERROR("sparsity_in", e.what());
1020  }
1021  }
1022 
1023  const Sparsity& Function::sparsity_in(const std::string &iname) const {
1024  try {
1025  return sparsity_in(index_in(iname));
1026  } catch(std::exception& e) {
1027  THROW_ERROR("sparsity_in", e.what());
1028  }
1029  }
1030 
1031  const Sparsity& Function::sparsity_out(casadi_int ind) const {
1032  try {
1033  return (*this)->sparsity_out_.at(ind);
1034  } catch(std::exception& e) {
1035  THROW_ERROR("sparsity_out", e.what());
1036  }
1037  }
1038 
1039  const Sparsity& Function::sparsity_out(const std::string &iname) const {
1040  try {
1041  return sparsity_out(index_out(iname));
1042  } catch(std::exception& e) {
1043  THROW_ERROR("sparsity_out", e.what());
1044  }
1045  }
1046 
1047  bool Function::is_diff_in(casadi_int ind) const {
1048  try {
1049  return (*this)->is_diff_in_.at(ind);
1050  } catch(std::exception& e) {
1051  THROW_ERROR("is_diff_in", e.what());
1052  }
1053  }
1054 
1055  bool Function::is_diff_out(casadi_int ind) const {
1056  try {
1057  return (*this)->is_diff_out_.at(ind);
1058  } catch(std::exception& e) {
1059  THROW_ERROR("is_diff_out", e.what());
1060  }
1061  }
1062 
1063  std::vector<bool> Function::is_diff_in() const {
1064  try {
1065  return (*this)->is_diff_in_;
1066  } catch(std::exception& e) {
1067  THROW_ERROR("is_diff_in", e.what());
1068  }
1069  }
1070 
1071  std::vector<bool> Function::is_diff_out() const {
1072  try {
1073  return (*this)->is_diff_out_;
1074  } catch(std::exception& e) {
1075  THROW_ERROR("is_diff_out", e.what());
1076  }
1077  }
1078 
1079  void Function::sz_work(size_t& sz_arg, size_t& sz_res, size_t& sz_iw, size_t& sz_w) const {
1080  (*this)->sz_work(sz_arg, sz_res, sz_iw, sz_w);
1081  }
1082 
1083  size_t Function::sz_arg() const { return (*this)->sz_arg();}
1084 
1085  size_t Function::sz_res() const { return (*this)->sz_res();}
1086 
1087  size_t Function::sz_iw() const { return (*this)->sz_iw();}
1088 
1089  size_t Function::sz_w() const { return (*this)->sz_w();}
1090 
1091  int Function::operator()(const bvec_t** arg, bvec_t** res,
1092  casadi_int* iw, bvec_t* w, int mem) const {
1093  try {
1094  return (*this)->sp_forward(arg, res, iw, w, memory(mem));
1095  } catch(std::exception& e) {
1096  THROW_ERROR("operator()", e.what());
1097  }
1098  }
1099 
1100  int Function::rev(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, int mem) const {
1101  try {
1102  return (*this)->sp_reverse(arg, res, iw, w, memory(mem));
1103  } catch(std::exception& e) {
1104  THROW_ERROR("rev", e.what());
1105  }
1106  }
1107 
1108  void Function::set_work(const double**& arg, double**& res, casadi_int*& iw, double*& w,
1109  int mem) const {
1110  try {
1111  (*this)->set_work(memory(mem), arg, res, iw, w);
1112  } catch(std::exception& e) {
1113  THROW_ERROR("set_work", e.what());
1114  }
1115  }
1116 
1117  void Function::set_temp(const double** arg, double** res, casadi_int* iw, double* w,
1118  int mem) const {
1119  try {
1120  (*this)->set_temp(memory(mem), arg, res, iw, w);
1121  } catch(std::exception& e) {
1122  THROW_ERROR("set_temp", e.what());
1123  }
1124  }
1125 
1126  void Function::setup(const double** arg, double** res, casadi_int* iw, double* w,
1127  int mem) const {
1128  try {
1129  (*this)->setup(memory(mem), arg, res, iw, w);
1130  } catch(std::exception& e) {
1131  THROW_ERROR("setup", e.what());
1132  }
1133  }
1134 
1135  Function Function::forward(casadi_int nfwd) const {
1136  try {
1137  return (*this)->forward(nfwd);
1138  } catch(std::exception& e) {
1139  THROW_ERROR("forward", e.what());
1140  }
1141  }
1142 
1143  Function Function::reverse(casadi_int nadj) const {
1144  try {
1145  return (*this)->reverse(nadj);
1146  } catch(std::exception& e) {
1147  THROW_ERROR("reverse", e.what());
1148  }
1149  }
1150 
1151  void Function::print_dimensions(std::ostream &stream) const {
1152  (*this)->print_dimensions(stream);
1153  }
1154 
1155  void Function::print_options(std::ostream &stream) const {
1156  (*this)->print_options(stream);
1157  }
1158 
1159  void Function::print_option(const std::string &name, std::ostream &stream) const {
1160  (*this)->print_option(name, stream);
1161  }
1162 
1163  bool Function::has_option(const std::string &option_name) const {
1164  try {
1165  return (*this)->has_option(option_name);
1166  } catch(std::exception& e) {
1167  THROW_ERROR("has_option", e.what());
1168  return false; // never reached
1169  }
1170  }
1171 
1172  void Function::change_option(const std::string& option_name, const GenericType& option_value) {
1173  try {
1174  // Assert existance
1175  if (!has_option(option_name))
1176  casadi_error("Option '" + option_name + "' does not exist");
1177  // Call internal class
1178  (*this)->change_option(option_name, option_value);
1179  } catch(std::exception& e) {
1180  THROW_ERROR("change_option", e.what());
1181  }
1182  }
1183 
1185  try {
1186  (*this)->reset_dump_count();
1187  } catch(std::exception& e) {
1188  THROW_ERROR("reset_dump_count", e.what());
1189  }
1190  }
1191 
1192 
1193  std::vector<std::string> Function::get_free() const {
1194  return (*this)->get_free();
1195  }
1196 
1197  std::string Function::generate(const Dict& opts) const {
1198  return generate(name(), opts);
1199  }
1200 
1201  std::string Function::generate(const std::string& fname, const Dict& opts) const {
1202  CodeGenerator gen(fname, opts);
1203  gen.add(*this);
1204  return gen.generate();
1205  }
1206 
1207  std::string Function::generate_dependencies(const std::string& fname, const Dict& opts) const {
1208  return (*this)->generate_dependencies(fname, opts);
1209  }
1210 
1211  void Function::generate_in(const std::string& fname, const std::vector<DM>& arg) {
1212  std::vector<double> d = nz_from_in(arg);
1213 
1214  // Set up output stream
1215  auto of_ptr = Filesystem::ofstream_ptr(fname);
1216  std::ostream& of = *of_ptr;
1217  normalized_setup(of);
1218 
1219  // Encode each output
1220  for (casadi_int i=0; i<d.size(); ++i) {
1221  normalized_out(of, d[i]);
1222  of << std::endl;
1223  }
1224  }
1225 
1226  void Function::generate_out(const std::string& fname, const std::vector<DM>& res) {
1227  std::vector<double> d = nz_from_out(res);
1228 
1229  // Set up output stream
1230  auto of_ptr = Filesystem::ofstream_ptr(fname);
1231  std::ostream& of = *of_ptr;
1232  normalized_setup(of);
1233 
1234  // Encode each output
1235  for (casadi_int i=0; i<d.size(); ++i) {
1236  normalized_out(of, d[i]);
1237  of << std::endl;
1238  }
1239  }
1240 
1241  std::vector<DM> Function::generate_in(const std::string& fname) {
1242  DM data = DM::from_file(fname, "txt");
1243  // Empty files are okay
1244  if (data.is_empty(true)) data = DM(0, 1);
1245  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1246  casadi_assert(data.numel()==nnz_in(),
1247  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1248  + ", while size " + str(nnz_in()) + " was expected.");
1249 
1250  return nz_to_in(data.nonzeros());
1251  }
1252 
1253  std::vector<DM> Function::generate_out(const std::string& fname) {
1254  DM data = DM::from_file(fname, "txt");
1255  // Empty files are okay
1256  if (data.is_empty(true)) data = DM(0, 1);
1257  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1258  casadi_assert(data.numel()==nnz_out(),
1259  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1260  + ", while size " + str(nnz_out()) + " was expected.");
1261 
1262  return nz_to_out(data.nonzeros());
1263  }
1264 
1265  void Function::export_code(const std::string& lang,
1266  std::ostream &stream, const Dict& options) const {
1267  return (*this)->export_code(lang, stream, options);
1268  }
1269 
1270  void Function::export_code(const std::string& lang,
1271  const std::string &fname, const Dict& options) const {
1272  auto stream_ptr = Filesystem::ofstream_ptr(fname);
1273  return (*this)->export_code(lang, *stream_ptr, options);
1274  }
1275 
1276 
1277  void Function::save(const std::string &fname, const Dict& opts) const {
1278  FileSerializer fs(fname, opts);
1279  fs.pack(*this);
1280  }
1281 
1282  std::string Function::serialize(const Dict& opts) const {
1283  std::stringstream ss;
1284  serialize(ss, opts);
1285  return ss.str();
1286  }
1287 
1288  void Function::serialize(std::ostream &stream, const Dict& opts) const {
1289  SerializingStream s(stream, opts);
1290  return serialize(s);
1291  }
1292 
1294  if (is_null()) {
1295  s.pack("Function::null", true);
1296  } else {
1297  s.pack("Function::null", false);
1298  (*this)->serialize(s);
1299  }
1300  }
1301 
1303  bool is_null;
1304  s.unpack("Function::null", is_null);
1305  if (is_null) return Function();
1307  }
1308 
1309  std::string Function::export_code(const std::string& lang, const Dict& options) const {
1310  std::stringstream ss;
1311  (*this)->export_code(lang, ss, options);
1312  return ss.str();
1313  }
1314 
1315  const std::string& Function::name() const {
1316  if (is_null()) {
1317  static std::string null = "null";
1318  return null;
1319  } else {
1320  return (*this)->name_;
1321  }
1322  }
1323 
1324  bool Function::check_name(const std::string& name) {
1325  // Check if empty
1326  if (name.empty()) return false;
1327 
1328  // Check if keyword
1329  for (const char* kw : {"null", "jac", "hess"}) {
1330  if (name==kw) return false;
1331  }
1332 
1333  // Make sure that the first character is a letter
1334  auto it=name.begin();
1335  if (!std::isalpha(*it++)) return false;
1336 
1337  // Check remain_ing characters
1338  for (; it!=name.end(); ++it) {
1339  if (*it=='_') {
1340  // Make sure that the next character isn't also an underscore
1341  if (it+1!=name.end() && *(it+1)=='_') return false;
1342  } else {
1343  // Make sure alphanumeric
1344  if (!std::isalnum(*it)) return false;
1345  }
1346  }
1347 
1348  // Valid function name if reached this point
1349  return true;
1350  }
1351 
1352  Function Function::deserialize(std::istream& stream) {
1353  DeserializingStream s(stream);
1354  return deserialize(s);
1355  }
1356 
1357  Function Function::load(const std::string& filename) {
1359  auto t = fs.pop_type();
1360  if (t==SerializerBase::SerializationType::SERIALIZED_FUNCTION) {
1361  return fs.blind_unpack_function();
1362  } else {
1363  casadi_error("File is not loadable with 'load'. Use 'FileDeserializer' instead.");
1364  }
1365  }
1366 
1367  Function Function::deserialize(const std::string& s) {
1368  std::stringstream ss;
1369  ss << s;
1370  return deserialize(ss);
1371  }
1372 
1373  std::string Function::fix_name(const std::string& name) {
1374  // Quick return if already valid name
1375  if (check_name(name)) return name;
1376 
1377  // If empty, name it "unnamed"
1378  if (name.empty()) return "unnamed";
1379 
1380  // Construct a sane name
1381  std::stringstream ss;
1382 
1383  // If the first character isn't a character, prepend an "a"
1384  if (!std::isalpha(name.front())) ss << "a";
1385 
1386  // Treat other characters
1387  bool previous_is_underscore = false;
1388  for (char c : name) {
1389  if (std::isalnum(c)) {
1390  // Alphanumeric characters
1391  ss << c;
1392  previous_is_underscore = false;
1393  } else if (!previous_is_underscore) {
1394  // Everything else becomes an underscore
1395  ss << '_';
1396  previous_is_underscore = true;
1397  }
1398  }
1399 
1400  // If name became a keyword, append 1
1401  for (const char* kw : {"null", "jac", "hess"}) {
1402  if (ss.str()==kw) ss << "1";
1403  }
1404 
1405  return ss.str();
1406  }
1407 
1408  std::vector<DM> Function::operator()(const std::vector<DM>& arg) const {
1409  std::vector<DM> res;
1410  call(arg, res);
1411  return res;
1412  }
1413 
1414  std::vector<SX> Function::operator()(const std::vector<SX>& arg) const {
1415  std::vector<SX> res;
1416  call(arg, res);
1417  return res;
1418  }
1419 
1420  std::vector<MX> Function::operator()(const std::vector<MX>& arg) const {
1421  std::vector<MX> res;
1422  call(arg, res);
1423  return res;
1424  }
1425 
1426  template<typename M>
1427  void Function::call_gen(const std::map<std::string, M>& arg, std::map<std::string, M>& res,
1428  bool always_inline, bool never_inline) const {
1429  // Convert to vector arguments
1430  std::vector<M> arg_v = (*this)->convert_arg(arg);
1431 
1432  // Make call
1433  std::vector<M> res_v;
1434  call(arg_v, res_v, always_inline, never_inline);
1435 
1436  // Save to map
1437  res.clear();
1438  for (casadi_int i=0; i<res_v.size(); ++i) {
1439  res[name_out(i)] = res_v[i];
1440  }
1441  }
1442 
1443  const DMDict Function::operator()(const DMDict& arg) const {
1444  DMDict res;
1445  call(arg, res);
1446  return res;
1447  }
1448 
1449  const SXDict Function::operator()(const SXDict& arg) const {
1450  SXDict res;
1451  call(arg, res);
1452  return res;
1453  }
1454 
1455  const MXDict Function::operator()(const MXDict& arg) const {
1456  MXDict res;
1457  call(arg, res);
1458  return res;
1459  }
1460 
1461  void Function::call(const DMDict& arg, DMDict& res,
1462  bool always_inline, bool never_inline) const {
1463  try {
1464  call_gen(arg, res, always_inline, never_inline);
1465  } catch(std::exception& e) {
1466  THROW_ERROR("call", e.what());
1467  }
1468  }
1469 
1470  void Function::call(const SXDict& arg, SXDict& res,
1471  bool always_inline, bool never_inline) const {
1472  try {
1473  call_gen(arg, res, always_inline, never_inline);
1474  } catch(std::exception& e) {
1475  THROW_ERROR("call", e.what());
1476  }
1477  }
1478 
1479  void Function::call(const MXDict& arg, MXDict& res,
1480  bool always_inline, bool never_inline) const {
1481  try {
1482  call_gen(arg, res, always_inline, never_inline);
1483  } catch(std::exception& e) {
1484  THROW_ERROR("call", e.what());
1485  }
1486  }
1487 
1488  double Function::default_in(casadi_int ind) const {
1489  return (*this)->get_default_in(ind);
1490  }
1491 
1492  double Function::max_in(casadi_int ind) const {
1493  return (*this)->get_max_in(ind);
1494  }
1495 
1496  double Function::min_in(casadi_int ind) const {
1497  return (*this)->get_min_in(ind);
1498  }
1499 
1500  std::vector<double> Function::nominal_in(casadi_int ind) const {
1501  return (*this)->get_nominal_in(ind);
1502  }
1503 
1504  std::vector<double> Function::nominal_out(casadi_int ind) const {
1505  return (*this)->get_nominal_out(ind);
1506  }
1507 
1508 #ifdef WITH_EXTRA_CHECKS
1509  // Initialize at zero depth
1510  thread_local casadi_int Function::call_depth_ = 0;
1511 #endif // WITH_EXTRA_CHECKS
1512 
1513  int Function::operator()(const double** arg, double** res,
1514  casadi_int* iw, double* w) const {
1515  scoped_checkout<Function> mem(*this);
1516  return operator()(arg, res, iw, w, mem);
1517  }
1518 
1519  int Function::operator()(const double** arg, double** res,
1520  casadi_int* iw, double* w, int mem) const {
1521  try {
1522 #ifdef WITH_EXTRA_CHECKS
1523  // Should never happen
1524  casadi_assert_dev(call_depth_>=0);
1525  call_depth_++;
1526  // For consistency check
1527  casadi_int depth = call_depth_;
1528 #endif // WITH_EXTRA_CHECKS
1529  int ret = (*this)->eval_gen(arg, res, iw, w, memory(mem), false, false);
1530 #ifdef WITH_EXTRA_CHECKS
1531  // Consitency check
1532  casadi_assert_dev(call_depth_==depth);
1533  call_depth_--;
1534 #endif // WITH_EXTRA_CHECKS
1535  return ret;
1536  } catch (KeyboardInterruptException& e) {
1537  (void)e; // unused
1538 #ifdef WITH_EXTRA_CHECKS
1539  call_depth_--;
1540 #endif // WITH_EXTRA_CHECKS
1541  throw;
1542  } catch(std::exception& e) {
1543 #ifdef WITH_EXTRA_CHECKS
1544  call_depth_--;
1545 #endif // WITH_EXTRA_CHECKS
1546  (*this)->print_in(uerr(), arg, true);
1547  THROW_ERROR("operator()", e.what());
1548  }
1549  }
1550 
1551  int Function::operator()(const SXElem** arg, SXElem** res,
1552  casadi_int* iw, SXElem* w, int mem) const {
1553  try {
1554  return (*this)->eval_sx(arg, res, iw, w, memory(mem), false, false);
1555  } catch(std::exception& e) {
1556  THROW_ERROR("operator()", e.what());
1557  }
1558  }
1559 
1560  const SX Function::sx_in(casadi_int iind) const {
1561  try {
1562  return (*this)->sx_in(iind);
1563  } catch(std::exception& e) {
1564  THROW_ERROR("sx_in", e.what());
1565  }
1566  }
1567 
1568  const SX Function::sx_out(casadi_int oind) const {
1569  try {
1570  return (*this)->sx_out(oind);
1571  } catch(std::exception& e) {
1572  THROW_ERROR("sx_out", e.what());
1573  }
1574  }
1575 
1576  const std::vector<SX> Function::sx_in() const {
1577  try {
1578  return (*this)->sx_in();
1579  } catch(std::exception& e) {
1580  THROW_ERROR("sx_in", e.what());
1581  }
1582  }
1583 
1584  const std::vector<SX> Function::sx_out() const {
1585  try {
1586  return (*this)->sx_out();
1587  } catch(std::exception& e) {
1588  THROW_ERROR("sx_out", e.what());
1589  }
1590  }
1591 
1592  const MX Function::mx_in(casadi_int ind) const {
1593  return (*this)->mx_in(ind);
1594  }
1595 
1596  const MX Function::mx_out(casadi_int ind) const {
1597  return (*this)->mx_out(ind);
1598  }
1599 
1600  const std::vector<MX> Function::mx_in() const {
1601  return (*this)->mx_in();
1602  }
1603 
1604  const std::vector<MX> Function::mx_out() const {
1605  return (*this)->mx_out();
1606  }
1607 
1608  std::vector<double> Function::nz_from_in(const std::vector<DM>& arg) const {
1609  return (*this)->nz_in(arg);
1610  }
1611 
1612  std::vector<double> Function::nz_from_out(const std::vector<DM>& res) const {
1613  return (*this)->nz_out(res);
1614  }
1615 
1616  std::vector<DM> Function::nz_to_in(const std::vector<double>& arg) const {
1617  return (*this)->nz_in(arg);
1618  }
1619 
1620  std::vector<DM> Function::nz_to_out(const std::vector<double>& res) const {
1621  return (*this)->nz_out(res);
1622  }
1623 
1624  DMDict Function::convert_in(const std::vector<DM>& arg) const {
1625  return (*this)->convert_arg(arg);
1626  }
1627 
1628  std::vector<DM> Function::convert_in(const DMDict& arg) const {
1629  return (*this)->convert_arg(arg);
1630  }
1631 
1632  DMDict Function::convert_out(const std::vector<DM>& arg) const {
1633  return (*this)->convert_res(arg);
1634  }
1635 
1636  std::vector<DM> Function::convert_out(const DMDict& arg) const {
1637  return (*this)->convert_res(arg);
1638  }
1639 
1640  SXDict Function::convert_in(const std::vector<SX>& arg) const {
1641  return (*this)->convert_arg(arg);
1642  }
1643 
1644  std::vector<SX> Function::convert_in(const SXDict& arg) const {
1645  return (*this)->convert_arg(arg);
1646  }
1647 
1648  SXDict Function::convert_out(const std::vector<SX>& arg) const {
1649  return (*this)->convert_res(arg);
1650  }
1651 
1652  std::vector<SX> Function::convert_out(const SXDict& arg) const {
1653  return (*this)->convert_res(arg);
1654  }
1655 
1656  MXDict Function::convert_in(const std::vector<MX>& arg) const {
1657  return (*this)->convert_arg(arg);
1658  }
1659 
1660  std::vector<MX> Function::convert_in(const MXDict& arg) const {
1661  return (*this)->convert_arg(arg);
1662  }
1663 
1664  MXDict Function::convert_out(const std::vector<MX>& arg) const {
1665  return (*this)->convert_res(arg);
1666  }
1667 
1668  std::vector<MX> Function::convert_out(const MXDict& arg) const {
1669  return (*this)->convert_res(arg);
1670  }
1671 
1672  bool Function::is_a(const std::string& type, bool recursive) const {
1673  return (*this)->is_a(type, recursive);
1674  }
1675 
1676  void Function::merge(const std::vector<MX>& arg,
1677  std::vector<MX>& subs_from, std::vector<MX>& subs_to) const {
1678  return (*this)->merge(arg, subs_from, subs_to);
1679  }
1680 
1681  std::vector<SX> Function::free_sx() const {
1682  try {
1683  return (*this)->free_sx();
1684  } catch(std::exception& e) {
1685  THROW_ERROR("free_sx", e.what());
1686  }
1687  }
1688 
1689  std::vector<MX> Function::free_mx() const {
1690  try {
1691  return (*this)->free_mx();
1692  } catch(std::exception& e) {
1693  THROW_ERROR("free_mx", e.what());
1694  }
1695  }
1696 
1697  bool Function::has_spfwd() const {
1698  return (*this)->has_spfwd();
1699  }
1700 
1701  bool Function::has_sprev() const {
1702  return (*this)->has_sprev();
1703  }
1704 
1705  bool Function::has_free() const {
1706  return (*this)->has_free();
1707  }
1708 
1709  void Function::generate_lifted(Function& vdef_fcn, Function& vinit_fcn) const {
1710  try {
1711  (*this)->generate_lifted(vdef_fcn, vinit_fcn);
1712  } catch(std::exception& e) {
1713  THROW_ERROR("generate_lifted", e.what());
1714  }
1715  }
1716 
1717  casadi_int Function::n_instructions() const {
1718  try {
1719  return (*this)->n_instructions();
1720  } catch(std::exception& e) {
1721  THROW_ERROR("n_instructions", e.what());
1722  }
1723  }
1724 
1725  MX Function::instruction_MX(casadi_int k) const {
1726  try {
1727  return (*this)->instruction_MX(k);
1728  } catch(std::exception& e) {
1729  THROW_ERROR("instruction_MX", e.what());
1730  }
1731  }
1732 
1734  try {
1735  return (*this)->instructions_sx();
1736  } catch(std::exception& e) {
1737  THROW_ERROR("instructions_sx", e.what());
1738  }
1739  }
1740 
1741  casadi_int Function::instruction_id(casadi_int k) const {
1742  try {
1743  return (*this)->instruction_id(k);
1744  } catch(std::exception& e) {
1745  THROW_ERROR("instruction_id", e.what());
1746  }
1747  }
1748 
1749  std::vector<casadi_int> Function::instruction_input(casadi_int k) const {
1750  try {
1751  return (*this)->instruction_input(k);
1752  } catch(std::exception& e) {
1753  THROW_ERROR("instruction_input", e.what());
1754  }
1755  }
1756 
1757  double Function::instruction_constant(casadi_int k) const {
1758  try {
1759  return (*this)->instruction_constant(k);
1760  } catch(std::exception& e) {
1761  THROW_ERROR("instruction_constant", e.what());
1762  }
1763  }
1764 
1765  std::vector<casadi_int> Function::instruction_output(casadi_int k) const {
1766  try {
1767  return (*this)->instruction_output(k);
1768  } catch(std::exception& e) {
1769  THROW_ERROR("instruction_output", e.what());
1770  }
1771  }
1772 
1773  casadi_int Function::n_nodes() const {
1774  try {
1775  return (*this)->n_nodes();
1776  } catch(std::exception& e) {
1777  THROW_ERROR("n_nodes", e.what());
1778  }
1779  }
1780 
1781  casadi_int Function::checkout() const {
1782  return (*this)->checkout();
1783  }
1784 
1785  void Function::release(int mem) const {
1786  (*this)->release(mem);
1787  }
1788 
1789  void* Function::memory(int ind) const {
1790  return (*this)->memory(ind);
1791  }
1792 
1793  void Function::assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1794  casadi_assert(size1_in(i)==nrow && size2_in(i)==ncol,
1795  "Incorrect shape for " + str(*this) + " input " + str(i) + " \""
1796  + name_in(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1797  + " but got " + str(size1_in(i)) + "-by-" + str(size2_in(i)));
1798 
1799  }
1800 
1801  void Function::assert_size_out(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1802  casadi_assert(size1_out(i)==nrow && size2_out(i)==ncol,
1803  "Incorrect shape for " + str(*this) + " output " + str(i) + " \""
1804  + name_out(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1805  + " but got " + str(size1_out(i)) + "-by-" + str(size2_out(i)));
1806  }
1807 
1808  void Function::assert_sparsity_out(casadi_int i, const Sparsity& sp,
1809  casadi_int n, bool allow_all_zero_sparse) const {
1810  // Assert shape
1811  assert_size_out(i, sp.size1(), sp.size2() * n);
1812  // Quick return if empty sparse
1813  if (allow_all_zero_sparse && sparsity_out(i).nnz() == 0) return;
1814  // Check sparsities
1815  casadi_assert(sparsity_out(i).is_stacked(sp, n), "Mismatching sparsity "
1816  "(but correct dimensions) for " + str(*this) + " output " + name_out(i));
1817  }
1818 
1820  factory(const std::string& name,
1821  const std::vector<std::string>& s_in,
1822  const std::vector<std::string>& s_out,
1823  const AuxOut& aux,
1824  const Dict& opts) const {
1825  try {
1826  return (*this)->factory(name, s_in, s_out, aux, opts);
1827  } catch(std::exception& e) {
1828  THROW_ERROR("factory", "Failed to create " + name + ":" + str(s_in) + "->" + str(s_out)
1829  + " with " + str(aux) + ":\n" + str(e.what()));
1830  }
1831  }
1832 
1833  std::vector<bool> Function::
1834  which_depends(const std::string& s_in, const std::vector<std::string>& s_out,
1835  casadi_int order, bool tr) const {
1836  try {
1837  return (*this)->which_depends(s_in, s_out, order, tr);
1838  } catch(std::exception& e) {
1839  THROW_ERROR("which_depends", e.what());
1840  }
1841  }
1842 
1844  try {
1845  return (*this)->cache();
1846  } catch(std::exception& e) {
1847  THROW_ERROR("cache", e.what());
1848  return {};
1849  }
1850  }
1851 
1852  std::vector<std::string> Function::get_function() const {
1853  try {
1854  return (*this)->get_function();
1855  } catch(std::exception& e) {
1856  THROW_ERROR("get_function", e.what());
1857  return {};
1858  }
1859  }
1860 
1861  Function Function::get_function(const std::string &name) const {
1862  try {
1863  return (*this)->get_function(name);
1864  } catch(std::exception& e) {
1865  THROW_ERROR("get_function", e.what());
1866  }
1867  }
1868 
1869  bool Function::has_function(const std::string& fname) const {
1870  try {
1871  return (*this)->has_function(fname);
1872  } catch(std::exception& e) {
1873  THROW_ERROR("has_function", e.what());
1874  return false;
1875  }
1876  }
1877 
1878  std::vector<Function> Function::find_functions(casadi_int max_depth) const {
1879  try {
1880  // If negative, make largest positive number
1881  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
1882  // The internal routine uses a map to avoid duplicate functions
1883  std::map<FunctionInternal*, Function> all_fun;
1884  (*this)->find(all_fun, max_depth);
1885  // Create return object
1886  std::vector<Function> ret;
1887  ret.reserve(all_fun.size());
1888  for (auto&& e : all_fun) ret.push_back(e.second);
1889  return ret;
1890  } catch(std::exception& e) {
1891  THROW_ERROR("find", e.what());
1892  return {};
1893  }
1894  }
1895 
1896  Function Function::find_function(const std::string &name, casadi_int max_depth) const {
1897  try {
1898  // If negative, make largest positive number
1899  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
1900  // The internal routine uses a map to avoid duplicate functions
1901  std::map<FunctionInternal*, Function> all_fun;
1902  (*this)->find(all_fun, max_depth);
1903  // Search this map
1904  for (auto&& e : all_fun) {
1905  if (e.second.name() == name) return e.second;
1906  }
1907  // Not found
1908  casadi_error("'" + name + "' not found");
1909  } catch(std::exception& e) {
1910  THROW_ERROR("find", e.what());
1911  return Function();
1912  }
1913  }
1914 
1915 
1917  try {
1918  return (*this)->oracle();
1919  } catch(std::exception& e) {
1920  THROW_ERROR("oracle", e.what());
1921  }
1922  }
1923 
1925  return (*this)->wrap();
1926  }
1927 
1929  return (*this)->wrap_as_needed(opts);
1930  }
1931 
1932  bool Function::operator==(const Function& f) const {
1933  try {
1934  casadi_assert(!is_null(), "lhs is null");
1935  casadi_assert(!f.is_null(), "rhs is null");
1936  return get()==f.get();
1937  } catch(std::exception& e) {
1938  THROW_ERROR("operator==", e.what());
1939  }
1940  }
1941 
1943  return (*this)->info();
1944  }
1945 
1946  std::vector<SX> Function::order(const std::vector<SX>& expr) {
1947  return SXFunction::order(expr);
1948  }
1949 
1950  std::vector<MX> Function::order(const std::vector<MX>& expr) {
1951  return MXFunction::order(expr);
1952  }
1953 
1955  w_.resize(f_.sz_w());
1956  iw_.resize(f_.sz_iw());
1957  arg_.resize(f_.sz_arg());
1958  res_.resize(f_.sz_res());
1959  mem_ = f_->checkout();
1960  mem_internal_ = f.memory(mem_);
1961  f_node_ = f.operator->();
1962  }
1963 
1965  if (f_->release_) {
1966  f_->release_(mem_);
1967  } else {
1968  f_.release(mem_);
1969  }
1970  }
1971 
1973  operator=(f);
1974  }
1975 
1977  f_ = f.f_;
1978  w_ = f.w_; iw_ = f.iw_; arg_ = f.arg_; res_ = f.res_; f_node_ = f.f_node_;
1979  // Checkout fresh memory
1980  if (f_->checkout_) {
1981  mem_ = f_->checkout_();
1982  } else {
1983  mem_ = f_.checkout();
1984  mem_internal_ = f_.memory(mem_);
1985  }
1986 
1987  return *this;
1988  }
1989 
1990  void FunctionBuffer::set_arg(casadi_int i, const double* a, casadi_int size) {
1991  casadi_assert(size>=f_.nnz_in(i)*sizeof(double),
1992  "Buffer is not large enough. Needed " + str(f_.nnz_in(i)*sizeof(double)) +
1993  " bytes, got " + str(size) + ".");
1994  arg_.at(i) = a;
1995  }
1996  void FunctionBuffer::set_res(casadi_int i, double* a, casadi_int size) {
1997  casadi_assert(size>=f_.nnz_out(i)*sizeof(double),
1998  "Buffer is not large enough. Needed " + str(f_.nnz_out(i)*sizeof(double)) +
1999  " bytes, got " + str(size) + ".");
2000  res_.at(i) = a;
2001  }
2003  if (f_node_->eval_) {
2004  ret_ = f_node_->eval_(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_);
2005  } else {
2006  ret_ = f_node_->eval(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_internal_);
2007  }
2008  }
2010  return ret_;
2011  }
2012 
2013  void CASADI_EXPORT _function_buffer_eval(void* raw) {
2014  static_cast<FunctionBuffer*>(raw)->_eval();
2015  }
2016 
2018  return f_.stats(mem_);
2019  }
2020 
2021 } // 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:1318
void set_res(casadi_int i, double *a, casadi_int size)
Set output buffer for ouput i.
Definition: function.cpp:1996
void set_arg(casadi_int i, const double *a, casadi_int size)
Set input buffer for input i.
Definition: function.cpp:1990
FunctionBuffer & operator=(const FunctionBuffer &f)
Definition: function.cpp:1976
FunctionBuffer(const Function &f)
Main constructor.
Definition: function.cpp:1954
int ret()
Get last return value.
Definition: function.cpp:2009
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
virtual double ad_weight() const
Weighting factor for chosing forward/reverse mode.
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.
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
casadi_checkout_t checkout_
Checkout redirected to a C function.
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_as_needed(const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
Function object.
Definition: function.hpp:60
bool has_sprev() const
Is the class able to propagate seeds through the algorithm?
Definition: function.cpp:1701
std::vector< double * > buf_out(VecRes res) const
Supported arguments for numerical evaluation and converters.
Definition: function.cpp:395
casadi_int numel_in() const
Get number of input elements.
Definition: function.cpp:859
Function forward(casadi_int nfwd) const
Get a function that calculates nfwd forward derivatives.
Definition: function.cpp:1135
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:855
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:810
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:1079
const std::map< std::string, std::vector< double > > & MapArg
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:577
void print_options(std::ostream &stream=casadi::uout()) const
Print options to a stream.
Definition: function.cpp:1155
casadi_int n_instructions() const
Number of instruction in the algorithm (SXFunction/MXFunction)
Definition: function.cpp:1717
size_t sz_res() const
Get required length of res field.
Definition: function.cpp:1085
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:1834
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:1211
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:1159
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:217
std::string generate_dependencies(const std::string &fname, const Dict &opts=Dict()) const
Export / Generate C code for the dependency function.
Definition: function.cpp:1207
static Function deserialize(std::istream &stream)
Build function from serialization.
Definition: function.cpp:1352
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:765
void save(const std::string &fname, const Dict &opts=Dict()) const
Save Function to a file.
Definition: function.cpp:1277
std::vector< bool > is_diff_in() const
Get differentiability of inputs/output.
Definition: function.cpp:1063
std::vector< std::string > get_function() const
Get a list of all functions.
Definition: function.cpp:1852
std::vector< double > nz_from_in(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1608
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:1793
casadi_int size2_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:839
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1592
bool has_spfwd() const
Is the class able to propagate seeds through the algorithm?
Definition: function.cpp:1697
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:1117
const std::vector< std::vector< double > > & VecArg
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:570
double max_in(casadi_int ind) const
Get largest input value.
Definition: function.cpp:1492
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
Definition: function.cpp:1031
FunctionInternal * get() const
Definition: function.cpp:353
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:827
std::vector< std::vector< double > * > VPrRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:574
Function fold(casadi_int N, const Dict &opts=Dict()) const
Create a mapaccumulated version of this function.
Definition: function.cpp:509
const std::vector< MX > mx_in() const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1600
Function mapaccum(const std::string &name, casadi_int N, const Dict &opts=Dict()) const
Create a mapaccumulated version of this function.
Definition: function.cpp:519
Function expand() const
Expand a function to SX.
Definition: function.cpp:308
Dict info() const
Definition: function.cpp:1942
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:961
const std::string & name() const
Name of the function.
Definition: function.cpp:1315
Dict cache() const
Get all functions in the cache.
Definition: function.cpp:1843
casadi_int numel_out() const
Get number of output elements.
Definition: function.cpp:863
std::vector< const double * > buf_in(VecArg arg) const
Supported arguments for numerical evaluation and converters.
Definition: function.cpp:384
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
Definition: function.cpp:1924
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:1373
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in the expression graphs.
Definition: function.cpp:1878
void reset_dump_count()
Reset the counter used to name dump files.
Definition: function.cpp:1184
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
Definition: function.cpp:1143
Function oracle() const
Get oracle.
Definition: function.cpp:1916
static bool test_cast(const SharedObjectInternal *ptr)
Check if a particular cast is allowed.
Definition: function.cpp:924
Function jacobian() const
Calculate all Jacobian blocks.
Definition: function.cpp:916
void call_gen(std::vector< const D * > arg, std::vector< D * > res) const
Evaluate with temporary memory allocation.
Definition: function.cpp:462
void release(int mem) const
Release a memory object.
Definition: function.cpp:1785
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:969
std::vector< casadi_int > instruction_input(casadi_int k) const
Locations in the work vector for the inputs of the instruction.
Definition: function.cpp:1749
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:336
std::vector< double > nominal_in(casadi_int ind) const
Get nominal input value.
Definition: function.cpp:1500
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:756
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:791
static bool check_name(const std::string &name)
Check if a string is a valid function name.
Definition: function.cpp:1324
casadi_int checkout() const
Checkout a memory object.
Definition: function.cpp:1781
std::vector< MX > free_mx() const
Get all the free variables of the function.
Definition: function.cpp:1689
Function hessian_old(casadi_int iind, casadi_int oind) const
[DEPRECATED] Replaced by Function::factory.
Definition: function.cpp:896
casadi_int n_nodes() const
Number of nodes in the algorithm.
Definition: function.cpp:1773
const Sparsity sparsity_jac(casadi_int iind, casadi_int oind, bool compact=false, bool symmetric=false) const
Definition: function.cpp:907
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:847
std::map< std::string, std::vector< double > > & MapRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:579
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
Definition: function.cpp:1100
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:1126
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1015
~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:1896
std::vector< casadi_int > instruction_output(casadi_int k) const
Location in the work vector for the output of the instruction.
Definition: function.cpp:1765
std::vector< double > nz_from_out(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1612
SX instructions_sx() const
Get the SX node corresponding to all instructions (SXFunction)
Definition: function.cpp:1733
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:1808
MX instruction_MX(casadi_int k) const
Get the MX node corresponding to an instruction (MXFunction)
Definition: function.cpp:1725
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:285
std::vector< double > nominal_out(casadi_int ind) const
Get nominal output value.
Definition: function.cpp:1504
size_t sz_iw() const
Get required length of iw field.
Definition: function.cpp:1087
const std::vector< SX > sx_out() const
Get symbolic primitives equivalent to the output expressions.
Definition: function.cpp:1584
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:823
std::vector< bool > is_diff_out() const
Get differentiability of inputs/output.
Definition: function.cpp:1071
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:819
bool has_out(const std::string &name) const
Does the function have a particularly named output?
Definition: function.cpp:992
void * memory(int ind) const
Get memory object.
Definition: function.cpp:1789
static std::vector< SX > order(const std::vector< SX > &expr)
Definition: function.cpp:1946
std::vector< std::string > get_free() const
Get free variables as a string.
Definition: function.cpp:1193
DMDict convert_in(const std::vector< DM > &arg) const
Convert from/to input/output lists/map.
Definition: function.cpp:1624
Function map(casadi_int n, const std::string &parallelization="serial") const
Create a mapped version of this function.
Definition: function.cpp:709
DMDict convert_out(const std::vector< DM > &arg) const
Convert from/to input/output lists/map.
Definition: function.cpp:1632
size_t sz_w() const
Get required length of w field.
Definition: function.cpp:1089
size_t sz_arg() const
Get required length of arg field.
Definition: function.cpp:1083
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:1226
std::string generate(const std::string &fname, const Dict &opts=Dict()) const
Export / Generate C code for the function.
Definition: function.cpp:1201
bool is_a(const std::string &type, bool recursive=true) const
Check if the function is of a particular type.
Definition: function.cpp:1672
double min_in(casadi_int ind) const
Get smallest input value.
Definition: function.cpp:1496
bool has_in(const std::string &name) const
Does the function have a particularly named input?
Definition: function.cpp:985
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:747
bool has_free() const
Does the function have free variables.
Definition: function.cpp:1705
const std::vector< SX > sx_in() const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1576
Function wrap_as_needed(const Dict &opts) const
Wrap in a Function with options.
Definition: function.cpp:1928
bool operator==(const Function &f) const
Check if same as another function.
Definition: function.cpp:1932
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:851
void generate_lifted(Function &vdef_fcn, Function &vinit_fcn) const
Extract the functions needed for the Lifted Newton method.
Definition: function.cpp:1709
double instruction_constant(casadi_int k) const
Get the floating point output argument of an instruction (SXFunction)
Definition: function.cpp:1757
bool uses_output() const
Do the derivative functions need nondifferentiated outputs?
Definition: function.cpp:883
bool has_function(const std::string &fname) const
Check if a particular dependency exists.
Definition: function.cpp:1869
Function()
Default constructor, null pointer.
Definition: function.cpp:58
static Function load(const std::string &filename)
Build function from serialization.
Definition: function.cpp:1357
void print_dimensions(std::ostream &stream=casadi::uout()) const
Print dimensions of inputs and outputs.
Definition: function.cpp:1151
void merge(const std::vector< MX > &arg, std::vector< MX > &subs_from, std::vector< MX > &subs_to) const
List merge opportunitities.
Definition: function.cpp:1676
std::vector< DM > operator()(const std::vector< DM > &arg) const
Definition: function.cpp:1408
std::map< std::string, std::vector< double > * > MPrRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:581
casadi_int size1_out(casadi_int ind) const
Get output dimension.
Definition: function.cpp:835
std::vector< DM > nz_to_in(const std::vector< double > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1616
void export_code(const std::string &lang, const std::string &fname, const Dict &options=Dict()) const
Export function in specific language.
Definition: function.cpp:1270
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:843
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:357
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:977
std::vector< DM > nz_to_out(const std::vector< double > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1620
Dict stats(int mem=0) const
Get all statistics obtained at the end of the last evaluate call.
Definition: function.cpp:928
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity of all Jacobian blocks.
Definition: function.cpp:940
std::map< std::string, std::vector< std::string > > AuxOut
Definition: function.hpp:404
std::vector< std::vector< double > > & VecRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:572
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:1108
void serialize(std::ostream &stream, const Dict &opts=Dict()) const
Serialize.
Definition: function.cpp:1288
std::vector< SX > free_sx() const
Get all the free variables of the function.
Definition: function.cpp:1681
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:1820
casadi_int size2_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:831
casadi_int instruction_id(casadi_int k) const
Identifier index of the instruction (SXFunction/MXFunction)
Definition: function.cpp:1741
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:965
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:1801
void change_option(const std::string &option_name, const GenericType &option_value)
Change option after object creation for debugging.
Definition: function.cpp:1172
const std::vector< MX > mx_out() const
Get symbolic primitives equivalent to the output expressions.
Definition: function.cpp:1604
Function jacobian_old(casadi_int iind, casadi_int oind) const
[DEPRECATED] Replaced by Function::factory.
Definition: function.cpp:888
FunctionInternal * operator->() const
Const access functions of the node.
Definition: function.cpp:348
double default_in(casadi_int ind) const
Get default input value.
Definition: function.cpp:1488
bool has_option(const std::string &option_name) const
Does a particular option exist.
Definition: function.cpp:1163
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.
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:2116
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.
int checkout() const
Checkout a memory object.
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:1009
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
bool isUnique(const std::vector< T > &v)
std::vector< SX > SXVector
Definition: sx_fwd.hpp:37
std::vector< MX > MXVector
Definition: mx.hpp:1006
std::map< std::string, SX > SXDict
Definition: sx_fwd.hpp:40
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:1007
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:2013
Dict extract_from_dict(const Dict &d, const std::string &key, T &value)
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:45
void normalized_out(std::ostream &stream, double val)