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_internal.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 {
92 class CASADI_EXPORT ProtoFunction :
public SharedObjectInternal {
97 ProtoFunction(
const std::string& name);
102 ~ProtoFunction()
override = 0;
109 void construct(
const Dict& opts);
115 static const Options options_;
116 virtual const Options& get_options()
const {
return options_;}
120 virtual Dict generate_options(
const std::string& target)
const;
125 void print_options(std::ostream &stream)
const;
130 void print_option(
const std::string &name, std::ostream &stream)
const;
135 bool has_option(
const std::string &option_name)
const;
140 virtual void change_option(
const std::string& option_name,
const GenericType& option_value);
150 virtual void init(
const Dict& opts);
158 virtual void finalize();
161 int checkout()
const;
164 void release(
int mem)
const;
167 void* memory(
int ind)
const;
172 virtual void* alloc_mem()
const {
return new ProtoFunctionMemory(); }
177 virtual int init_mem(
void* mem)
const;
182 virtual void free_mem(
void *mem)
const {
delete static_cast<ProtoFunctionMemory*
>(mem); }
185 virtual Dict get_stats(
void* mem)
const;
195 void print(
const char* fmt, ...)
const;
200 void sprint(
char* buf,
size_t buf_sz,
const char* fmt, ...)
const;
205 void format_time(
char* buffer,
double time)
const;
210 void print_time(
const std::map<std::string, FStats>& fstats)
const;
215 void serialize(SerializingStream &s)
const;
220 virtual void serialize_body(SerializingStream &s)
const;
224 virtual void serialize_type(SerializingStream &s)
const {}
229 virtual std::string serialize_base_function()
const {
246 bool regularity_check_;
255 explicit ProtoFunction(DeserializingStream& s);
257 #ifdef CASADI_WITH_THREAD
259 mutable std::mutex mtx_;
264 mutable std::vector<void*> mem_;
267 mutable std::stack<int> unused_;
276 class CASADI_EXPORT FunctionInternal :
public ProtoFunction {
277 friend class Function;
282 FunctionInternal(
const std::string& name);
287 ~FunctionInternal()
override = 0;
292 virtual std::string getAdaptorSolverName()
const {
return ""; }
298 static const Options options_;
299 const Options& get_options()
const override {
return options_;}
303 Dict generate_options(
const std::string& target)
const override;
308 void change_option(
const std::string& option_name,
const GenericType& option_value)
override;
313 void init(
const Dict& opts)
override;
318 void finalize()
override;
323 Function
self()
const {
return shared_from_this<Function>();}
326 virtual Function factory(
const std::string& name,
327 const std::vector<std::string>& s_in,
328 const std::vector<std::string>& s_out,
330 const Dict& opts)
const;
333 virtual std::vector<std::string> get_function()
const;
336 virtual const Function& get_function(
const std::string &name)
const;
339 virtual bool has_function(
const std::string& fname)
const {
return false;}
342 void add_embedded(std::map<FunctionInternal*, Function>& all_fun,
343 const Function& dep, casadi_int max_depth)
const;
346 virtual void find(std::map<FunctionInternal*, Function>& all_fun, casadi_int max_depth)
const {}
356 virtual std::vector<bool> which_depends(
const std::string& s_in,
357 const std::vector<std::string>& s_out,
358 casadi_int order,
bool tr=
false)
const;
364 virtual bool has_spfwd()
const {
return false;}
365 virtual bool has_sprev()
const {
return false;}
372 int eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const;
373 virtual int eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const;
379 virtual int eval_sx(
const SXElem** arg, SXElem** res,
380 casadi_int* iw, SXElem* w,
void* mem)
const;
386 bool always_inline,
bool never_inline)
const;
392 virtual std::vector<DM> eval_dm(
const std::vector<DM>& arg)
const;
393 virtual bool has_eval_dm()
const {
return false;}
400 int eval_gen(
const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w,
void* mem)
const {
401 return eval_sx(arg, res, iw, w, mem);
403 int eval_gen(
const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w,
void* mem)
const {
404 return sp_forward(arg, res, iw, w, mem);
413 bool always_inline,
bool never_inline)
const;
416 void call_gen(
const std::vector<Matrix<D> >& arg, std::vector<Matrix<D> >& res,
417 casadi_int npar,
bool always_inline,
bool never_inline)
const;
424 void call(
const std::vector<M>& arg, std::vector<M>& res,
425 bool always_inline,
bool never_inline)
const;
433 static bool check_mat(
const Sparsity& arg,
const Sparsity& inp, casadi_int& npar);
446 void check_arg(
const std::vector<M>& arg, casadi_int& npar)
const;
459 void check_res(
const std::vector<M>& res, casadi_int& npar)
const;
470 template<
typename M>
bool
471 matching_arg(
const std::vector<M>& arg, casadi_int& npar)
const;
481 template<
typename M>
bool
482 matching_res(
const std::vector<M>& arg, casadi_int& npar)
const;
487 template<
typename M> std::vector<M>
488 replace_arg(
const std::vector<M>& arg, casadi_int npar)
const;
493 template<
typename M> std::vector<M>
494 project_arg(
const std::vector<M>& arg, casadi_int npar)
const;
499 template<
typename M> std::vector<M>
500 project_res(
const std::vector<M>& arg, casadi_int npar)
const;
505 template<
typename M> std::vector<M>
506 replace_res(
const std::vector<M>& res, casadi_int npar)
const;
511 template<
typename M> std::vector<std::vector<M>>
512 replace_fseed(
const std::vector<std::vector<M>>& fseed, casadi_int npar)
const;
517 template<
typename M> std::vector<std::vector<M>>
518 replace_aseed(
const std::vector<std::vector<M>>& aseed, casadi_int npar)
const;
525 std::map<std::string, M> convert_arg(
const std::vector<M>& arg)
const;
527 std::vector<M> convert_arg(
const std::map<std::string, M>& arg)
const;
529 std::map<std::string, M> convert_res(
const std::vector<M>& res)
const;
531 std::vector<M> convert_res(
const std::map<std::string, M>& res)
const;
538 std::vector<double> nz_in(
const std::vector<DM>& arg)
const;
539 std::vector<double> nz_out(
const std::vector<DM>& res)
const;
540 std::vector<DM> nz_in(
const std::vector<double>& arg)
const;
541 std::vector<DM> nz_out(
const std::vector<double>& res)
const;
548 virtual void call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
549 const std::vector<std::vector<MX> >& fseed,
550 std::vector<std::vector<MX> >& fsens,
551 bool always_inline,
bool never_inline)
const;
552 virtual void call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
553 const std::vector<std::vector<SX> >& fseed,
554 std::vector<std::vector<SX> >& fsens,
555 bool always_inline,
bool never_inline)
const;
562 virtual void call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
563 const std::vector<std::vector<MX> >& aseed,
564 std::vector<std::vector<MX> >& asens,
565 bool always_inline,
bool never_inline)
const;
566 virtual void call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
567 const std::vector<std::vector<SX> >& aseed,
568 std::vector<std::vector<SX> >& asens,
569 bool always_inline,
bool never_inline)
const;
575 std::vector<MX> mapsum_mx(
const std::vector<MX > &arg,
const std::string& parallelization);
580 virtual bool uses_output()
const {
return false;}
586 Function jacobian()
const;
587 virtual bool has_jacobian()
const {
return false;}
588 virtual Function get_jacobian(
const std::string& name,
589 const std::vector<std::string>& inames,
590 const std::vector<std::string>& onames,
591 const Dict& opts)
const;
599 Sparsity& jac_sparsity(casadi_int oind, casadi_int iind,
bool compact,
bool symmetric)
const;
600 virtual bool has_jac_sparsity(casadi_int oind, casadi_int iind)
const {
return false;}
601 virtual Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind,
bool symmetric)
const;
605 static std::string forward_name(
const std::string& fcn, casadi_int nfwd) {
606 return "fwd" + str(nfwd) +
"_" + fcn;
610 std::string diff_prefix(
const std::string& prefix)
const;
620 Function forward(casadi_int nfwd)
const;
621 virtual bool has_forward(casadi_int nfwd)
const {
return false;}
622 virtual Function get_forward(casadi_int nfwd,
const std::string& name,
623 const std::vector<std::string>& inames,
624 const std::vector<std::string>& onames,
625 const Dict& opts)
const;
629 static std::string reverse_name(
const std::string& fcn, casadi_int nadj) {
630 return "adj" + str(nadj) +
"_" + fcn;
641 Function reverse(casadi_int nadj)
const;
642 virtual bool has_reverse(casadi_int nadj)
const {
return false;}
643 virtual Function get_reverse(casadi_int nadj,
const std::string& name,
644 const std::vector<std::string>& inames,
645 const std::vector<std::string>& onames,
646 const Dict& opts)
const;
652 template<
typename MatType>
653 static MatType ensure_stacked(
const MatType& v,
const Sparsity& sp, casadi_int n);
658 virtual Function slice(
const std::string& name,
const std::vector<casadi_int>& order_in,
659 const std::vector<casadi_int>& order_out,
const Dict& opts)
const;
664 virtual const Function& oracle()
const;
669 bool has_derivative()
const;
674 virtual double ad_weight()
const;
681 virtual double sp_weight()
const;
687 virtual const SX sx_in(casadi_int ind)
const;
688 virtual const SX sx_out(casadi_int ind)
const;
689 virtual const std::vector<SX> sx_in()
const;
690 virtual const std::vector<SX> sx_out()
const;
691 virtual const MX mx_in(casadi_int ind)
const;
692 virtual const MX mx_out(casadi_int ind)
const;
693 virtual const std::vector<MX> mx_in()
const;
694 virtual const std::vector<MX> mx_out()
const;
695 const DM dm_in(casadi_int ind)
const;
696 const DM dm_out(casadi_int ind)
const;
697 const std::vector<DM> dm_in()
const;
698 const std::vector<DM> dm_out()
const;
702 virtual std::vector<MX> free_mx()
const;
705 virtual std::vector<SX> free_sx()
const;
710 virtual bool has_free()
const {
return false;}
715 virtual void generate_lifted(Function& vdef_fcn, Function& vinit_fcn)
const;
720 virtual casadi_int n_instructions()
const;
725 virtual casadi_int instruction_id(casadi_int k)
const;
730 virtual std::vector<casadi_int> instruction_input(casadi_int k)
const;
735 virtual double instruction_constant(casadi_int k)
const;
740 virtual std::vector<casadi_int> instruction_output(casadi_int k)
const;
745 virtual casadi_int n_nodes()
const;
750 virtual MX instruction_MX(casadi_int k)
const;
755 virtual SX instructions_sx()
const;
760 Function wrap()
const;
765 Function wrap_as_needed(
const Dict& opts)
const;
775 bool incache(
const std::string& fname, Function& f,
const std::string& suffix=
"")
const;
780 void tocache(
const Function& f,
const std::string& suffix=
"")
const;
785 void codegen(CodeGenerator& g,
const std::string& fname)
const;
790 void codegen_meta(CodeGenerator& g)
const;
795 void codegen_sparsities(CodeGenerator& g)
const;
800 virtual std::string codegen_name(
const CodeGenerator& g,
bool ns=
true)
const;
805 std::string codegen_mem(CodeGenerator& g,
const std::string& index=
"mem")
const;
810 virtual void codegen_incref(CodeGenerator& g)
const {}
815 virtual void codegen_decref(CodeGenerator& g)
const {}
820 virtual void codegen_alloc_mem(CodeGenerator& g)
const;
825 virtual void codegen_init_mem(CodeGenerator& g)
const;
830 virtual void codegen_free_mem(CodeGenerator& g)
const {}
835 virtual void codegen_checkout(CodeGenerator& g)
const;
840 virtual void codegen_release(CodeGenerator& g)
const;
845 std::string signature(
const std::string& fname)
const;
850 std::string signature_unrolled(
const std::string& fname)
const;
855 virtual void codegen_declarations(CodeGenerator& g)
const;
860 virtual void codegen_body(CodeGenerator& g)
const;
865 virtual std::string codegen_mem_type()
const {
return ""; }
870 virtual std::string generate_dependencies(
const std::string& fname,
const Dict& opts)
const;
875 virtual bool has_codegen()
const {
return false;}
880 virtual void jit_dependencies(
const std::string& fname) {}
885 virtual void export_code(
const std::string& lang,
886 std::ostream &stream,
const Dict& options)
const;
891 void serialize_type(SerializingStream &s)
const override;
896 void serialize_body(SerializingStream &s)
const override;
901 void disp(std::ostream& stream,
bool more)
const override;
906 virtual void disp_more(std::ostream& stream)
const {}
911 std::string definition()
const;
916 void print_dimensions(std::ostream &stream)
const;
921 virtual std::vector<std::string> get_free()
const;
926 void get_partition(casadi_int iind, casadi_int oind, Sparsity& D1, Sparsity& D2,
927 bool compact,
bool symmetric,
928 bool allow_forward,
bool allow_reverse)
const;
934 casadi_int nnz_in()
const;
935 casadi_int nnz_in(casadi_int ind)
const {
return sparsity_in(ind).nnz(); }
936 casadi_int nnz_out()
const;
937 casadi_int nnz_out(casadi_int ind)
const {
return sparsity_out(ind).nnz(); }
944 casadi_int numel_in()
const;
945 casadi_int numel_in(casadi_int ind)
const {
return sparsity_in(ind).numel(); }
946 casadi_int numel_out(casadi_int ind)
const {
return sparsity_out(ind).numel(); }
947 casadi_int numel_out()
const;
954 casadi_int size1_in(casadi_int ind)
const {
return sparsity_in(ind).size1(); }
955 casadi_int size2_in(casadi_int ind)
const {
return sparsity_in(ind).size2(); }
956 casadi_int size1_out(casadi_int ind)
const {
return sparsity_out(ind).size1(); }
957 casadi_int size2_out(casadi_int ind)
const {
return sparsity_out(ind).size2(); }
958 std::pair<casadi_int, casadi_int> size_in(casadi_int ind)
const {
959 return sparsity_in(ind).size();
961 std::pair<casadi_int, casadi_int> size_out(casadi_int ind)
const {
962 return sparsity_out(ind).size();
970 const Sparsity& sparsity_in(casadi_int ind)
const {
return sparsity_in_.at(ind); }
971 const Sparsity& sparsity_out(casadi_int ind)
const {
return sparsity_out_.at(ind); }
978 bool all_scalar()
const;
981 virtual bool jac_is_symm(casadi_int oind, casadi_int iind)
const;
984 Sparsity to_compact(casadi_int oind, casadi_int iind,
const Sparsity& sp)
const;
987 Sparsity from_compact(casadi_int oind, casadi_int iind,
const Sparsity& sp)
const;
991 Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind)
const;
994 Sparsity get_jac_sparsity_hierarchical(casadi_int oind, casadi_int iind)
const;
999 Sparsity get_jac_sparsity_hierarchical_symm(casadi_int oind, casadi_int iind)
const;
1002 virtual std::vector<MX> symbolic_output(
const std::vector<MX>& arg)
const;
1008 virtual size_t get_n_in();
1009 virtual size_t get_n_out();
1017 virtual std::string get_name_in(casadi_int i);
1018 virtual std::string get_name_out(casadi_int i);
1024 virtual double get_default_in(casadi_int ind)
const {
1031 virtual double get_max_in(casadi_int ind)
const {
1038 virtual double get_min_in(casadi_int ind)
const {
1042 virtual std::vector<double> get_nominal_in(casadi_int ind)
const {
1043 return std::vector<double>(nnz_in(ind), 1.);
1046 virtual std::vector<double> get_nominal_out(casadi_int ind)
const {
1047 return std::vector<double>(nnz_out(ind), 1.);
1053 virtual double get_reltol()
const {
1060 virtual double get_abstol()
const {
1067 virtual Sparsity get_sparsity_in(casadi_int i);
1072 virtual Sparsity get_sparsity_out(casadi_int i);
1077 virtual bool get_diff_in(casadi_int i) {
return true; }
1082 virtual bool get_diff_out(casadi_int i) {
return true; }
1087 casadi_int index_in(
const std::string &name)
const {
1088 for (casadi_int i=0; i<name_in_.size(); ++i) {
1089 if (name_in_[i]==name)
return i;
1091 casadi_error(
"FunctionInternal::index_in: could not find entry \""
1092 + name +
"\". Available names are: " + str(name_in_) +
".");
1099 casadi_int index_out(
const std::string &name)
const {
1100 for (casadi_int i=0; i<name_out_.size(); ++i) {
1101 if (name_out_[i]==name)
return i;
1103 casadi_error(
"FunctionInternal::index_out: could not find entry \""
1104 + name +
"\". Available names are: " + str(name_out_) +
".");
1111 virtual int sp_forward(
const bvec_t** arg, bvec_t** res,
1112 casadi_int* iw, bvec_t* w,
void* mem)
const;
1117 virtual int sp_forward_block(
const bvec_t** arg, bvec_t** res,
1118 casadi_int* iw, bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const;
1123 virtual int sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w,
void* mem)
const;
1128 void sz_work(
size_t& sz_arg,
size_t& sz_res,
size_t& sz_iw,
size_t& sz_w)
const;
1133 size_t sz_arg()
const {
return sz_arg_per_ + sz_arg_tmp_;}
1138 size_t sz_res()
const {
return sz_res_per_ + sz_res_tmp_;}
1143 size_t sz_iw()
const {
return sz_iw_per_ + sz_iw_tmp_;}
1148 size_t sz_w()
const {
return sz_w_per_ + sz_w_tmp_;}
1153 void alloc_arg(
size_t sz_arg,
bool persistent=
false);
1158 void alloc_res(
size_t sz_res,
bool persistent=
false);
1163 void alloc_iw(
size_t sz_iw,
bool persistent=
false);
1168 void alloc_w(
size_t sz_w,
bool persistent=
false);
1173 void alloc(
const Function& f,
bool persistent=
false,
int num_threads=1);
1178 virtual void set_work(
void* mem,
const double**& arg,
double**& res,
1179 casadi_int*& iw,
double*& w)
const {}
1184 virtual void set_temp(
void* mem,
const double** arg,
double** res,
1185 casadi_int* iw,
double* w)
const {}
1190 void setup(
void* mem,
const double** arg,
double** res, casadi_int* iw,
double* w)
const;
1196 virtual bool fwdViaJac(casadi_int nfwd)
const;
1197 virtual bool adjViaJac(casadi_int nadj)
const;
1201 virtual Dict info()
const;
1206 Function map(casadi_int n,
const std::string& parallelization)
const;
1211 void generate_in(
const std::string& fname,
const double** arg)
const;
1212 void generate_out(
const std::string& fname,
double** res)
const;
1214 bool always_inline_, never_inline_;
1217 size_t n_in_, n_out_;
1220 std::vector<bool> is_diff_in_, is_diff_out_;
1223 std::vector<Sparsity> sparsity_in_, sparsity_out_;
1226 std::vector<std::string> name_in_, name_out_;
1241 std::string jit_serialize_;
1246 std::string jit_name_;
1248 std::string jit_base_name_;
1253 bool jit_temp_suffix_;
1263 casadi_checkout_t checkout_;
1268 casadi_release_t release_;
1286 mutable std::map<std::string, WeakRef> cache_;
1289 mutable std::vector<Sparsity> jac_sparsity_[2];
1292 Function derivative_of_;
1298 std::string compiler_plugin_;
1303 double jac_penalty_;
1306 bool enable_forward_, enable_reverse_, enable_jacobian_, enable_fd_;
1307 bool enable_forward_op_, enable_reverse_op_, enable_jacobian_op_, enable_fd_op_;
1310 double ad_weight_, ad_weight_sp_;
1313 casadi_int max_num_dir_;
1325 std::string fd_method_;
1335 bool dump_in_, dump_out_, dump_;
1338 std::string dump_dir_;
1341 std::string dump_format_;
1344 Dict forward_options_, reverse_options_, jacobian_options_, der_options_;
1347 Function custom_jacobian_;
1350 mutable casadi_int dump_count_ = 0;
1351 #ifdef CASADI_WITH_THREAD
1352 mutable std::mutex dump_count_mtx_;
1358 virtual bool is_a(
const std::string& type,
bool recursive)
const;
1363 template<
typename MatType>
1364 static bool purgable(
const std::vector<MatType>& seed);
1369 template<
typename MatType>
1370 std::vector<std::vector<MatType> >
1371 fwd_seed(casadi_int nfwd)
const;
1376 template<
typename MatType>
1377 std::vector<std::vector<MatType> >
1378 symbolicAdjSeed(casadi_int nadj,
const std::vector<MatType>& v)
const;
1385 explicit FunctionInternal(DeserializingStream& e);
1390 static Function deserialize(DeserializingStream& s);
1391 static std::map<std::string, ProtoFunction* (*)(DeserializingStream&)> deserialize_map;
1396 void print_in(std::ostream &stream,
const double** arg,
bool truncate)
const;
1401 void print_out(std::ostream &stream,
double** res,
bool truncate)
const;
1407 void set_jac_sparsity(casadi_int oind, casadi_int iind,
const Sparsity& sp);
1412 casadi_int get_dump_id()
const;
1413 void dump_in(casadi_int
id,
const double** arg)
const;
1414 void dump_out(casadi_int
id,
double** res)
const;
1421 size_t sz_arg_per_, sz_res_per_, sz_iw_per_, sz_w_per_;
1426 size_t sz_arg_tmp_, sz_res_tmp_, sz_iw_tmp_, sz_w_tmp_;
1430 template<
typename MatType>
1431 bool FunctionInternal::purgable(
const std::vector<MatType>& v) {
1432 for (
auto i=v.begin(); i!=v.end(); ++i) {
1433 if (!i->is_zero())
return false;
1438 template<
typename MatType>
1439 std::vector<std::vector<MatType> >
1441 fwd_seed(casadi_int nfwd)
const {
1442 std::vector<std::vector<MatType>> fseed(nfwd);
1443 for (casadi_int dir=0; dir<nfwd; ++dir) {
1444 fseed[dir].resize(n_in_);
1445 for (casadi_int iind=0; iind<n_in_; ++iind) {
1446 std::string n =
"f" + str(dir) +
"_" + name_in_[iind];
1447 Sparsity sp = is_diff_in_[iind] ? sparsity_in(iind) : Sparsity(size_in(iind));
1448 fseed[dir][iind] = MatType::sym(n, sp);
1454 template<
typename MatType>
1455 std::vector<std::vector<MatType> >
1457 symbolicAdjSeed(casadi_int nadj,
const std::vector<MatType>& v)
const {
1458 std::vector<std::vector<MatType> > aseed(nadj, v);
1459 for (casadi_int dir=0; dir<nadj; ++dir) {
1462 for (
typename std::vector<MatType>::iterator i=aseed[dir].begin();
1463 i!=aseed[dir].end();
1466 std::stringstream ss;
1468 if (nadj>1) ss << dir <<
"_";
1472 *i = MatType::sym(ss.str(), is_diff_out_[oind] ? i->sparsity() : Sparsity(i->size()));
1479 template<
typename M>
1480 void FunctionInternal::call(
const std::vector<M>& arg, std::vector<M>& res,
1481 bool always_inline,
bool never_inline)
const {
1485 bool matrix_call =
false;
1486 std::pair<casadi_int, casadi_int> sz;
1487 for (
auto&& a : arg) {
1488 if (!a.is_scalar() && !a.is_empty()) {
1493 }
else if (a.size()!=sz) {
1495 matrix_call =
false;
1506 for (
auto&& a : res) a = z;
1508 std::vector<M> arg1 = arg, res1;
1509 for (casadi_int c=0; c<sz.second; ++c) {
1510 for (casadi_int r=0; r<sz.first; ++r) {
1512 for (casadi_int i=0; i<arg.size(); ++i) {
1513 if (arg[i].size()==sz) arg1[i] = arg[i](r, c);
1516 call(arg1, res1, always_inline, never_inline);
1518 casadi_assert_dev(res.size() == res1.size());
1519 for (casadi_int i=0; i<res.size(); ++i) res[i](r, c) = res1[i];
1528 casadi_int npar = 1;
1529 if (!matching_arg(arg, npar)) {
1530 return call(replace_arg(arg, npar), res, always_inline, never_inline);
1534 call_gen(arg, res, npar, always_inline, never_inline);
1537 template<
typename M>
1538 std::vector<M> FunctionInternal::
1539 project_arg(
const std::vector<M>& arg, casadi_int npar)
const {
1540 casadi_assert_dev(arg.size()==n_in_);
1543 std::vector<bool> mapped(n_in_);
1544 for (casadi_int i=0; i<n_in_; ++i) {
1545 mapped[i] = arg[i].size2()!=size2_in(i);
1549 std::vector<bool> matching(n_in_);
1550 bool any_mismatch =
false;
1551 for (casadi_int i=0; i<n_in_; ++i) {
1553 matching[i] = arg[i].sparsity().is_stacked(sparsity_in(i), npar);
1555 matching[i] = arg[i].sparsity()==sparsity_in(i);
1557 any_mismatch = any_mismatch || !matching[i];
1562 std::vector<M> arg2(arg);
1563 for (casadi_int i=0; i<n_in_; ++i) {
1566 arg2[i] = project(arg2[i], repmat(sparsity_in(i), 1, npar));
1568 arg2[i] = project(arg2[i], sparsity_in(i));
1577 template<
typename M>
1578 std::vector<M> FunctionInternal::
1579 project_res(
const std::vector<M>& arg, casadi_int npar)
const {
1583 template<
typename D>
1584 void FunctionInternal::
1585 call_gen(
const std::vector<Matrix<D> >& arg, std::vector<Matrix<D> >& res,
1586 casadi_int npar,
bool always_inline,
bool never_inline)
const {
1587 casadi_assert(!never_inline,
"Call-nodes only possible in MX expressions");
1588 std::vector< Matrix<D> > arg2 = project_arg(arg, npar);
1591 std::vector<bool> mapped(n_in_);
1592 for (casadi_int i=0; i<n_in_; ++i) {
1593 mapped[i] = arg[i].size2()!=size2_in(i);
1598 for (casadi_int i=0; i<n_out_; ++i) {
1599 if (!res[i].sparsity().is_stacked(sparsity_out(i), npar)) {
1605 std::vector<casadi_int> iw_tmp(sz_iw());
1606 std::vector<D> w_tmp(sz_w());
1609 std::vector<const D*> argp(sz_arg());
1610 for (casadi_int i=0; i<n_in_; ++i) argp[i]=get_ptr(arg2[i]);
1613 std::vector<D*> resp(sz_res());
1614 for (casadi_int i=0; i<n_out_; ++i) resp[i]=get_ptr(res[i]);
1617 for (casadi_int p=0; p<npar; ++p) {
1619 if (eval_gen(get_ptr(argp), get_ptr(resp),
1620 get_ptr(iw_tmp), get_ptr(w_tmp), memory(0))) {
1621 if (error_on_fail_) casadi_error(
"Evaluation failed");
1624 if (p==npar-1)
break;
1625 for (casadi_int i=0; i<n_in_; ++i)
if (mapped[i]) argp[i] += nnz_in(i);
1626 for (casadi_int i=0; i<n_out_; ++i) resp[i] += nnz_out(i);
1630 template<
typename M>
1631 void FunctionInternal::check_arg(
const std::vector<M>& arg, casadi_int& npar)
const {
1632 casadi_assert(arg.size()==n_in_,
"Incorrect number of inputs: Expected "
1633 + str(n_in_) +
", got " + str(arg.size()));
1634 for (casadi_int i=0; i<n_in_; ++i) {
1635 if (!check_mat(arg[i].sparsity(), sparsity_in(i), npar)) {
1637 std::string d_arg = str(arg[i].size1()) +
"-by-" + str(arg[i].size2());
1638 std::string d_in = str(size1_in(i)) +
"-by-" + str(size2_in(i));
1639 std::string e =
"Input " + str(i) +
" (" + name_in_[i] +
") has mismatching shape. "
1640 "Got " + d_arg +
". Allowed dimensions, in general, are:\n"
1641 " - The input dimension N-by-M (here " + d_in +
")\n"
1642 " - A scalar, i.e. 1-by-1\n"
1643 " - M-by-N if N=1 or M=1 (i.e. a transposed vector)\n"
1644 " - N-by-M1 if K*M1=M for some K (argument repeated horizontally)\n";
1646 e +=
" - N-by-P*M, indicating evaluation with multiple arguments (P must be a "
1647 "multiple of " + str(npar) +
" for consistency with previous inputs)";
1654 template<
typename M>
1655 void FunctionInternal::check_res(
const std::vector<M>& res, casadi_int& npar)
const {
1656 casadi_assert(res.size()==n_out_,
"Incorrect number of outputs: Expected "
1657 + str(n_out_) +
", got " + str(res.size()));
1658 for (casadi_int i=0; i<n_out_; ++i) {
1659 casadi_assert(check_mat(res[i].sparsity(), sparsity_out(i), npar),
1660 "Output " + str(i) +
" (" + name_out_[i] +
") has mismatching shape. "
1661 "Expected " + str(size_out(i)) +
", got " + str(res[i].size()));
1665 template<
typename M>
1666 bool FunctionInternal::matching_arg(
const std::vector<M>& arg, casadi_int& npar)
const {
1667 check_arg(arg, npar);
1668 for (casadi_int i=0; i<n_in_; ++i) {
1669 if (arg.at(i).size1()!=size1_in(i))
return false;
1670 if (arg.at(i).size2()!=size2_in(i) && arg.at(i).size2()!=npar*size2_in(i))
return false;
1675 template<
typename M>
1676 bool FunctionInternal::matching_res(
const std::vector<M>& res, casadi_int& npar)
const {
1677 check_res(res, npar);
1678 for (casadi_int i=0; i<n_out_; ++i) {
1679 if (res.at(i).size1()!=size1_out(i))
return false;
1680 if (res.at(i).size2()!=size2_out(i) && res.at(i).size2()!=npar*size2_out(i))
return false;
1685 template<
typename M>
1686 M replace_mat(
const M& arg,
const Sparsity& inp, casadi_int npar) {
1687 if (arg.size()==inp.size()) {
1690 }
else if (arg.is_empty()) {
1692 return M(inp.size());
1693 }
else if (arg.is_scalar()) {
1696 }
else if (arg.is_vector() && inp.size()==std::make_pair(arg.size2(), arg.size1())) {
1699 }
else if (arg.size1()==inp.size1() && arg.size2()>0 && inp.size2()>0
1700 && inp.size2()%arg.size2()==0) {
1702 return repmat(arg, 1, inp.size2()/arg.size2());
1704 casadi_assert_dev(npar!=-1);
1706 return repmat(arg, 1, (npar*inp.size2())/arg.size2());
1710 template<
typename M>
1711 std::vector<M> FunctionInternal::
1712 replace_arg(
const std::vector<M>& arg, casadi_int npar)
const {
1713 std::vector<M> r(arg.size());
1714 for (casadi_int i=0; i<r.size(); ++i) r[i] = replace_mat(arg[i], sparsity_in(i), npar);
1718 template<
typename M>
1719 std::vector<M> FunctionInternal::
1720 replace_res(
const std::vector<M>& res, casadi_int npar)
const {
1721 std::vector<M> r(res.size());
1722 for (casadi_int i=0; i<r.size(); ++i) r[i] = replace_mat(res[i], sparsity_out(i), npar);
1726 template<
typename M>
1727 std::vector<std::vector<M> > FunctionInternal::
1728 replace_fseed(
const std::vector<std::vector<M> >& fseed, casadi_int npar)
const {
1729 std::vector<std::vector<M> > r(fseed.size());
1730 for (casadi_int d=0; d<r.size(); ++d) r[d] = replace_arg(fseed[d], npar);
1734 template<
typename M>
1735 std::vector<std::vector<M> > FunctionInternal::
1736 replace_aseed(
const std::vector<std::vector<M> >& aseed, casadi_int npar)
const {
1737 std::vector<std::vector<M> > r(aseed.size());
1738 for (casadi_int d=0; d<r.size(); ++d) r[d] = replace_res(aseed[d], npar);
1742 template<
typename M>
1743 std::map<std::string, M> FunctionInternal::
1744 convert_arg(
const std::vector<M>& arg)
const {
1745 casadi_assert(arg.size()==n_in_,
"Incorrect number of inputs: Expected "
1746 + str(n_in_) +
", got " + str(arg.size()));
1747 std::map<std::string, M> ret;
1748 for (casadi_int i=0;i<n_in_;++i) {
1749 ret[name_in_[i]] = arg[i];
1754 template<
typename M>
1755 std::vector<M> FunctionInternal::
1756 convert_arg(
const std::map<std::string, M>& arg)
const {
1758 std::vector<M> arg_v(n_in_);
1759 for (casadi_int i=0; i<arg_v.size(); ++i) {
1760 arg_v[i] = get_default_in(i);
1764 for (
auto&& e : arg) {
1765 arg_v.at(index_in(e.first)) = e.second;
1771 template<
typename M>
1772 std::map<std::string, M> FunctionInternal::
1773 convert_res(
const std::vector<M>& res)
const {
1774 casadi_assert(res.size()==n_out_,
"Incorrect number of outputs: Expected "
1775 + str(n_out_) +
", got " + str(res.size()));
1776 std::map<std::string, M> ret;
1777 for (casadi_int i=0;i<n_out_;++i) {
1778 ret[name_out_[i]] = res[i];
1783 template<
typename M>
1784 std::vector<M> FunctionInternal::
1785 convert_res(
const std::map<std::string, M>& res)
const {
1787 std::vector<M> res_v(n_out_);
1788 for (casadi_int i=0; i<res_v.size(); ++i) {
1789 res_v[i] = std::numeric_limits<double>::quiet_NaN();
1793 for (
auto&& e : res) {
1795 res_v.at(index_out(e.first)) = a;
1800 template<
typename MatType>
1801 MatType FunctionInternal::ensure_stacked(
const MatType& v,
const Sparsity& sp, casadi_int n) {
1803 if (v.size1() == sp.size1() && v.size2() == n * sp.size2()) {
1805 if (v.nnz() != 0 && !v.sparsity().is_stacked(sp, n)) {
1806 return project(v, repmat(sp, 1, n));
1810 casadi_assert_dev(v.is_empty());
1811 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.