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 
1184  std::vector<std::string> Function::get_free() const {
1185  return (*this)->get_free();
1186  }
1187 
1188  std::string Function::generate(const Dict& opts) const {
1189  return generate(name(), opts);
1190  }
1191 
1192  std::string Function::generate(const std::string& fname, const Dict& opts) const {
1193  CodeGenerator gen(fname, opts);
1194  gen.add(*this);
1195  return gen.generate();
1196  }
1197 
1198  std::string Function::generate_dependencies(const std::string& fname, const Dict& opts) const {
1199  return (*this)->generate_dependencies(fname, opts);
1200  }
1201 
1202  void Function::generate_in(const std::string& fname, const std::vector<DM>& arg) {
1203  std::vector<double> d = nz_from_in(arg);
1204 
1205  // Set up output stream
1206  std::ofstream of;
1207  Filesystem::open(of, fname);
1208  normalized_setup(of);
1209 
1210  // Encode each output
1211  for (casadi_int i=0; i<d.size(); ++i) {
1212  normalized_out(of, d[i]);
1213  of << std::endl;
1214  }
1215  }
1216 
1217  void Function::generate_out(const std::string& fname, const std::vector<DM>& res) {
1218  std::vector<double> d = nz_from_out(res);
1219 
1220  // Set up output stream
1221  std::ofstream of;
1222  Filesystem::open(of, fname);
1223  normalized_setup(of);
1224 
1225  // Encode each output
1226  for (casadi_int i=0; i<d.size(); ++i) {
1227  normalized_out(of, d[i]);
1228  of << std::endl;
1229  }
1230  }
1231 
1232  std::vector<DM> Function::generate_in(const std::string& fname) {
1233  DM data = DM::from_file(fname, "txt");
1234  // Empty files are okay
1235  if (data.is_empty(true)) data = DM(0, 1);
1236  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1237  casadi_assert(data.numel()==nnz_in(),
1238  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1239  + ", while size " + str(nnz_in()) + " was expected.");
1240 
1241  return nz_to_in(data.nonzeros());
1242  }
1243 
1244  std::vector<DM> Function::generate_out(const std::string& fname) {
1245  DM data = DM::from_file(fname, "txt");
1246  // Empty files are okay
1247  if (data.is_empty(true)) data = DM(0, 1);
1248  casadi_assert(data.is_vector() && data.is_dense(), "Expected dense vector");
1249  casadi_assert(data.numel()==nnz_out(),
1250  "Dimension mismatch: file contains a vector of size " + str(data.numel())
1251  + ", while size " + str(nnz_out()) + " was expected.");
1252 
1253  return nz_to_out(data.nonzeros());
1254  }
1255 
1256  void Function::export_code(const std::string& lang,
1257  std::ostream &stream, const Dict& options) const {
1258  return (*this)->export_code(lang, stream, options);
1259  }
1260 
1261  void Function::export_code(const std::string& lang,
1262  const std::string &fname, const Dict& options) const {
1263  std::ofstream stream;
1264  Filesystem::open(stream, fname);
1265  return (*this)->export_code(lang, stream, options);
1266  }
1267 
1268 
1269  void Function::save(const std::string &fname, const Dict& opts) const {
1270  FileSerializer fs(fname, opts);
1271  fs.pack(*this);
1272  }
1273 
1274  std::string Function::serialize(const Dict& opts) const {
1275  std::stringstream ss;
1276  serialize(ss, opts);
1277  return ss.str();
1278  }
1279 
1280  void Function::serialize(std::ostream &stream, const Dict& opts) const {
1281  SerializingStream s(stream, opts);
1282  return serialize(s);
1283  }
1284 
1286  if (is_null()) {
1287  s.pack("Function::null", true);
1288  } else {
1289  s.pack("Function::null", false);
1290  (*this)->serialize(s);
1291  }
1292  }
1293 
1295  bool is_null;
1296  s.unpack("Function::null", is_null);
1297  if (is_null) return Function();
1299  }
1300 
1301  std::string Function::export_code(const std::string& lang, const Dict& options) const {
1302  std::stringstream ss;
1303  (*this)->export_code(lang, ss, options);
1304  return ss.str();
1305  }
1306 
1307  const std::string& Function::name() const {
1308  if (is_null()) {
1309  static std::string null = "null";
1310  return null;
1311  } else {
1312  return (*this)->name_;
1313  }
1314  }
1315 
1316  bool Function::check_name(const std::string& name) {
1317  // Check if empty
1318  if (name.empty()) return false;
1319 
1320  // Check if keyword
1321  for (const char* kw : {"null", "jac", "hess"}) {
1322  if (name==kw) return false;
1323  }
1324 
1325  // Make sure that the first character is a letter
1326  auto it=name.begin();
1327  if (!std::isalpha(*it++)) return false;
1328 
1329  // Check remain_ing characters
1330  for (; it!=name.end(); ++it) {
1331  if (*it=='_') {
1332  // Make sure that the next character isn't also an underscore
1333  if (it+1!=name.end() && *(it+1)=='_') return false;
1334  } else {
1335  // Make sure alphanumeric
1336  if (!std::isalnum(*it)) return false;
1337  }
1338  }
1339 
1340  // Valid function name if reached this point
1341  return true;
1342  }
1343 
1344  Function Function::deserialize(std::istream& stream) {
1345  DeserializingStream s(stream);
1346  return deserialize(s);
1347  }
1348 
1349  Function Function::load(const std::string& filename) {
1351  auto t = fs.pop_type();
1352  if (t==SerializerBase::SerializationType::SERIALIZED_FUNCTION) {
1353  return fs.blind_unpack_function();
1354  } else {
1355  casadi_error("File is not loadable with 'load'. Use 'FileDeserializer' instead.");
1356  }
1357  }
1358 
1359  Function Function::deserialize(const std::string& s) {
1360  std::stringstream ss;
1361  ss << s;
1362  return deserialize(ss);
1363  }
1364 
1365  std::string Function::fix_name(const std::string& name) {
1366  // Quick return if already valid name
1367  if (check_name(name)) return name;
1368 
1369  // If empty, name it "unnamed"
1370  if (name.empty()) return "unnamed";
1371 
1372  // Construct a sane name
1373  std::stringstream ss;
1374 
1375  // If the first character isn't a character, prepend an "a"
1376  if (!std::isalpha(name.front())) ss << "a";
1377 
1378  // Treat other characters
1379  bool previous_is_underscore = false;
1380  for (char c : name) {
1381  if (std::isalnum(c)) {
1382  // Alphanumeric characters
1383  ss << c;
1384  previous_is_underscore = false;
1385  } else if (!previous_is_underscore) {
1386  // Everything else becomes an underscore
1387  ss << '_';
1388  previous_is_underscore = true;
1389  }
1390  }
1391 
1392  // If name became a keyword, append 1
1393  for (const char* kw : {"null", "jac", "hess"}) {
1394  if (ss.str()==kw) ss << "1";
1395  }
1396 
1397  return ss.str();
1398  }
1399 
1400  std::vector<DM> Function::operator()(const std::vector<DM>& arg) const {
1401  std::vector<DM> res;
1402  call(arg, res);
1403  return res;
1404  }
1405 
1406  std::vector<SX> Function::operator()(const std::vector<SX>& arg) const {
1407  std::vector<SX> res;
1408  call(arg, res);
1409  return res;
1410  }
1411 
1412  std::vector<MX> Function::operator()(const std::vector<MX>& arg) const {
1413  std::vector<MX> res;
1414  call(arg, res);
1415  return res;
1416  }
1417 
1418  template<typename M>
1419  void Function::call_gen(const std::map<std::string, M>& arg, std::map<std::string, M>& res,
1420  bool always_inline, bool never_inline) const {
1421  // Convert to vector arguments
1422  std::vector<M> arg_v = (*this)->convert_arg(arg);
1423 
1424  // Make call
1425  std::vector<M> res_v;
1426  call(arg_v, res_v, always_inline, never_inline);
1427 
1428  // Save to map
1429  res.clear();
1430  for (casadi_int i=0; i<res_v.size(); ++i) {
1431  res[name_out(i)] = res_v[i];
1432  }
1433  }
1434 
1435  const DMDict Function::operator()(const DMDict& arg) const {
1436  DMDict res;
1437  call(arg, res);
1438  return res;
1439  }
1440 
1441  const SXDict Function::operator()(const SXDict& arg) const {
1442  SXDict res;
1443  call(arg, res);
1444  return res;
1445  }
1446 
1447  const MXDict Function::operator()(const MXDict& arg) const {
1448  MXDict res;
1449  call(arg, res);
1450  return res;
1451  }
1452 
1453  void Function::call(const DMDict& arg, DMDict& res,
1454  bool always_inline, bool never_inline) const {
1455  try {
1456  call_gen(arg, res, always_inline, never_inline);
1457  } catch(std::exception& e) {
1458  THROW_ERROR("call", e.what());
1459  }
1460  }
1461 
1462  void Function::call(const SXDict& arg, SXDict& res,
1463  bool always_inline, bool never_inline) const {
1464  try {
1465  call_gen(arg, res, always_inline, never_inline);
1466  } catch(std::exception& e) {
1467  THROW_ERROR("call", e.what());
1468  }
1469  }
1470 
1471  void Function::call(const MXDict& arg, MXDict& res,
1472  bool always_inline, bool never_inline) const {
1473  try {
1474  call_gen(arg, res, always_inline, never_inline);
1475  } catch(std::exception& e) {
1476  THROW_ERROR("call", e.what());
1477  }
1478  }
1479 
1480  double Function::default_in(casadi_int ind) const {
1481  return (*this)->get_default_in(ind);
1482  }
1483 
1484  double Function::max_in(casadi_int ind) const {
1485  return (*this)->get_max_in(ind);
1486  }
1487 
1488  double Function::min_in(casadi_int ind) const {
1489  return (*this)->get_min_in(ind);
1490  }
1491 
1492  std::vector<double> Function::nominal_in(casadi_int ind) const {
1493  return (*this)->get_nominal_in(ind);
1494  }
1495 
1496  std::vector<double> Function::nominal_out(casadi_int ind) const {
1497  return (*this)->get_nominal_out(ind);
1498  }
1499 
1500 #ifdef WITH_EXTRA_CHECKS
1501  // Initialize at zero depth
1502  thread_local casadi_int Function::call_depth_ = 0;
1503 #endif // WITH_EXTRA_CHECKS
1504 
1505  int Function::operator()(const double** arg, double** res,
1506  casadi_int* iw, double* w) const {
1507  scoped_checkout<Function> mem(*this);
1508  return operator()(arg, res, iw, w, mem);
1509  }
1510 
1511  int Function::operator()(const double** arg, double** res,
1512  casadi_int* iw, double* w, int mem) const {
1513  try {
1514 #ifdef WITH_EXTRA_CHECKS
1515  // Should never happen
1516  casadi_assert_dev(call_depth_>=0);
1517  call_depth_++;
1518  // For consistency check
1519  casadi_int depth = call_depth_;
1520 #endif // WITH_EXTRA_CHECKS
1521  int ret = (*this)->eval_gen(arg, res, iw, w, memory(mem), false, false);
1522 #ifdef WITH_EXTRA_CHECKS
1523  // Consitency check
1524  casadi_assert_dev(call_depth_==depth);
1525  call_depth_--;
1526 #endif // WITH_EXTRA_CHECKS
1527  return ret;
1528  } catch (KeyboardInterruptException& e) {
1529  (void)e; // unused
1530 #ifdef WITH_EXTRA_CHECKS
1531  call_depth_--;
1532 #endif // WITH_EXTRA_CHECKS
1533  throw;
1534  } catch(std::exception& e) {
1535 #ifdef WITH_EXTRA_CHECKS
1536  call_depth_--;
1537 #endif // WITH_EXTRA_CHECKS
1538  (*this)->print_in(uerr(), arg, true);
1539  THROW_ERROR("operator()", e.what());
1540  }
1541  }
1542 
1543  int Function::operator()(const SXElem** arg, SXElem** res,
1544  casadi_int* iw, SXElem* w, int mem) const {
1545  try {
1546  return (*this)->eval_sx(arg, res, iw, w, memory(mem), false, false);
1547  } catch(std::exception& e) {
1548  THROW_ERROR("operator()", e.what());
1549  }
1550  }
1551 
1552  const SX Function::sx_in(casadi_int iind) const {
1553  try {
1554  return (*this)->sx_in(iind);
1555  } catch(std::exception& e) {
1556  THROW_ERROR("sx_in", e.what());
1557  }
1558  }
1559 
1560  const SX Function::sx_out(casadi_int oind) const {
1561  try {
1562  return (*this)->sx_out(oind);
1563  } catch(std::exception& e) {
1564  THROW_ERROR("sx_out", e.what());
1565  }
1566  }
1567 
1568  const std::vector<SX> Function::sx_in() const {
1569  try {
1570  return (*this)->sx_in();
1571  } catch(std::exception& e) {
1572  THROW_ERROR("sx_in", e.what());
1573  }
1574  }
1575 
1576  const std::vector<SX> Function::sx_out() const {
1577  try {
1578  return (*this)->sx_out();
1579  } catch(std::exception& e) {
1580  THROW_ERROR("sx_out", e.what());
1581  }
1582  }
1583 
1584  const MX Function::mx_in(casadi_int ind) const {
1585  return (*this)->mx_in(ind);
1586  }
1587 
1588  const MX Function::mx_out(casadi_int ind) const {
1589  return (*this)->mx_out(ind);
1590  }
1591 
1592  const std::vector<MX> Function::mx_in() const {
1593  return (*this)->mx_in();
1594  }
1595 
1596  const std::vector<MX> Function::mx_out() const {
1597  return (*this)->mx_out();
1598  }
1599 
1600  std::vector<double> Function::nz_from_in(const std::vector<DM>& arg) const {
1601  return (*this)->nz_in(arg);
1602  }
1603 
1604  std::vector<double> Function::nz_from_out(const std::vector<DM>& res) const {
1605  return (*this)->nz_out(res);
1606  }
1607 
1608  std::vector<DM> Function::nz_to_in(const std::vector<double>& arg) const {
1609  return (*this)->nz_in(arg);
1610  }
1611 
1612  std::vector<DM> Function::nz_to_out(const std::vector<double>& res) const {
1613  return (*this)->nz_out(res);
1614  }
1615 
1616  DMDict Function::convert_in(const std::vector<DM>& arg) const {
1617  return (*this)->convert_arg(arg);
1618  }
1619 
1620  std::vector<DM> Function::convert_in(const DMDict& arg) const {
1621  return (*this)->convert_arg(arg);
1622  }
1623 
1624  DMDict Function::convert_out(const std::vector<DM>& arg) const {
1625  return (*this)->convert_res(arg);
1626  }
1627 
1628  std::vector<DM> Function::convert_out(const DMDict& arg) const {
1629  return (*this)->convert_res(arg);
1630  }
1631 
1632  SXDict Function::convert_in(const std::vector<SX>& arg) const {
1633  return (*this)->convert_arg(arg);
1634  }
1635 
1636  std::vector<SX> Function::convert_in(const SXDict& arg) const {
1637  return (*this)->convert_arg(arg);
1638  }
1639 
1640  SXDict Function::convert_out(const std::vector<SX>& arg) const {
1641  return (*this)->convert_res(arg);
1642  }
1643 
1644  std::vector<SX> Function::convert_out(const SXDict& arg) const {
1645  return (*this)->convert_res(arg);
1646  }
1647 
1648  MXDict Function::convert_in(const std::vector<MX>& arg) const {
1649  return (*this)->convert_arg(arg);
1650  }
1651 
1652  std::vector<MX> Function::convert_in(const MXDict& arg) const {
1653  return (*this)->convert_arg(arg);
1654  }
1655 
1656  MXDict Function::convert_out(const std::vector<MX>& arg) const {
1657  return (*this)->convert_res(arg);
1658  }
1659 
1660  std::vector<MX> Function::convert_out(const MXDict& arg) const {
1661  return (*this)->convert_res(arg);
1662  }
1663 
1664  bool Function::is_a(const std::string& type, bool recursive) const {
1665  return (*this)->is_a(type, recursive);
1666  }
1667 
1668  void Function::merge(const std::vector<MX>& arg,
1669  std::vector<MX>& subs_from, std::vector<MX>& subs_to) const {
1670  return (*this)->merge(arg, subs_from, subs_to);
1671  }
1672 
1673  std::vector<SX> Function::free_sx() const {
1674  try {
1675  return (*this)->free_sx();
1676  } catch(std::exception& e) {
1677  THROW_ERROR("free_sx", e.what());
1678  }
1679  }
1680 
1681  std::vector<MX> Function::free_mx() const {
1682  try {
1683  return (*this)->free_mx();
1684  } catch(std::exception& e) {
1685  THROW_ERROR("free_mx", e.what());
1686  }
1687  }
1688 
1689  bool Function::has_spfwd() const {
1690  return (*this)->has_spfwd();
1691  }
1692 
1693  bool Function::has_sprev() const {
1694  return (*this)->has_sprev();
1695  }
1696 
1697  bool Function::has_free() const {
1698  return (*this)->has_free();
1699  }
1700 
1701  void Function::generate_lifted(Function& vdef_fcn, Function& vinit_fcn) const {
1702  try {
1703  (*this)->generate_lifted(vdef_fcn, vinit_fcn);
1704  } catch(std::exception& e) {
1705  THROW_ERROR("generate_lifted", e.what());
1706  }
1707  }
1708 
1709  casadi_int Function::n_instructions() const {
1710  try {
1711  return (*this)->n_instructions();
1712  } catch(std::exception& e) {
1713  THROW_ERROR("n_instructions", e.what());
1714  }
1715  }
1716 
1717  MX Function::instruction_MX(casadi_int k) const {
1718  try {
1719  return (*this)->instruction_MX(k);
1720  } catch(std::exception& e) {
1721  THROW_ERROR("instruction_MX", e.what());
1722  }
1723  }
1724 
1726  try {
1727  return (*this)->instructions_sx();
1728  } catch(std::exception& e) {
1729  THROW_ERROR("instructions_sx", e.what());
1730  }
1731  }
1732 
1733  casadi_int Function::instruction_id(casadi_int k) const {
1734  try {
1735  return (*this)->instruction_id(k);
1736  } catch(std::exception& e) {
1737  THROW_ERROR("instruction_id", e.what());
1738  }
1739  }
1740 
1741  std::vector<casadi_int> Function::instruction_input(casadi_int k) const {
1742  try {
1743  return (*this)->instruction_input(k);
1744  } catch(std::exception& e) {
1745  THROW_ERROR("instruction_input", e.what());
1746  }
1747  }
1748 
1749  double Function::instruction_constant(casadi_int k) const {
1750  try {
1751  return (*this)->instruction_constant(k);
1752  } catch(std::exception& e) {
1753  THROW_ERROR("instruction_constant", e.what());
1754  }
1755  }
1756 
1757  std::vector<casadi_int> Function::instruction_output(casadi_int k) const {
1758  try {
1759  return (*this)->instruction_output(k);
1760  } catch(std::exception& e) {
1761  THROW_ERROR("instruction_output", e.what());
1762  }
1763  }
1764 
1765  casadi_int Function::n_nodes() const {
1766  try {
1767  return (*this)->n_nodes();
1768  } catch(std::exception& e) {
1769  THROW_ERROR("n_nodes", e.what());
1770  }
1771  }
1772 
1773  casadi_int Function::checkout() const {
1774  return (*this)->checkout();
1775  }
1776 
1777  void Function::release(int mem) const {
1778  (*this)->release(mem);
1779  }
1780 
1781  void* Function::memory(int ind) const {
1782  return (*this)->memory(ind);
1783  }
1784 
1785  void Function::assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1786  casadi_assert(size1_in(i)==nrow && size2_in(i)==ncol,
1787  "Incorrect shape for " + str(*this) + " input " + str(i) + " \""
1788  + name_in(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1789  + " but got " + str(size1_in(i)) + "-by-" + str(size2_in(i)));
1790 
1791  }
1792 
1793  void Function::assert_size_out(casadi_int i, casadi_int nrow, casadi_int ncol) const {
1794  casadi_assert(size1_out(i)==nrow && size2_out(i)==ncol,
1795  "Incorrect shape for " + str(*this) + " output " + str(i) + " \""
1796  + name_out(i) + "\". Expected " + str(nrow) + "-by-" + str(ncol)
1797  + " but got " + str(size1_out(i)) + "-by-" + str(size2_out(i)));
1798  }
1799 
1800  void Function::assert_sparsity_out(casadi_int i, const Sparsity& sp,
1801  casadi_int n, bool allow_all_zero_sparse) const {
1802  // Assert shape
1803  assert_size_out(i, sp.size1(), sp.size2() * n);
1804  // Quick return if empty sparse
1805  if (allow_all_zero_sparse && sparsity_out(i).nnz() == 0) return;
1806  // Check sparsities
1807  casadi_assert(sparsity_out(i).is_stacked(sp, n), "Mismatching sparsity "
1808  "(but correct dimensions) for " + str(*this) + " output " + name_out(i));
1809  }
1810 
1812  factory(const std::string& name,
1813  const std::vector<std::string>& s_in,
1814  const std::vector<std::string>& s_out,
1815  const AuxOut& aux,
1816  const Dict& opts) const {
1817  try {
1818  return (*this)->factory(name, s_in, s_out, aux, opts);
1819  } catch(std::exception& e) {
1820  THROW_ERROR("factory", "Failed to create " + name + ":" + str(s_in) + "->" + str(s_out)
1821  + " with " + str(aux) + ":\n" + str(e.what()));
1822  }
1823  }
1824 
1825  std::vector<bool> Function::
1826  which_depends(const std::string& s_in, const std::vector<std::string>& s_out,
1827  casadi_int order, bool tr) const {
1828  try {
1829  return (*this)->which_depends(s_in, s_out, order, tr);
1830  } catch(std::exception& e) {
1831  THROW_ERROR("which_depends", e.what());
1832  }
1833  }
1834 
1836  try {
1837  return (*this)->cache();
1838  } catch(std::exception& e) {
1839  THROW_ERROR("cache", e.what());
1840  return {};
1841  }
1842  }
1843 
1844  std::vector<std::string> Function::get_function() const {
1845  try {
1846  return (*this)->get_function();
1847  } catch(std::exception& e) {
1848  THROW_ERROR("get_function", e.what());
1849  return {};
1850  }
1851  }
1852 
1853  Function Function::get_function(const std::string &name) const {
1854  try {
1855  return (*this)->get_function(name);
1856  } catch(std::exception& e) {
1857  THROW_ERROR("get_function", e.what());
1858  }
1859  }
1860 
1861  bool Function::has_function(const std::string& fname) const {
1862  try {
1863  return (*this)->has_function(fname);
1864  } catch(std::exception& e) {
1865  THROW_ERROR("has_function", e.what());
1866  return false;
1867  }
1868  }
1869 
1870  std::vector<Function> Function::find_functions(casadi_int max_depth) const {
1871  try {
1872  // If negative, make largest positive number
1873  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
1874  // The internal routine uses a map to avoid duplicate functions
1875  std::map<FunctionInternal*, Function> all_fun;
1876  (*this)->find(all_fun, max_depth);
1877  // Create return object
1878  std::vector<Function> ret;
1879  ret.reserve(all_fun.size());
1880  for (auto&& e : all_fun) ret.push_back(e.second);
1881  return ret;
1882  } catch(std::exception& e) {
1883  THROW_ERROR("find", e.what());
1884  return {};
1885  }
1886  }
1887 
1888  Function Function::find_function(const std::string &name, casadi_int max_depth) const {
1889  try {
1890  // If negative, make largest positive number
1891  if (max_depth < 0) max_depth = std::numeric_limits<casadi_int>::max();
1892  // The internal routine uses a map to avoid duplicate functions
1893  std::map<FunctionInternal*, Function> all_fun;
1894  (*this)->find(all_fun, max_depth);
1895  // Search this map
1896  for (auto&& e : all_fun) {
1897  if (e.second.name() == name) return e.second;
1898  }
1899  // Not found
1900  casadi_error("'" + name + "' not found");
1901  } catch(std::exception& e) {
1902  THROW_ERROR("find", e.what());
1903  return Function();
1904  }
1905  }
1906 
1907 
1909  try {
1910  return (*this)->oracle();
1911  } catch(std::exception& e) {
1912  THROW_ERROR("oracle", e.what());
1913  }
1914  }
1915 
1917  return (*this)->wrap();
1918  }
1919 
1921  return (*this)->wrap_as_needed(opts);
1922  }
1923 
1924  bool Function::operator==(const Function& f) const {
1925  try {
1926  casadi_assert(!is_null(), "lhs is null");
1927  casadi_assert(!f.is_null(), "rhs is null");
1928  return get()==f.get();
1929  } catch(std::exception& e) {
1930  THROW_ERROR("operator==", e.what());
1931  }
1932  }
1933 
1935  return (*this)->info();
1936  }
1937 
1938  std::vector<SX> Function::order(const std::vector<SX>& expr) {
1939  return SXFunction::order(expr);
1940  }
1941 
1942  std::vector<MX> Function::order(const std::vector<MX>& expr) {
1943  return MXFunction::order(expr);
1944  }
1945 
1947  w_.resize(f_.sz_w());
1948  iw_.resize(f_.sz_iw());
1949  arg_.resize(f_.sz_arg());
1950  res_.resize(f_.sz_res());
1951  mem_ = f_->checkout();
1952  mem_internal_ = f.memory(mem_);
1953  f_node_ = f.operator->();
1954  }
1955 
1957  if (f_->release_) {
1958  f_->release_(mem_);
1959  } else {
1960  f_.release(mem_);
1961  }
1962  }
1963 
1965  operator=(f);
1966  }
1967 
1969  f_ = f.f_;
1970  w_ = f.w_; iw_ = f.iw_; arg_ = f.arg_; res_ = f.res_; f_node_ = f.f_node_;
1971  // Checkout fresh memory
1972  if (f_->checkout_) {
1973  mem_ = f_->checkout_();
1974  } else {
1975  mem_ = f_.checkout();
1976  mem_internal_ = f_.memory(mem_);
1977  }
1978 
1979  return *this;
1980  }
1981 
1982  void FunctionBuffer::set_arg(casadi_int i, const double* a, casadi_int size) {
1983  casadi_assert(size>=f_.nnz_in(i)*sizeof(double),
1984  "Buffer is not large enough. Needed " + str(f_.nnz_in(i)*sizeof(double)) +
1985  " bytes, got " + str(size) + ".");
1986  arg_.at(i) = a;
1987  }
1988  void FunctionBuffer::set_res(casadi_int i, double* a, casadi_int size) {
1989  casadi_assert(size>=f_.nnz_out(i)*sizeof(double),
1990  "Buffer is not large enough. Needed " + str(f_.nnz_out(i)*sizeof(double)) +
1991  " bytes, got " + str(size) + ".");
1992  res_.at(i) = a;
1993  }
1995  if (f_node_->eval_) {
1996  ret_ = f_node_->eval_(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_);
1997  } else {
1998  ret_ = f_node_->eval(get_ptr(arg_), get_ptr(res_), get_ptr(iw_), get_ptr(w_), mem_internal_);
1999  }
2000  }
2002  return ret_;
2003  }
2004 
2005  void CASADI_EXPORT _function_buffer_eval(void* raw) {
2006  static_cast<FunctionBuffer*>(raw)->_eval();
2007  }
2008 
2010  return f_.stats(mem_);
2011  }
2012 
2013 } // 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:135
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
static void open(std::ofstream &, 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:1313
void set_res(casadi_int i, double *a, casadi_int size)
Set output buffer for ouput i.
Definition: function.cpp:1988
void set_arg(casadi_int i, const double *a, casadi_int size)
Set input buffer for input i.
Definition: function.cpp:1982
FunctionBuffer & operator=(const FunctionBuffer &f)
Definition: function.cpp:1968
FunctionBuffer(const Function &f)
Main constructor.
Definition: function.cpp:1946
int ret()
Get last return value.
Definition: function.cpp:2001
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:1693
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:572
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:1709
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:1826
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:1202
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:1198
static Function deserialize(std::istream &stream)
Build function from serialization.
Definition: function.cpp:1344
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:1269
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:1844
std::vector< double > nz_from_in(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1600
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:1785
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:1584
bool has_spfwd() const
Is the class able to propagate seeds through the algorithm?
Definition: function.cpp:1689
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:565
double max_in(casadi_int ind) const
Get largest input value.
Definition: function.cpp:1484
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:569
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:1592
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:1934
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:961
const std::string & name() const
Name of the function.
Definition: function.cpp:1307
Dict cache() const
Get all functions in the cache.
Definition: function.cpp:1835
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:1916
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:1365
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in the expression graphs.
Definition: function.cpp:1870
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:1908
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:1777
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:1741
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:1492
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:1316
casadi_int checkout() const
Checkout a memory object.
Definition: function.cpp:1773
std::vector< MX > free_mx() const
Get all the free variables of the function.
Definition: function.cpp:1681
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:1765
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:574
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:1888
std::vector< casadi_int > instruction_output(casadi_int k) const
Location in the work vector for the output of the instruction.
Definition: function.cpp:1757
std::vector< double > nz_from_out(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
Definition: function.cpp:1604
SX instructions_sx() const
Get the SX node corresponding to all instructions (SXFunction)
Definition: function.cpp:1725
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:1800
MX instruction_MX(casadi_int k) const
Get the MX node corresponding to an instruction (MXFunction)
Definition: function.cpp:1717
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:1496
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:1576
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:1781
static std::vector< SX > order(const std::vector< SX > &expr)
Definition: function.cpp:1938
std::vector< std::string > get_free() const
Get free variables as a string.
Definition: function.cpp:1184
DMDict convert_in(const std::vector< DM > &arg) const
Convert from/to input/output lists/map.
Definition: function.cpp:1616
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:1624
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:1217
std::string generate(const std::string &fname, const Dict &opts=Dict()) const
Export / Generate C code for the function.
Definition: function.cpp:1192
bool is_a(const std::string &type, bool recursive=true) const
Check if the function is of a particular type.
Definition: function.cpp:1664
double min_in(casadi_int ind) const
Get smallest input value.
Definition: function.cpp:1488
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:1697
const std::vector< SX > sx_in() const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1568
Function wrap_as_needed(const Dict &opts) const
Wrap in a Function with options.
Definition: function.cpp:1920
bool operator==(const Function &f) const
Check if same as another function.
Definition: function.cpp:1924
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:1701
double instruction_constant(casadi_int k) const
Get the floating point output argument of an instruction (SXFunction)
Definition: function.cpp:1749
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:1861
Function()
Default constructor, null pointer.
Definition: function.cpp:58
static Function load(const std::string &filename)
Build function from serialization.
Definition: function.cpp:1349
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:1668
std::vector< DM > operator()(const std::vector< DM > &arg) const
Definition: function.cpp:1400
std::map< std::string, std::vector< double > * > MPrRes
Supported arguments for numerical evaluation and converters.
Definition: function.hpp:576
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:1608
void export_code(const std::string &lang, const std::string &fname, const Dict &options=Dict()) const
Export function in specific language.
Definition: function.cpp:1261
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:1612
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:567
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:1280
std::vector< SX > free_sx() const
Get all the free variables of the function.
Definition: function.cpp:1673
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
Definition: function.cpp:1812
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:1733
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:1793
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:1596
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:1480
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:2005
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)