26 #ifndef CASADI_FUNCTION_INTERNAL_HPP
27 #define CASADI_FUNCTION_INTERNAL_HPP
29 #include "function.hpp"
32 #include "code_generator.hpp"
33 #include "importer.hpp"
34 #include "options.hpp"
35 #include "shared_object.hpp"
37 #ifdef CASADI_WITH_THREAD
38 #ifdef CASADI_WITH_THREAD_MINGW
39 #include <mingw.mutex.h>
46 #define INPUTSCHEME(name)
49 #define OUTPUTSCHEME(name)
55 std::vector<std::pair<std::string, T>> zip(
const std::vector<std::string>&
id,
56 const std::vector<T>& mat) {
57 casadi_assert_dev(
id.size()==mat.size());
58 std::vector<std::pair<std::string, T>> r(
id.size());
59 for (casadi_uint i=0; i<r.size(); ++i) r[i] = std::make_pair(
id[i], mat[i]);
66 struct CASADI_EXPORT ProtoFunctionMemory {
68 std::map<std::string, FStats> fstats;
74 void add_stat(
const std::string& s) {
75 bool added = fstats.insert(std::make_pair(s, FStats())).second;
76 casadi_assert(added,
"Duplicate stat: '" + s +
"'");
83 struct CASADI_EXPORT FunctionMemory :
public ProtoFunctionMemory {
85 FunctionMemory() : stats_available(false) {}
94 class CASADI_EXPORT ProtoFunction :
public SharedObjectInternal {
99 ProtoFunction(
const std::string& name);
104 ~ProtoFunction()
override = 0;
111 void construct(
const Dict& opts);
117 static const Options options_;
118 virtual const Options& get_options()
const {
return options_;}
122 virtual Dict generate_options(
const std::string& target)
const;
127 void print_options(std::ostream &stream)
const;
132 void print_option(
const std::string &name, std::ostream &stream)
const;
137 bool has_option(
const std::string &option_name)
const;
142 virtual void change_option(
const std::string& option_name,
const GenericType& option_value);
152 virtual void init(
const Dict& opts);
160 virtual void finalize();
163 int checkout()
const;
166 void release(
int mem)
const;
169 void* memory(
int ind)
const;
172 bool has_memory(
int ind)
const;
179 virtual void check_mem_count(casadi_int n)
const { }
184 virtual void* alloc_mem()
const {
return new ProtoFunctionMemory(); }
189 virtual int init_mem(
void* mem)
const;
194 virtual void free_mem(
void *mem)
const {
delete static_cast<ProtoFunctionMemory*
>(mem); }
197 virtual Dict get_stats(
void* mem)
const;
207 void print(
const char* fmt, ...)
const;
212 void sprint(
char* buf,
size_t buf_sz,
const char* fmt, ...)
const;
217 void format_time(
char* buffer,
double time)
const;
222 void print_time(
const std::map<std::string, FStats>& fstats)
const;
227 void serialize(SerializingStream &s)
const;
232 virtual void serialize_body(SerializingStream &s)
const;
236 virtual void serialize_type(SerializingStream &s)
const {}
241 virtual std::string serialize_base_function()
const {
258 bool regularity_check_;
267 explicit ProtoFunction(DeserializingStream& s);
269 #ifdef CASADI_WITH_THREAD
271 mutable std::mutex mtx_;
276 mutable std::vector<void*> mem_;
279 mutable std::stack<int> unused_;
288 class CASADI_EXPORT FunctionInternal :
public ProtoFunction {
289 friend class Function;
294 FunctionInternal(
const std::string& name);
299 ~FunctionInternal()
override = 0;
304 virtual std::string getAdaptorSolverName()
const {
return ""; }
310 static const Options options_;
311 const Options& get_options()
const override {
return options_;}
315 Dict generate_options(
const std::string& target)
const override;
320 void change_option(
const std::string& option_name,
const GenericType& option_value)
override;
325 void reset_dump_count();
330 void init(
const Dict& opts)
override;
335 void finalize()
override;
340 void* alloc_mem()
const override {
return new FunctionMemory(); }
345 void free_mem(
void *mem)
const override {
delete static_cast<FunctionMemory*
>(mem); }
348 Dict get_stats(
void* mem)
const override;
353 Function
self()
const {
return shared_from_this<Function>();}
356 virtual Function factory(
const std::string& name,
357 const std::vector<std::string>& s_in,
358 const std::vector<std::string>& s_out,
360 const Dict& opts)
const;
363 virtual std::vector<std::string> get_function()
const;
366 virtual const Function& get_function(
const std::string &name)
const;
369 virtual bool has_function(
const std::string& fname)
const {
return false;}
372 void add_embedded(std::map<FunctionInternal*, std::pair<Function, size_t> >& all_fun,
373 const Function& dep, casadi_int max_depth)
const;
376 virtual void find(std::map<FunctionInternal*, std::pair<Function, size_t> >& all_fun,
377 casadi_int max_depth)
const;
387 virtual std::vector<bool> which_depends(
const std::string& s_in,
388 const std::vector<std::string>& s_out,
389 casadi_int order,
bool tr=
false)
const;
397 virtual Function simplify_passes(
398 const std::vector<std::pair<std::string, casadi_int> >& tasks)
const;
404 virtual bool has_spfwd()
const {
return false;}
405 virtual bool has_sprev()
const {
return false;}
412 int eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
413 bool always_inline,
bool never_inline)
const;
414 virtual int eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const;
420 virtual int eval_sx(
const SXElem** arg, SXElem** res,
421 casadi_int* iw, SXElem* w,
void* mem,
bool always_inline,
bool never_inline)
const;
427 bool always_inline,
bool never_inline)
const;
433 virtual std::vector<DM> eval_dm(
const std::vector<DM>& arg)
const;
434 virtual bool has_eval_dm()
const {
return false;}
441 int eval_gen(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w,
void* mem,
442 bool always_inline,
bool never_inline)
const {
443 return eval_sx(arg, res, iw, w, mem, always_inline, never_inline);
445 int eval_gen(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w,
void* mem,
446 bool always_inline,
bool never_inline)
const {
447 return sp_forward(arg, res, iw, w, mem);
456 bool always_inline,
bool never_inline)
const;
459 void call_gen(
const std::vector<Matrix<D> >& arg, std::vector<Matrix<D> >& res,
460 casadi_int npar,
bool always_inline,
bool never_inline)
const;
467 void call(
const std::vector<M>& arg, std::vector<M>& res,
468 bool always_inline,
bool never_inline)
const;
476 static bool check_mat(
const Sparsity& arg,
const Sparsity& inp, casadi_int& npar);
489 void check_arg(
const std::vector<M>& arg, casadi_int& npar)
const;
502 void check_res(
const std::vector<M>& res, casadi_int& npar)
const;
513 template<
typename M>
bool
514 matching_arg(
const std::vector<M>& arg, casadi_int& npar)
const;
524 template<
typename M>
bool
525 matching_res(
const std::vector<M>& arg, casadi_int& npar)
const;
530 template<
typename M> std::vector<M>
531 replace_arg(
const std::vector<M>& arg, casadi_int npar)
const;
536 template<
typename M> std::vector<M>
537 project_arg(
const std::vector<M>& arg, casadi_int npar)
const;
542 template<
typename M> std::vector<M>
543 project_res(
const std::vector<M>& arg, casadi_int npar)
const;
548 template<
typename M> std::vector<M>
549 replace_res(
const std::vector<M>& res, casadi_int npar)
const;
554 template<
typename M> std::vector<std::vector<M>>
555 replace_fseed(
const std::vector<std::vector<M>>& fseed, casadi_int npar)
const;
560 template<
typename M> std::vector<std::vector<M>>
561 replace_aseed(
const std::vector<std::vector<M>>& aseed, casadi_int npar)
const;
568 std::map<std::string, M> convert_arg(
const std::vector<M>& arg)
const;
570 std::vector<M> convert_arg(
const std::map<std::string, M>& arg)
const;
572 std::map<std::string, M> convert_res(
const std::vector<M>& res)
const;
574 std::vector<M> convert_res(
const std::map<std::string, M>& res)
const;
581 std::vector<double> nz_in(
const std::vector<DM>& arg)
const;
582 std::vector<double> nz_out(
const std::vector<DM>& res)
const;
583 std::vector<DM> nz_in(
const std::vector<double>& arg)
const;
584 std::vector<DM> nz_out(
const std::vector<double>& res)
const;
591 virtual void call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
592 const std::vector<std::vector<MX> >& fseed,
593 std::vector<std::vector<MX> >& fsens,
594 bool always_inline,
bool never_inline)
const;
595 virtual void call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
596 const std::vector<std::vector<SX> >& fseed,
597 std::vector<std::vector<SX> >& fsens,
598 bool always_inline,
bool never_inline)
const;
605 virtual void call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
606 const std::vector<std::vector<MX> >& aseed,
607 std::vector<std::vector<MX> >& asens,
608 bool always_inline,
bool never_inline)
const;
609 virtual void call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
610 const std::vector<std::vector<SX> >& aseed,
611 std::vector<std::vector<SX> >& asens,
612 bool always_inline,
bool never_inline)
const;
618 std::vector<MX> mapsum_mx(
const std::vector<MX > &arg,
const std::string& parallelization);
623 virtual bool uses_output()
const {
return false;}
629 Function jacobian()
const;
630 virtual bool has_jacobian()
const {
return false;}
631 virtual Function get_jacobian(
const std::string& name,
632 const std::vector<std::string>& inames,
633 const std::vector<std::string>& onames,
634 const Dict& opts)
const;
642 Sparsity& jac_sparsity(casadi_int oind, casadi_int iind,
bool compact,
bool symmetric)
const;
643 virtual bool has_jac_sparsity(casadi_int oind, casadi_int iind)
const {
return false;}
644 virtual Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind,
bool symmetric)
const;
648 static std::string forward_name(
const std::string& fcn, casadi_int nfwd) {
649 return "fwd" + str(nfwd) +
"_" + fcn;
653 std::string diff_prefix(
const std::string& prefix)
const;
663 Function forward(casadi_int nfwd)
const;
664 virtual bool has_forward(casadi_int nfwd)
const {
return false;}
665 virtual Function get_forward(casadi_int nfwd,
const std::string& name,
666 const std::vector<std::string>& inames,
667 const std::vector<std::string>& onames,
668 const Dict& opts)
const;
672 static std::string reverse_name(
const std::string& fcn, casadi_int nadj) {
673 return "adj" + str(nadj) +
"_" + fcn;
684 Function reverse(casadi_int nadj)
const;
685 virtual bool has_reverse(casadi_int nadj)
const {
return false;}
686 virtual Function get_reverse(casadi_int nadj,
const std::string& name,
687 const std::vector<std::string>& inames,
688 const std::vector<std::string>& onames,
689 const Dict& opts)
const;
695 template<
typename MatType>
696 static MatType ensure_stacked(
const MatType& v,
const Sparsity& sp, casadi_int n);
701 virtual Function slice(
const std::string& name,
const std::vector<casadi_int>& order_in,
702 const std::vector<casadi_int>& order_out,
const Dict& opts)
const;
707 virtual const Function& oracle()
const;
712 bool has_derivative()
const;
717 virtual double ad_weight()
const;
724 virtual double sp_weight()
const;
730 virtual const SX sx_in(casadi_int ind)
const;
731 virtual const SX sx_out(casadi_int ind)
const;
732 virtual const std::vector<SX> sx_in()
const;
733 virtual const std::vector<SX> sx_out()
const;
734 virtual const MX mx_in(casadi_int ind)
const;
735 virtual const MX mx_out(casadi_int ind)
const;
736 virtual const std::vector<MX> mx_in()
const;
737 virtual const std::vector<MX> mx_out()
const;
738 const DM dm_in(casadi_int ind)
const;
739 const DM dm_out(casadi_int ind)
const;
740 const std::vector<DM> dm_in()
const;
741 const std::vector<DM> dm_out()
const;
745 virtual std::vector<MX> free_mx()
const;
748 virtual std::vector<SX> free_sx()
const;
753 virtual bool has_free()
const {
return false;}
758 virtual void generate_lifted(Function& vdef_fcn, Function& vinit_fcn)
const;
763 virtual casadi_int n_instructions()
const;
768 virtual casadi_int instruction_id(casadi_int k)
const;
773 virtual std::vector<casadi_int> instruction_input(casadi_int k)
const;
778 virtual double instruction_constant(casadi_int k)
const;
783 virtual std::vector<casadi_int> instruction_output(casadi_int k)
const;
788 virtual casadi_int n_nodes()
const;
793 virtual MX instruction_MX(casadi_int k)
const;
798 virtual SX instructions_sx()
const;
804 Function wrap(
const std::string& name)
const;
805 Function wrap()
const;
812 Function wrap_as_needed(
const std::string& name,
const Dict& opts)
const;
813 Function wrap_as_needed(
const Dict& opts)
const;
824 bool incache(
const std::string& fname, Function& f,
const std::string& suffix=
"")
const;
829 void tocache(
const Function& f,
const std::string& suffix=
"")
const;
835 void tocache_if_missing(Function& f,
const std::string& suffix=
"")
const;
840 void codegen(CodeGenerator& g,
const std::string& fname)
const;
845 void codegen_meta(CodeGenerator& g)
const;
850 void codegen_sparsities(CodeGenerator& g)
const;
855 virtual std::string codegen_name(
const CodeGenerator& g,
bool ns=
true)
const;
860 std::string codegen_mem(CodeGenerator& g,
const std::string& index=
"mem")
const;
865 virtual void codegen_incref(CodeGenerator& g)
const;
870 virtual void codegen_decref(CodeGenerator& g)
const;
875 virtual void codegen_alloc_mem(CodeGenerator& g)
const;
880 virtual void codegen_init_mem(CodeGenerator& g)
const;
885 virtual void codegen_free_mem(CodeGenerator& g)
const {}
890 virtual void codegen_checkout(CodeGenerator& g)
const;
895 virtual void codegen_release(CodeGenerator& g)
const;
900 std::string signature(
const std::string& fname)
const;
905 std::string signature_unrolled(
const std::string& fname)
const;
910 virtual void codegen_declarations(CodeGenerator& g)
const;
915 virtual void codegen_body(CodeGenerator& g)
const;
920 virtual std::string codegen_mem_type()
const {
return ""; }
925 virtual bool codegen_needs_mem()
const {
return false; }
932 virtual bool codegen_mem_is_opaque()
const {
return false; }
937 virtual std::string generate_dependencies(
const std::string& fname,
const Dict& opts)
const;
942 virtual bool has_codegen()
const {
return false;}
947 virtual void jit_dependencies(
const std::string& fname) {}
952 static std::string get_jit_directory(
const Dict& jit_options);
957 virtual void export_code(
const std::string& lang,
958 std::ostream &stream,
const Dict& options)
const;
963 void serialize_type(SerializingStream &s)
const override;
968 void serialize_body(SerializingStream &s)
const override;
973 void disp(std::ostream& stream,
bool more)
const override;
978 virtual void disp_more(std::ostream& stream)
const {}
983 std::string definition()
const;
988 void print_dimensions(std::ostream &stream)
const;
993 virtual std::vector<std::string> get_free()
const;
998 void get_partition(casadi_int iind, casadi_int oind, Sparsity& D1, Sparsity& D2,
999 bool compact,
bool symmetric,
1000 bool allow_forward,
bool allow_reverse)
const;
1006 casadi_int nnz_in()
const;
1007 casadi_int nnz_in(casadi_int ind)
const {
return sparsity_in(ind).nnz(); }
1008 casadi_int nnz_out()
const;
1009 casadi_int nnz_out(casadi_int ind)
const {
return sparsity_out(ind).nnz(); }
1016 casadi_int numel_in()
const;
1017 casadi_int numel_in(casadi_int ind)
const {
return sparsity_in(ind).numel(); }
1018 casadi_int numel_out(casadi_int ind)
const {
return sparsity_out(ind).numel(); }
1019 casadi_int numel_out()
const;
1026 casadi_int size1_in(casadi_int ind)
const {
return sparsity_in(ind).size1(); }
1027 casadi_int size2_in(casadi_int ind)
const {
return sparsity_in(ind).size2(); }
1028 casadi_int size1_out(casadi_int ind)
const {
return sparsity_out(ind).size1(); }
1029 casadi_int size2_out(casadi_int ind)
const {
return sparsity_out(ind).size2(); }
1030 std::pair<casadi_int, casadi_int> size_in(casadi_int ind)
const {
1031 return sparsity_in(ind).size();
1033 std::pair<casadi_int, casadi_int> size_out(casadi_int ind)
const {
1034 return sparsity_out(ind).size();
1042 const Sparsity& sparsity_in(casadi_int ind)
const {
return sparsity_in_.at(ind); }
1043 const Sparsity& sparsity_out(casadi_int ind)
const {
return sparsity_out_.at(ind); }
1050 bool all_scalar()
const;
1053 virtual bool jac_is_symm(casadi_int oind, casadi_int iind)
const;
1056 Sparsity to_compact(casadi_int oind, casadi_int iind,
const Sparsity& sp)
const;
1059 Sparsity from_compact(casadi_int oind, casadi_int iind,
const Sparsity& sp)
const;
1063 Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind)
const;
1066 Sparsity get_jac_sparsity_hierarchical(casadi_int oind, casadi_int iind)
const;
1071 Sparsity get_jac_sparsity_hierarchical_symm(casadi_int oind, casadi_int iind)
const;
1074 virtual std::vector<MX> symbolic_output(
const std::vector<MX>& arg)
const;
1080 virtual size_t get_n_in();
1081 virtual size_t get_n_out();
1089 virtual std::string get_name_in(casadi_int i);
1090 virtual std::string get_name_out(casadi_int i);
1096 virtual double get_default_in(casadi_int ind)
const {
1103 virtual double get_max_in(casadi_int ind)
const {
1110 virtual double get_min_in(casadi_int ind)
const {
1114 virtual std::vector<double> get_nominal_in(casadi_int ind)
const {
1115 return std::vector<double>(nnz_in(ind), 1.);
1118 virtual std::vector<double> get_nominal_out(casadi_int ind)
const {
1119 return std::vector<double>(nnz_out(ind), 1.);
1125 virtual double get_reltol()
const {
1132 virtual double get_abstol()
const {
1139 virtual Sparsity get_sparsity_in(casadi_int i);
1144 virtual Sparsity get_sparsity_out(casadi_int i);
1149 virtual bool get_diff_in(casadi_int i) {
return true; }
1154 virtual bool get_diff_out(casadi_int i) {
return true; }
1159 casadi_int index_in(
const std::string &name)
const {
1160 for (casadi_int i=0; i<name_in_.size(); ++i) {
1161 if (name_in_[i]==name)
return i;
1163 casadi_error(
"FunctionInternal::index_in: could not find entry \""
1164 + name +
"\". Available names are: " + str(name_in_) +
".");
1171 casadi_int index_out(
const std::string &name)
const {
1172 for (casadi_int i=0; i<name_out_.size(); ++i) {
1173 if (name_out_[i]==name)
return i;
1175 casadi_error(
"FunctionInternal::index_out: could not find entry \""
1176 + name +
"\". Available names are: " + str(name_out_) +
".");
1183 virtual int sp_forward(
const bvec_t** arg, bvec_t** res,
1184 casadi_int* iw, bvec_t* w,
void* mem)
const;
1193 virtual int eval_activity(
const bvec_t** arg, bvec_t** res,
1194 casadi_int* iw, bvec_t* w,
void* mem)
const;
1199 virtual int sp_forward_block(
const bvec_t** arg, bvec_t** res,
1200 casadi_int* iw, bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const;
1205 virtual int sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w,
void* mem)
const;
1210 void sz_work(
size_t& sz_arg,
size_t& sz_res,
size_t& sz_iw,
size_t& sz_w)
const;
1215 size_t sz_arg()
const {
return sz_arg_per_ + sz_arg_tmp_;}
1220 size_t sz_res()
const {
return sz_res_per_ + sz_res_tmp_;}
1225 size_t sz_iw()
const {
return sz_iw_per_ + sz_iw_tmp_;}
1230 size_t sz_w()
const {
return sz_w_per_ + sz_w_tmp_;}
1236 virtual size_t codegen_sz_arg(
const CodeGenerator& g)
const;
1237 virtual size_t codegen_sz_res(
const CodeGenerator& g)
const;
1238 virtual size_t codegen_sz_iw(
const CodeGenerator& g)
const;
1239 virtual size_t codegen_sz_w(
const CodeGenerator& g)
const;
1245 void alloc_arg(
size_t sz_arg,
bool persistent=
false);
1250 void alloc_res(
size_t sz_res,
bool persistent=
false);
1255 void alloc_iw(
size_t sz_iw,
bool persistent=
false);
1260 void alloc_w(
size_t sz_w,
bool persistent=
false);
1265 void alloc(
const Function& f,
bool persistent=
false,
int num_threads=1);
1270 virtual void set_work(
void* mem,
const double**& arg,
double**& res,
1271 casadi_int*& iw,
double*& w)
const {}
1276 virtual void set_temp(
void* mem,
const double** arg,
double** res,
1277 casadi_int* iw,
double* w)
const {}
1282 void setup(
void* mem,
const double** arg,
double** res, casadi_int* iw,
double* w)
const;
1288 virtual bool fwdViaJac(casadi_int nfwd)
const;
1289 virtual bool adjViaJac(casadi_int nadj)
const;
1293 virtual Dict info()
const;
1298 Function map(casadi_int n,
const std::string& parallelization)
const;
1303 void generate_in(
const std::string& fname,
const double** arg)
const;
1304 void generate_out(
const std::string& fname,
double** res)
const;
1306 bool always_inline_, never_inline_;
1309 size_t n_in_, n_out_;
1312 std::vector<bool> is_diff_in_, is_diff_out_;
1315 std::vector<Sparsity> sparsity_in_, sparsity_out_;
1318 std::vector<std::string> name_in_, name_out_;
1333 std::string jit_serialize_;
1338 std::string jit_name_;
1339 std::string jit_directory_;
1340 std::string jit_base_name_;
1345 bool jit_temp_suffix_;
1355 casadi_checkout_t checkout_;
1360 casadi_release_t release_;
1365 signal_t incref_, decref_;
1380 bool has_refcount_in_deps_;
1388 mutable WeakCache<std::string, Function> cache_;
1391 mutable std::vector<Sparsity> jac_sparsity_[2];
1393 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
1395 mutable std::mutex jac_sparsity_mtx_;
1399 Function derivative_of_;
1405 std::string compiler_plugin_;
1410 double jac_penalty_;
1413 bool enable_forward_, enable_reverse_, enable_jacobian_, enable_fd_;
1414 bool enable_forward_op_, enable_reverse_op_, enable_jacobian_op_, enable_fd_op_;
1417 double ad_weight_, ad_weight_sp_;
1420 casadi_int max_num_dir_;
1432 std::string fd_method_;
1439 bool print_canonical_;
1445 bool dump_in_, dump_out_, dump_;
1448 std::string dump_dir_;
1451 std::string dump_format_;
1454 Dict forward_options_, reverse_options_, jacobian_options_, der_options_;
1457 Function custom_jacobian_;
1460 std::vector<Function> registered_functions_;
1463 #ifdef CASADI_WITH_THREAD
1464 mutable std::atomic<casadi_int> dump_count_;
1466 mutable casadi_int dump_count_;
1472 virtual bool is_a(
const std::string& type,
bool recursive)
const;
1477 virtual void merge(
const std::vector<MX>& arg,
1478 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const;
1483 template<
typename MatType>
1484 static bool purgable(
const std::vector<MatType>& seed);
1489 template<
typename MatType>
1490 std::vector<std::vector<MatType> >
1491 fwd_seed(casadi_int nfwd)
const;
1496 template<
typename MatType>
1497 std::vector<std::vector<MatType> >
1498 symbolicAdjSeed(casadi_int nadj,
const std::vector<MatType>& v)
const;
1505 explicit FunctionInternal(DeserializingStream& e);
1510 static Function deserialize(DeserializingStream& s);
1511 static std::map<std::string, ProtoFunction* (*)(DeserializingStream&)> deserialize_map;
1516 void print_in(std::ostream &stream,
const double** arg,
bool truncate)
const;
1521 void print_out(std::ostream &stream,
double** res,
bool truncate)
const;
1526 static void print_canonical(std::ostream &stream,
const Sparsity& sp,
const double* nz);
1531 static void print_canonical(std::ostream &stream, casadi_int sz,
const double* nz);
1536 static void print_canonical(std::ostream &stream,
double a);
1542 void set_jac_sparsity(casadi_int oind, casadi_int iind,
const Sparsity& sp);
1547 casadi_int get_dump_id()
const;
1548 void dump_in(casadi_int
id,
const double** arg)
const;
1549 void dump_out(casadi_int
id,
double** res)
const;
1556 size_t sz_arg_per_, sz_res_per_, sz_iw_per_, sz_w_per_;
1561 size_t sz_arg_tmp_, sz_res_tmp_, sz_iw_tmp_, sz_w_tmp_;
1565 template<
typename MatType>
1566 bool FunctionInternal::purgable(
const std::vector<MatType>& v) {
1567 for (
auto i=v.begin(); i!=v.end(); ++i) {
1568 if (!i->is_zero())
return false;
1573 template<
typename MatType>
1574 std::vector<std::vector<MatType> >
1576 fwd_seed(casadi_int nfwd)
const {
1577 std::vector<std::vector<MatType>> fseed(nfwd);
1578 for (casadi_int dir=0; dir<nfwd; ++dir) {
1579 fseed[dir].resize(n_in_);
1580 for (casadi_int iind=0; iind<n_in_; ++iind) {
1581 std::string n =
"f" + str(dir) +
"_" + name_in_[iind];
1582 Sparsity sp = is_diff_in_[iind] ? sparsity_in(iind) : Sparsity(size_in(iind));
1583 fseed[dir][iind] = MatType::sym(n, sp);
1589 template<
typename MatType>
1590 std::vector<std::vector<MatType> >
1592 symbolicAdjSeed(casadi_int nadj,
const std::vector<MatType>& v)
const {
1593 std::vector<std::vector<MatType> > aseed(nadj, v);
1594 for (casadi_int dir=0; dir<nadj; ++dir) {
1597 for (
typename std::vector<MatType>::iterator i=aseed[dir].begin();
1598 i!=aseed[dir].end();
1601 std::stringstream ss;
1603 if (nadj>1) ss << dir <<
"_";
1607 *i = MatType::sym(ss.str(), is_diff_out_[oind] ? i->sparsity() : Sparsity(i->size()));
1614 template<
typename M>
1615 void FunctionInternal::call(
const std::vector<M>& arg, std::vector<M>& res,
1616 bool always_inline,
bool never_inline)
const {
1620 bool matrix_call =
false;
1621 std::pair<casadi_int, casadi_int> sz;
1622 for (
auto&& a : arg) {
1623 if (!a.is_scalar() && !a.is_empty()) {
1628 }
else if (a.size()!=sz) {
1630 matrix_call =
false;
1641 for (
auto&& a : res) a = z;
1643 std::vector<M> arg1 = arg, res1;
1644 for (casadi_int c=0; c<sz.second; ++c) {
1645 for (casadi_int r=0; r<sz.first; ++r) {
1647 for (casadi_int i=0; i<arg.size(); ++i) {
1648 if (arg[i].size()==sz) arg1[i] = arg[i](r, c);
1651 call(arg1, res1, always_inline, never_inline);
1653 casadi_assert_dev(res.size() == res1.size());
1654 for (casadi_int i=0; i<res.size(); ++i) res[i](r, c) = res1[i];
1663 casadi_int npar = 1;
1664 if (!matching_arg(arg, npar)) {
1665 return call(replace_arg(arg, npar), res, always_inline, never_inline);
1669 call_gen(arg, res, npar, always_inline, never_inline);
1672 template<
typename M>
1673 std::vector<M> FunctionInternal::
1674 project_arg(
const std::vector<M>& arg, casadi_int npar)
const {
1675 casadi_assert_dev(arg.size()==n_in_);
1678 std::vector<bool> mapped(n_in_);
1679 for (casadi_int i=0; i<n_in_; ++i) {
1680 mapped[i] = arg[i].size2()!=size2_in(i);
1684 std::vector<bool> matching(n_in_);
1685 bool any_mismatch =
false;
1686 for (casadi_int i=0; i<n_in_; ++i) {
1688 matching[i] = arg[i].sparsity().is_stacked(sparsity_in(i), npar);
1690 matching[i] = arg[i].sparsity()==sparsity_in(i);
1692 any_mismatch = any_mismatch || !matching[i];
1697 std::vector<M> arg2(arg);
1698 for (casadi_int i=0; i<n_in_; ++i) {
1701 arg2[i] = project(arg2[i], repmat(sparsity_in(i), 1, npar));
1703 arg2[i] = project(arg2[i], sparsity_in(i));
1712 template<
typename M>
1713 std::vector<M> FunctionInternal::
1714 project_res(
const std::vector<M>& arg, casadi_int npar)
const {
1718 template<
typename D>
1719 void FunctionInternal::
1720 call_gen(
const std::vector<Matrix<D> >& arg, std::vector<Matrix<D> >& res,
1721 casadi_int npar,
bool always_inline,
bool never_inline)
const {
1722 std::vector< Matrix<D> > arg2 = project_arg(arg, npar);
1725 std::vector<bool> mapped(n_in_);
1726 for (casadi_int i=0; i<n_in_; ++i) {
1727 mapped[i] = arg[i].size2()!=size2_in(i);
1732 for (casadi_int i=0; i<n_out_; ++i) {
1733 if (!res[i].sparsity().is_stacked(sparsity_out(i), npar)) {
1739 std::vector<casadi_int> iw_tmp(sz_iw());
1740 std::vector<D> w_tmp(sz_w());
1743 std::vector<const D*> argp(sz_arg());
1744 for (casadi_int i=0; i<n_in_; ++i) argp[i]=get_ptr(arg2[i]);
1747 std::vector<D*> resp(sz_res());
1748 for (casadi_int i=0; i<n_out_; ++i) resp[i]=get_ptr(res[i]);
1751 for (casadi_int p=0; p<npar; ++p) {
1753 if (eval_gen(get_ptr(argp), get_ptr(resp),
1754 get_ptr(iw_tmp), get_ptr(w_tmp), memory(0),
1755 always_inline, never_inline)) {
1756 if (error_on_fail_) casadi_error(
"Evaluation failed");
1759 if (p==npar-1)
break;
1760 for (casadi_int i=0; i<n_in_; ++i)
if (mapped[i]) argp[i] += nnz_in(i);
1761 for (casadi_int i=0; i<n_out_; ++i) resp[i] += nnz_out(i);
1765 template<
typename M>
1766 void FunctionInternal::check_arg(
const std::vector<M>& arg, casadi_int& npar)
const {
1767 casadi_assert(arg.size()==n_in_,
"Incorrect number of inputs: Expected "
1768 + str(n_in_) +
", got " + str(arg.size()));
1769 for (casadi_int i=0; i<n_in_; ++i) {
1770 if (!check_mat(arg[i].sparsity(), sparsity_in(i), npar)) {
1772 std::string d_arg = str(arg[i].size1()) +
"-by-" + str(arg[i].size2());
1773 std::string d_in = str(size1_in(i)) +
"-by-" + str(size2_in(i));
1774 std::string e =
"Input " + str(i) +
" (" + name_in_[i] +
") has mismatching shape. "
1775 "Got " + d_arg +
". Allowed dimensions, in general, are:\n"
1776 " - The input dimension N-by-M (here " + d_in +
")\n"
1777 " - A scalar, i.e. 1-by-1\n"
1778 " - M-by-N if N=1 or M=1 (i.e. a transposed vector)\n"
1779 " - N-by-M1 if K*M1=M for some K (argument repeated horizontally)\n";
1781 e +=
" - N-by-P*M, indicating evaluation with multiple arguments (P must be a "
1782 "multiple of " + str(npar) +
" for consistency with previous inputs)";
1789 template<
typename M>
1790 void FunctionInternal::check_res(
const std::vector<M>& res, casadi_int& npar)
const {
1791 casadi_assert(res.size()==n_out_,
"Incorrect number of outputs: Expected "
1792 + str(n_out_) +
", got " + str(res.size()));
1793 for (casadi_int i=0; i<n_out_; ++i) {
1794 casadi_assert(check_mat(res[i].sparsity(), sparsity_out(i), npar),
1795 "Output " + str(i) +
" (" + name_out_[i] +
") has mismatching shape. "
1796 "Expected " + str(size_out(i)) +
", got " + str(res[i].size()));
1800 template<
typename M>
1801 bool FunctionInternal::matching_arg(
const std::vector<M>& arg, casadi_int& npar)
const {
1802 check_arg(arg, npar);
1803 for (casadi_int i=0; i<n_in_; ++i) {
1804 if (arg.at(i).size1()!=size1_in(i))
return false;
1805 if (arg.at(i).size2()!=size2_in(i) && arg.at(i).size2()!=npar*size2_in(i))
return false;
1810 template<
typename M>
1811 bool FunctionInternal::matching_res(
const std::vector<M>& res, casadi_int& npar)
const {
1812 check_res(res, npar);
1813 for (casadi_int i=0; i<n_out_; ++i) {
1814 if (res.at(i).size1()!=size1_out(i))
return false;
1815 if (res.at(i).size2()!=size2_out(i) && res.at(i).size2()!=npar*size2_out(i))
return false;
1820 template<
typename M>
1821 M replace_mat(
const M& arg,
const Sparsity& inp, casadi_int npar) {
1822 if (arg.size()==inp.size()) {
1825 }
else if (arg.is_scalar()) {
1828 }
else if (arg.is_vector() && inp.size()==std::make_pair(arg.size2(), arg.size1())) {
1831 }
else if (arg.size1()==inp.size1() && arg.size2()>0 && inp.size2()>0
1832 && inp.size2()%arg.size2()==0) {
1834 return repmat(arg, 1, inp.size2()/arg.size2());
1835 }
else if (npar!=-1 && arg.size1()==inp.size1() && arg.size2()>0 && inp.size2()>0
1836 && (npar*inp.size2())%arg.size2()==0) {
1838 return repmat(arg, 1, (npar*inp.size2())/arg.size2());
1842 casadi_assert_dev(arg.is_empty());
1843 return M(inp.size());
1847 template<
typename M>
1848 std::vector<M> FunctionInternal::
1849 replace_arg(
const std::vector<M>& arg, casadi_int npar)
const {
1850 std::vector<M> r(arg.size());
1851 for (casadi_int i=0; i<r.size(); ++i) r[i] = replace_mat(arg[i], sparsity_in(i), npar);
1855 template<
typename M>
1856 std::vector<M> FunctionInternal::
1857 replace_res(
const std::vector<M>& res, casadi_int npar)
const {
1858 std::vector<M> r(res.size());
1859 for (casadi_int i=0; i<r.size(); ++i) r[i] = replace_mat(res[i], sparsity_out(i), npar);
1863 template<
typename M>
1864 std::vector<std::vector<M> > FunctionInternal::
1865 replace_fseed(
const std::vector<std::vector<M> >& fseed, casadi_int npar)
const {
1866 std::vector<std::vector<M> > r(fseed.size());
1867 for (casadi_int d=0; d<r.size(); ++d) r[d] = replace_arg(fseed[d], npar);
1871 template<
typename M>
1872 std::vector<std::vector<M> > FunctionInternal::
1873 replace_aseed(
const std::vector<std::vector<M> >& aseed, casadi_int npar)
const {
1874 std::vector<std::vector<M> > r(aseed.size());
1875 for (casadi_int d=0; d<r.size(); ++d) r[d] = replace_res(aseed[d], npar);
1879 template<
typename M>
1880 std::map<std::string, M> FunctionInternal::
1881 convert_arg(
const std::vector<M>& arg)
const {
1882 casadi_assert(arg.size()==n_in_,
"Incorrect number of inputs: Expected "
1883 + str(n_in_) +
", got " + str(arg.size()));
1884 std::map<std::string, M> ret;
1885 for (casadi_int i=0;i<n_in_;++i) {
1886 ret[name_in_[i]] = arg[i];
1891 template<
typename M>
1892 std::vector<M> FunctionInternal::
1893 convert_arg(
const std::map<std::string, M>& arg)
const {
1895 std::vector<M> arg_v(n_in_);
1896 for (casadi_int i=0; i<arg_v.size(); ++i) {
1897 arg_v[i] = get_default_in(i);
1901 for (
auto&& e : arg) {
1902 arg_v.at(index_in(e.first)) = e.second;
1908 template<
typename M>
1909 std::map<std::string, M> FunctionInternal::
1910 convert_res(
const std::vector<M>& res)
const {
1911 casadi_assert(res.size()==n_out_,
"Incorrect number of outputs: Expected "
1912 + str(n_out_) +
", got " + str(res.size()));
1913 std::map<std::string, M> ret;
1914 for (casadi_int i=0;i<n_out_;++i) {
1915 ret[name_out_[i]] = res[i];
1920 template<
typename M>
1921 std::vector<M> FunctionInternal::
1922 convert_res(
const std::map<std::string, M>& res)
const {
1924 std::vector<M> res_v(n_out_);
1925 for (casadi_int i=0; i<res_v.size(); ++i) {
1926 res_v[i] = std::numeric_limits<double>::quiet_NaN();
1930 for (
auto&& e : res) {
1932 res_v.at(index_out(e.first)) = a;
1937 template<
typename MatType>
1938 MatType FunctionInternal::ensure_stacked(
const MatType& v,
const Sparsity& sp, casadi_int n) {
1940 if (v.size1() == sp.size1() && v.size2() == n * sp.size2()) {
1942 if (v.nnz() != 0 && !v.sparsity().is_stacked(sp, n)) {
1943 return project(v, repmat(sp, 1, n));
1947 casadi_assert_dev(v.is_empty());
1948 return MatType(sp.size1(), sp.size2() * n);
std::map< std::string, std::vector< std::string > > AuxOut
static Matrix< Scalar > zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
std::vector< MX > MXVector
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.