26 #include "function_internal.hpp"
27 #include "casadi_call.hpp"
28 #include "call_sx.hpp"
29 #include "casadi_misc.hpp"
30 #include "global_options.hpp"
31 #include "external.hpp"
32 #include "finite_differences.hpp"
33 #include "serializing_stream.hpp"
34 #include "mx_function.hpp"
35 #include "sx_function.hpp"
36 #include "rootfinder_impl.hpp"
40 #include "interpolant_impl.hpp"
41 #include "nlpsol_impl.hpp"
42 #include "conic_impl.hpp"
43 #include "integrator_impl.hpp"
44 #include "external_impl.hpp"
45 #include "fmu_function.hpp"
46 #include "blazing_spline_impl.hpp"
47 #include "onnx_function_impl.hpp"
48 #include "filesystem_impl.hpp"
72 casadi_error(
"Function name is not valid. A valid function name is a std::string "
73 "starting with a letter followed by letters, numbers or "
74 "non-consecutive underscores. It may also not match the keywords "
75 "'null', 'jac' or 'hess'. Got '" +
name_ +
"'");
127 for (
void* m : mem_) {
128 if (m!=
nullptr) casadi_warning(
"Memory object has not been properly freed");
137 if (
remove(jit_name.c_str())) casadi_warning(
"Failed to remove " + jit_name);
155 }
catch(std::exception& e) {
156 casadi_error(
"Error calling " +
class_name() +
"::init for '" +
name_ +
"':\n"
157 + std::string(e.what()));
163 }
catch(std::exception& e) {
164 casadi_error(
"Error calling " +
class_name() +
"::finalize for '" +
name_ +
"':\n"
165 + std::string(e.what()));
173 "Verbose evaluation -- for debugging"}},
176 "print information about execution time. Implies record_time."}},
179 "record information about execution time, for retrieval with stats()."}},
182 "Throw exceptions when NaN or Inf appears during evaluation"}},
185 "Throw exceptions when function evaluation fails (default true)."}}
193 "Weighting factor for derivative calculation."
194 "When there is an option of either using forward or reverse mode "
195 "directional derivatives, the condition ad_weight*nf<=(1-ad_weight)*na "
196 "is used where nf and na are estimates of the number of forward/reverse "
197 "mode directional derivatives needed. By default, ad_weight is calculated "
198 "automatically, but this can be overridden by setting this option. "
199 "In particular, 0 means forcing forward mode and 1 forcing reverse mode. "
200 "Leave unset for (class specific) heuristics."}},
203 "Weighting factor for sparsity pattern calculation calculation."
204 "Overrides default behavior. Set to 0 and 1 to force forward and "
205 "reverse mode respectively. Cf. option \"ad_weight\". "
206 "When set to -1, sparsity is completely ignored and dense matrices are used."}},
212 "Forbid inlining."}},
215 "When requested for a number of forward/reverse directions, "
216 "it may be cheaper to compute first the full jacobian and then "
217 "multiply with seeds, rather than obtain the requested directions "
218 "in a straightforward manner. "
219 "Casadi uses a heuristic to decide which is cheaper. "
220 "A high value of 'jac_penalty' makes it less likely for the heurstic "
221 "to chose the full Jacobian strategy. "
222 "The special value -1 indicates never to use the full Jacobian strategy"}},
225 "A user-defined field that can be used to identify "
226 "the function or pass additional information"}},
229 "Throw exceptions when the numerical values of the inputs don't make sense"}},
232 "Deprecated option (ignored): Statistics are now always collected."}},
235 "Use just-in-time compiler to speed up the evaluation"}},
238 "Cleanup up the temporary source file that jit creates. Default: true"}},
241 "Specify behaviour when serializing a jitted function: SOURCE|link|embed."}},
244 "The file name used to write out code. "
245 "The actual file names used depend on 'jit_temp_suffix' and include extensions. "
246 "Default: 'jit_tmp'"}},
249 "Use a temporary (seemingly random) filename suffix for generated code and libraries. "
250 "This is desired for thread-safety. "
251 "This behaviour may defeat caching compiler wrappers. "
255 "Just-in-time compiler plugin to be used."}},
258 "Options to be passed to the jit compiler."}},
261 "Options to be passed to the code generator of jit, e.g. {\"stats\": true} to "
262 "record statistics inside the compiled code. Default: none"}},
265 "The function is a derivative of another function. "
266 "The type of derivative (directional derivative, Jacobian) "
267 "is inferred from the function name."}},
270 "Specify the maximum number of directions for derivative functions."
271 " Overrules the builtin optimized_num_dir."}},
274 "Enable derivative calculation using generated functions for"
275 " Jacobian-times-vector products - typically using forward mode AD"
276 " - if available. [default: true]"}},
279 "Enable derivative calculation using generated functions for"
280 " transposed Jacobian-times-vector products - typically using reverse mode AD"
281 " - if available. [default: true]"}},
284 "Enable derivative calculation using generated functions for"
285 " Jacobians of all differentiable outputs with respect to all differentiable inputs"
286 " - if available. [default: true]"}},
289 "Enable derivative calculation by finite differencing. [default: false]]"}},
292 "Options to be passed to the finite difference instance"}},
295 "Method for finite differencing [default 'central']"}},
298 "Print numerical values of inputs [default: false]"}},
301 "Print numerical values of outputs [default: false]"}},
304 "When printing numerical matrices, use a format that is "
305 "exact and reproducible in generated C code."}},
308 "Acceptable number of inputs and outputs. Warn if exceeded."}},
311 "Dump numerical values of inputs to file (readable with DM.from_file) [default: false] "
312 "A counter is used to generate unique names. "
313 "The counter may be reset using reset_dump_count."}},
316 "Dump numerical values of outputs to file (readable with DM.from_file) [default: false] "
317 "A counter is used to generate unique names. "
318 "The counter may be reset using reset_dump_count."}},
321 "Dump function to file upon first evaluation. [false]"}},
324 "Directory to dump inputs/outputs and traces to. Make sure the directory exists [.]"}},
327 "Choose file format to dump matrices. See DM.from_file [mtx]"}},
330 "Options to be passed to a forward mode constructor"}},
333 "Options to be passed to a reverse mode constructor"}},
336 "Options to be passed to a Jacobian constructor"}},
339 "Default options to be used to populate forward_options, reverse_options, and "
340 "jacobian_options before those options are merged in."}},
343 "Override CasADi's AD. Use together with 'jac_penalty': 0. "
344 "Note: Highly experimental. Syntax may break often."}},
347 "Indicate for each input if it should be differentiable."}},
350 "Indicate for each output if it should be differentiable."}},
353 "After construction, expand this Function. Default: False"}},
354 {
"post_expand_options",
356 "Options to be passed to post-construction expansion. Default: empty"}},
359 "Prepopulate the function cache. Default: empty"}},
360 {
"external_transform",
362 "List of external_transform instruction arguments. Default: empty"}}
368 for (
auto&& op : opts) {
369 if (op.first==
"verbose") {
371 }
else if (op.first==
"print_time") {
373 }
else if (op.first==
"record_time") {
375 }
else if (op.first==
"regularity_check") {
377 }
else if (op.first==
"error_on_fail") {
398 if (target!=
"tmp") opts[
"jit"] =
jit_;
411 if (target==
"clone" || target==
"tmp") {
432 opts[
"dump"] =
dump_;
433 if (target==
"clone") {
437 if (target==
"forward") {
441 if (target==
"reverse") {
450 if (option_name ==
"print_in") {
452 }
else if (option_name ==
"print_out") {
454 }
else if (option_name ==
"print_canonical") {
456 }
else if (option_name==
"ad_weight") {
458 }
else if (option_name==
"ad_weight_sp") {
460 }
else if (option_name==
"dump") {
461 dump_ = option_value;
462 }
else if (option_name==
"dump_in") {
464 }
else if (option_name==
"dump_out") {
466 }
else if (option_name==
"dump_dir") {
468 }
else if (option_name==
"dump_format") {
488 for (
auto&& op : opts) {
489 if (op.first==
"jac_penalty") {
491 }
else if (op.first==
"user_data") {
493 }
else if (op.first==
"inputs_check") {
495 }
else if (op.first==
"gather_stats") {
496 casadi_warning(
"Deprecated option \"gather_stats\": Always enabled");
497 }
else if (op.first==
"jit") {
499 }
else if (op.first==
"jit_cleanup") {
501 }
else if (op.first==
"jit_serialize") {
504 "jit_serialize option not understood. Pick one of source, link, embed.");
505 }
else if (op.first==
"compiler") {
507 }
else if (op.first==
"jit_options") {
509 }
else if (op.first==
"codegen_options") {
511 }
else if (op.first==
"jit_name") {
513 }
else if (op.first==
"jit_temp_suffix") {
515 }
else if (op.first==
"derivative_of") {
517 }
else if (op.first==
"ad_weight") {
519 }
else if (op.first==
"ad_weight_sp") {
521 }
else if (op.first==
"max_num_dir") {
523 }
else if (op.first==
"enable_forward") {
525 }
else if (op.first==
"enable_reverse") {
527 }
else if (op.first==
"enable_jacobian") {
529 }
else if (op.first==
"enable_fd") {
531 }
else if (op.first==
"fd_options") {
533 }
else if (op.first==
"fd_method") {
535 }
else if (op.first==
"print_in") {
537 }
else if (op.first==
"print_out") {
539 }
else if (op.first==
"print_canonical") {
541 }
else if (op.first==
"max_io") {
543 }
else if (op.first==
"dump_in") {
545 }
else if (op.first==
"dump_out") {
547 }
else if (op.first==
"dump") {
549 }
else if (op.first==
"dump_dir") {
551 }
else if (op.first==
"dump_format") {
553 }
else if (op.first==
"forward_options") {
555 }
else if (op.first==
"reverse_options") {
557 }
else if (op.first==
"jacobian_options") {
559 }
else if (op.first==
"der_options") {
561 }
else if (op.first==
"custom_jacobian") {
564 "Inconsistent naming of custom Jacobian, expected: jac_" +
name_);
566 }
else if (op.first==
"always_inline") {
568 }
else if (op.first==
"never_inline") {
570 }
else if (op.first==
"is_diff_in") {
572 }
else if (op.first==
"is_diff_out") {
574 }
else if (op.first==
"cache") {
588 casadi_warning(
"Function " +
name_ +
" has many inputs (" +
str(
n_in_) +
" > "
590 +
"Changing the problem formulation is strongly encouraged.");
596 casadi_warning(
"Function " +
name_ +
" has many outputs (" +
str(
n_out_) +
" > "
598 +
"Changing the problem formulation is strongly encouraged.");
607 +
" inputs, but is_diff_in has length " +
str(
is_diff_in_.size()) +
".");
616 +
" outputs, but is_diff_out has length " +
str(
is_diff_out_.size()) +
".");
625 +
" inputs, but sparsity_in has length " +
str(
sparsity_in_.size()) +
".");
634 +
" outputs, but sparsity_out has length " +
str(
sparsity_out_.size()) +
".");
643 +
" inputs, but name_in has length " +
str(
name_in_.size()) +
".");
652 +
" outputs, but name_out has length " +
str(
name_out_.size()) +
".");
658 if (c.first != f.
name()) {
659 casadi_warning(
"Cannot add '" + c.first +
"' a.k.a. '" + f.
name()
660 +
"' to cache. Mismatching names not implemented.");
667 sz_arg_per_ +=
n_in_;
683 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
704 if (
name_ ==
"jac_" + n) {
708 }
else if (
name_ ==
"adj1_" + n) {
722 std::string directory;
723 directory =
get_from_dict(jit_options,
"directory", std::string(
""));
728 jit_directory = directory;
730 jit_directory = jit_directory + directory;
746 for (
const Function& f : shared_from_this<Function>().find_functions(0)) {
747 if (f->has_refcount_in_deps_) {
763 if (
verbose_) casadi_message(
"Codegenerating function '" +
name_ +
"'.");
767 if (opts.find(
"prefix")==opts.end()) opts[
"prefix"] =
"jit";
770 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"'..");
772 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"' done.");
780 casadi_assert(
eval_!=
nullptr,
"Cannot load JIT'ed function.");
798 casadi_assert_dev(mem==0);
804 std::ostream& of = *of_ptr;
808 for (casadi_int i=0; i<
n_in_; ++i) {
809 const double* v = arg[i];
810 for (casadi_int k=0;k<
nnz_in(i);++k) {
820 std::ostream& of = *of_ptr;
824 for (casadi_int i=0; i<
n_out_; ++i) {
825 const double* v = res[i];
826 for (casadi_int k=0;k<
nnz_out(i);++k) {
827 normalized_out(of, v ? v[k] : std::numeric_limits<double>::quiet_NaN());
834 trace_values(std::ostream& trace,
const double* values, casadi_int nnz) {
840 for (casadi_int i = 0; i < nnz; ++i) {
842 double v = values[i];
845 }
else if (isinf(v)) {
846 trace << (v < 0 ?
"\"-inf\"" :
"\"inf\"");
855 open_trace(
const double** arg, casadi_int dump_id)
const {
856 if (dump_id < 0) dump_id = get_dump_id();
859 << std::setw(6) << dump_id <<
".trace.jsonl";
861 std::ostream& trace = *output;
863 trace <<
"{\"event\":\"header\",\"format\":\"casadi_trace\",\"version\":1,"
865 <<
"\",\"dump_id\":" << dump_id <<
"}\n";
866 trace <<
"{\"event\":\"inputs\",\"values\":[";
867 for (casadi_int i = 0; i <
n_in_; ++i) {
876 finish_trace(std::ostream& trace,
double** res,
int ret)
const {
878 trace <<
"{\"event\":\"outputs\",\"values\":[";
879 for (casadi_int i = 0; i <
n_out_; ++i) {
885 trace <<
"{\"event\":\"end\",\"status\":" << ret <<
"}\n";
887 casadi_assert(trace.good(),
"Failed to write dump_trace for '" +
name_ +
"'");
890 void FunctionInternal::dump_in(casadi_int
id,
const double** arg)
const {
891 std::stringstream ss;
892 ss << std::setfill(
'0') << std::setw(6) << id;
893 std::string count = ss.str();
894 for (casadi_int i=0;i<
n_in_;++i) {
900 casadi_message(
"dump_in for " +
name_ +
" -> " + name);
905 void FunctionInternal::dump_out(casadi_int
id,
double** res)
const {
906 std::stringstream ss;
907 ss << std::setfill(
'0') << std::setw(6) << id;
908 std::string count = ss.str();
909 for (casadi_int i=0;i<
n_out_;++i) {
915 casadi_message(
"dump_out for " +
name_ +
" -> " + name);
920 void FunctionInternal::dump()
const {
924 casadi_int FunctionInternal::get_dump_id()
const {
932 m->t_total = &m->fstats.at(
"total");
934 m->t_total =
nullptr;
940 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
941 for (casadi_int i=0; i<
n_in_; ++i) {
942 stream <<
"Input " << i <<
" (" <<
name_in_[i] <<
"): ";
951 stream <<
"NULL" << std::endl;
957 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
958 for (casadi_int i=0; i<
n_out_; ++i) {
959 stream <<
"Output " << i <<
" (" <<
name_out_[i] <<
"): ";
968 stream <<
"NULL" << std::endl;
978 for (casadi_int i=0; i<sz; ++i) {
979 if (i>0) stream <<
", ";
989 const Sparsity& sp,
const double* nz) {
994 stream << sp.
dim(
false) <<
": ";
997 for (casadi_int i=0; i<sp.
nnz(); ++i) {
998 if (i>0) stream <<
", ";
1004 stream <<
", colind: [";
1005 for (casadi_int i=0; i<sp.
size2()+1; ++i) {
1006 if (i>0) stream <<
", ";
1007 stream << sp.
colind()[i];
1010 stream <<
", row: [";
1011 for (casadi_int i=0; i<sp.
nnz(); ++i) {
1012 if (i>0) stream <<
", ";
1013 stream << sp.
row()[i];
1030 eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
1031 bool always_inline,
bool never_inline)
const {
1033 if (
dump_in_) dump_in(dump_id, arg);
1034 if (
dump_ && dump_id==0) dump();
1039 for (casadi_int i=0;i<
n_in_;++i) {
1040 casadi_assert(arg[i]==
nullptr || arg[i]+
nnz_in(i)<=w || arg[i]>=w+
sz_w(),
1041 "Memory corruption detected for input " +
name_in_[i] +
".\n"+
1043 " intersects with w " +
str(w)+
"-"+
str(w+
sz_w())+
".");
1045 for (casadi_int i=0;i<
n_out_;++i) {
1046 casadi_assert(res[i]==
nullptr || res[i]+
nnz_out(i)<=w || res[i]>=w+
sz_w(),
1047 "Memory corruption detected for output " +
name_out_[i]);
1050 for (
auto&& s : m->fstats) s.second.reset();
1051 if (m->t_total) m->t_total->tic();
1052 m->dump_id = dump_id;
1059 #ifdef CASADI_WITH_THREAD
1060 std::lock_guard<std::mutex> lock(mtx_);
1064 ret =
eval_(arg, res, iw, w, mem_);
1066 #ifdef CASADI_WITH_THREAD
1067 std::lock_guard<std::mutex> lock(mtx_);
1072 ret =
eval(arg, res, iw, w, mem);
1074 if (m->t_total) m->t_total->toc();
1082 for (casadi_int i = 0; i <
n_out_; ++i) {
1084 if (!res[i])
continue;
1086 casadi_int nnz = this->
nnz_out(i);
1087 for (casadi_int nz = 0; nz < nnz; ++nz) {
1088 if (isnan(res[i][nz]) || isinf(res[i][nz])) {
1090 casadi_error(
str(res[i][nz]) +
" detected for output " +
name_out_[i] +
" at "
1100 stream <<
" Number of inputs: " <<
n_in_ << std::endl;
1101 for (casadi_int i=0; i<
n_in_; ++i) {
1102 stream <<
" Input " << i <<
" (\"" <<
name_in_[i] <<
"\"): "
1105 stream <<
" Number of outputs: " <<
n_out_ << std::endl;
1106 for (casadi_int i=0; i<
n_out_; ++i) {
1107 stream <<
" Output " << i <<
" (\"" <<
name_out_[i] <<
"\"): "
1126 if (option_name ==
"verbose") {
1128 }
else if (option_name ==
"regularity_check") {
1132 casadi_error(
"Option '" + option_name +
"' cannot be changed");
1138 return std::vector<std::string>();
1142 std::stringstream s;
1147 for (casadi_int i=0; i<
n_in_; ++i) {
1153 for (casadi_int i=0; i<
n_out_; ++i) {
1165 stream << std::endl;
1175 std::vector<std::string> keys;
1176 std::vector<Function> entries;
1177 cache_.cache(keys, entries);
1179 for (
size_t i=0; i<keys.size(); ++i) {
1181 std::string s = keys[i];
1182 casadi_assert_dev(s.size() > 0);
1184 std::replace(s.begin(), s.end(),
':',
'_');
1186 if (s.back() ==
'_') s.resize(s.size() - 1);
1188 ret[s] = entries[i];
1195 const std::string& suffix)
const {
1196 return cache_.incache(fname +
":" + suffix, f);
1204 cache_.tocache_if_missing(f.
name() +
":" + suffix, f);
1209 if (parallelization==
"serial") {
1211 std::string fname =
"map" +
str(n) +
"_" +
name_;
1215 casadi_assert_dev(f.
name()==fname);
1231 if (opts.empty() && name==
name_)
return shared_from_this<Function>();
1233 Dict my_opts = opts;
1235 if (my_opts.find(
"ad_weight")==my_opts.end())
1237 if (my_opts.find(
"ad_weight_sp")==my_opts.end())
1239 if (my_opts.find(
"max_num_dir")==my_opts.end())
1242 std::vector<MX> arg =
mx_in();
1243 std::vector<MX> res =
self()(arg);
1263 std::vector<MX> arg =
mx_in();
1264 std::vector<MX> res =
self()(arg);
1279 for (casadi_int i=begin; i<end; ++i) {
1280 s[i] ^= (
bvec_t(1) << j);
1285 for (casadi_int i=begin; i<end; ++i) {
1293 for (casadi_int i=begin; i<end; ++i) r |= s[i];
1298 template<
bool fwd>
struct JacSparsityTraits {};
1299 template<>
struct JacSparsityTraits<true> {
1300 typedef const bvec_t* arg_t;
1301 static inline void sp(
const FunctionInternal *f,
1303 casadi_int* iw,
bvec_t* w,
void* mem) {
1304 std::vector<const bvec_t*> argm(f->sz_arg(),
nullptr);
1305 std::vector<bvec_t> wm(f->nnz_in(),
bvec_t(0));
1308 for (casadi_int i=0;i<f->n_in_;++i) {
1309 if (f->is_diff_in_[i]) {
1312 argm[i] = arg[i] ? wp :
nullptr;
1316 f->sp_forward(
get_ptr(argm), res, iw, w, mem);
1317 for (casadi_int i=0;i<f->n_out_;++i) {
1318 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1322 template<>
struct JacSparsityTraits<false> {
1324 static inline void sp(
const FunctionInternal *f,
1326 casadi_int* iw,
bvec_t* w,
void* mem) {
1327 for (casadi_int i=0;i<f->n_out_;++i) {
1328 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1330 f->sp_reverse(arg, res, iw, w, mem);
1331 for (casadi_int i=0;i<f->n_in_;++i) {
1332 if (!f->is_diff_in_[i] && arg[i])
casadi_clear(arg[i], f->nnz_in(i));
1344 std::vector<typename JacSparsityTraits<fwd>::arg_t> arg(
sz_arg(),
nullptr);
1345 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1346 std::vector<casadi_int> iw(
sz_iw());
1347 std::vector<bvec_t> w(
sz_w(), 0);
1350 std::vector<bvec_t> seed(
nz_in, 0);
1352 std::vector<bvec_t> sens(
nz_out, 0);
1354 if (!fwd) std::swap(seed, sens);
1357 casadi_int nsweep = seed.size() /
bvec_size;
1362 casadi_message(
str(nsweep) + std::string(fwd ?
" forward" :
" reverse") +
" sweeps "
1363 "needed for " +
str(seed.size()) +
" directions");
1367 casadi_int progress = -10;
1370 std::vector<casadi_int> jcol, jrow;
1373 for (casadi_int s=0; s<nsweep; ++s) {
1377 casadi_int progress_new = (s*100)/nsweep;
1379 if (progress_new / 10 > progress / 10) {
1380 progress = progress_new;
1381 casadi_message(
str(progress) +
" %");
1389 casadi_int ndir_local = seed.size()-offset;
1390 ndir_local = std::min(
static_cast<casadi_int
>(
bvec_size), ndir_local);
1392 for (casadi_int i=0; i<ndir_local; ++i) {
1393 seed[offset+i] |=
bvec_t(1)<<i;
1401 for (casadi_int el=0; el<sens.size(); ++el) {
1404 bvec_t spsens = sens[el];
1415 for (casadi_int i=0; i<ndir_local; ++i) {
1418 if ((
bvec_t(1) << i) & spsens) {
1421 jrow.push_back(i+offset);
1428 for (casadi_int i=0; i<ndir_local; ++i) {
1434 if (!fwd) swap(jrow, jcol);
1437 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(ret.
size()) +
", "
1444 casadi_int iind)
const {
1448 casadi_int nz =
nnz_in(iind);
1449 casadi_assert_dev(nz==
nnz_out(oind));
1452 std::vector<const bvec_t*> arg(
sz_arg(),
nullptr);
1453 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1454 std::vector<casadi_int> iw(
sz_iw());
1455 std::vector<bvec_t> w(
sz_w());
1458 std::vector<bvec_t> seed(nz, 0);
1462 std::vector<bvec_t> sens(nz, 0);
1466 std::vector<casadi_int> jcol, jrow;
1469 std::vector<casadi_int> coarse(2, 0); coarse[1] = nz;
1472 std::vector<casadi_int> fine;
1480 casadi_int granularity = nz;
1482 casadi_int nsweeps = 0;
1484 bool hasrun =
false;
1486 while (!hasrun || coarse.size()!=nz+1) {
1487 if (
verbose_) casadi_message(
"Block size: " +
str(granularity));
1499 casadi_message(
"Star coloring on " +
str(r.
dim()) +
": "
1500 +
str(
D.size2()) +
" <-> " +
str(
D.size1()));
1504 std::fill(seed.begin(), seed.end(), 0);
1507 for (casadi_int k=0; k<coarse.size()-1; ++k) {
1508 casadi_int
diff = coarse[k+1]-coarse[k];
1509 casadi_int new_diff =
diff/subdivision;
1510 if (
diff%subdivision>0) new_diff++;
1511 std::vector<casadi_int> temp =
range(coarse[k], coarse[k+1], new_diff);
1512 fine.insert(fine.end(), temp.begin(), temp.end());
1514 if (fine.back()!=coarse.back()) fine.push_back(coarse.back());
1516 granularity = fine[1] - fine[0];
1519 casadi_int bvec_i = 0;
1522 std::vector<casadi_int> fine_lookup =
lookupvector(fine, nz+1);
1525 std::vector<casadi_int> lookup_col;
1526 std::vector<casadi_int> lookup_row;
1527 std::vector<casadi_int> lookup_value;
1530 casadi_int n_fine_blocks_max = 0;
1531 for (casadi_int i=0;i<coarse.size()-1;++i) {
1532 casadi_int del = fine_lookup[coarse[i+1]]-fine_lookup[coarse[i]];
1533 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1537 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1540 casadi_int fci_offset = 0;
1544 bool f_finished =
false;
1547 while (!f_finished) {
1550 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1551 casadi_int cci =
D.row(k);
1554 casadi_int fci_start = fine_lookup[coarse[cci]];
1555 casadi_int fci_end = fine_lookup[coarse[cci+1]];
1558 casadi_int bvec_i_mod = 0;
1560 casadi_int value = -bvec_i + fci_offset + fci_start;
1565 for (casadi_int fci = fci_offset; fci<std::min(fci_end-fci_start, fci_cap); ++fci) {
1569 for (casadi_int cri=r.
colind(cci);cri<r.
colind(cci+1);++cri) {
1570 lookup_col.push_back(r.
row(cri));
1571 lookup_row.push_back(bvec_i+bvec_i_mod);
1572 lookup_value.push_back(value);
1583 bvec_i += std::min(n_fine_blocks_max, fci_cap);
1593 IM lookup =
IM::triplet(lookup_row, lookup_col, lookup_value,
1596 std::reverse(lookup_col.begin(), lookup_col.end());
1597 std::reverse(lookup_row.begin(), lookup_row.end());
1598 std::reverse(lookup_value.begin(), lookup_value.end());
1602 duplicates = sparsify(duplicates);
1613 for (casadi_int cri=0; cri<coarse.size()-1; ++cri) {
1616 for (casadi_int fri=fine_lookup[coarse[cri]];fri<fine_lookup[coarse[cri+1]];++fri) {
1621 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1622 if (spsens & (
bvec_t(1) << bvec_i)) {
1625 if (ind==-1)
continue;
1626 casadi_int lk = lookup->at(ind);
1628 jrow.push_back(bvec_i+lk);
1629 jcol.push_back(fri);
1630 jrow.push_back(fri);
1631 jcol.push_back(bvec_i+lk);
1639 std::fill(seed.begin(), seed.end(), 0);
1644 lookup_value.clear();
1647 if (n_fine_blocks_max>fci_cap) {
1648 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1670 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1671 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
1686 std::vector<bvec_t> s_in(
nz_in, 0);
1687 std::vector<bvec_t> s_out(
nz_out, 0);
1690 std::vector<const bvec_t*> arg_fwd(
sz_arg(),
nullptr);
1691 std::vector<bvec_t*> arg_adj(
sz_arg(),
nullptr);
1692 arg_fwd[iind] = arg_adj[iind] =
get_ptr(s_in);
1693 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1695 std::vector<casadi_int> iw(
sz_iw());
1696 std::vector<bvec_t> w(
sz_w());
1699 std::vector<casadi_int> jcol, jrow;
1702 std::vector<casadi_int> coarse_col(2, 0); coarse_col[1] =
nz_out;
1704 std::vector<casadi_int> coarse_row(2, 0); coarse_row[1] =
nz_in;
1707 std::vector<casadi_int> fine_col;
1710 std::vector<casadi_int> fine_row;
1718 casadi_int granularity_row =
nz_in;
1719 casadi_int granularity_col =
nz_out;
1721 bool use_fwd =
true;
1723 casadi_int nsweeps = 0;
1725 bool hasrun =
false;
1731 std::vector<bvec_t> bvec_lookup;
1734 bvec_lookup.push_back(
bvec_t(1) << i);
1737 while (!hasrun || coarse_col.size()!=
nz_out+1 || coarse_row.size()!=
nz_in+1) {
1739 casadi_message(
"Block size: " +
str(granularity_col) +
" x " +
str(granularity_row));
1760 casadi_message(
"Coloring on " +
str(r.
dim()) +
" (fwd seeps: " +
str(D1.
size2()) +
1761 " , adj sweeps: " +
str(D2.
size1()) +
")");
1765 double fwd_cost =
static_cast<double>(use_fwd ? granularity_row : granularity_col) *
1766 sp_w*
static_cast<double>(D1.
size2());
1767 double adj_cost =
static_cast<double>(use_fwd ? granularity_col : granularity_row) *
1768 (1-sp_w)*
static_cast<double>(D2.
size2());
1769 use_fwd = fwd_cost <= adj_cost;
1771 casadi_message(std::string(use_fwd ?
"Forward" :
"Reverse") +
" mode chosen "
1772 "(fwd cost: " +
str(fwd_cost) +
", adj cost: " +
str(adj_cost) +
")");
1784 for (casadi_int i=0; i<nz_seed; ++i) seed_v[i]=0;
1791 std::swap(coarse_col, coarse_row);
1792 std::swap(granularity_col, granularity_row);
1797 for (casadi_int k=0;k<coarse_col.size()-1;++k) {
1798 casadi_int
diff = coarse_col[k+1]-coarse_col[k];
1799 casadi_int new_diff =
diff/subdivision;
1800 if (
diff%subdivision>0) new_diff++;
1801 std::vector<casadi_int> temp =
range(coarse_col[k], coarse_col[k+1], new_diff);
1802 fine_col.insert(fine_col.end(), temp.begin(), temp.end());
1805 for (casadi_int k=0;k<coarse_row.size()-1;++k) {
1806 casadi_int
diff = coarse_row[k+1]-coarse_row[k];
1807 casadi_int new_diff =
diff/subdivision;
1808 if (
diff%subdivision>0) new_diff++;
1809 std::vector<casadi_int> temp =
range(coarse_row[k], coarse_row[k+1], new_diff);
1810 fine_row.insert(fine_row.end(), temp.begin(), temp.end());
1812 if (fine_row.back()!=coarse_row.back()) fine_row.push_back(coarse_row.back());
1813 if (fine_col.back()!=coarse_col.back()) fine_col.push_back(coarse_col.back());
1815 granularity_col = fine_col[1] - fine_col[0];
1816 granularity_row = fine_row[1] - fine_row[0];
1819 casadi_int bvec_i = 0;
1822 std::vector<casadi_int> fine_col_lookup =
lookupvector(fine_col, nz_sens+1);
1823 std::vector<casadi_int> fine_row_lookup =
lookupvector(fine_row, nz_seed+1);
1826 std::vector<casadi_int> lookup_col;
1827 std::vector<casadi_int> lookup_row;
1828 std::vector<casadi_int> lookup_value;
1832 casadi_int n_fine_blocks_max = 0;
1833 for (casadi_int i=0;i<coarse_row.size()-1;++i) {
1834 casadi_int del = fine_row_lookup[coarse_row[i+1]]-fine_row_lookup[coarse_row[i]];
1835 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1839 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1841 casadi_int fci_offset = 0;
1845 bool f_finished =
false;
1848 while (!f_finished) {
1851 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1852 casadi_int cci =
D.row(k);
1855 casadi_int fci_start = fine_row_lookup[coarse_row[cci]];
1856 casadi_int fci_end = fine_row_lookup[coarse_row[cci+1]];
1859 casadi_int bvec_i_mod = 0;
1861 casadi_int value = -bvec_i + fci_offset + fci_start;
1864 for (casadi_int fci = fci_offset; fci < std::min(fci_end-fci_start, fci_cap); ++fci) {
1868 for (casadi_int cri=rT.
colind(cci);cri<rT.
colind(cci+1);++cri) {
1869 lookup_col.push_back(rT.
row(cri));
1870 lookup_row.push_back(bvec_i+bvec_i_mod);
1871 lookup_value.push_back(value);
1875 bvec_toggle(seed_v, fine_row[fci+fci_start], fine_row[fci+fci_start+1],
1882 bvec_i+= std::min(n_fine_blocks_max, fci_cap);
1897 JacSparsityTraits<true>::sp(
this,
get_ptr(arg_fwd),
get_ptr(res),
1900 std::fill(w.begin(), w.end(), 0);
1901 JacSparsityTraits<false>::sp(
this,
get_ptr(arg_adj),
get_ptr(res),
1909 for (casadi_int cri=0;cri<coarse_col.size()-1;++cri) {
1912 for (casadi_int fri=fine_col_lookup[coarse_col[cri]];
1913 fri<fine_col_lookup[coarse_col[cri+1]];++fri) {
1915 bvec_or(sens_v, spsens, fine_col[fri], fine_col[fri+1]);
1918 if (!spsens)
continue;
1921 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1922 if (spsens & bvec_lookup[bvec_i]) {
1925 if (ind==-1)
continue;
1926 jrow.push_back(bvec_i+lookup->at(ind));
1927 jcol.push_back(fri);
1934 std::fill(s_in.begin(), s_in.end(), 0);
1937 std::fill(s_out.begin(), s_out.end(), 0);
1942 lookup_value.clear();
1945 if (n_fine_blocks_max>fci_cap) {
1946 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1961 coarse_col = fine_col;
1962 coarse_row = fine_row;
1966 coarse_col = fine_row;
1967 coarse_row = fine_col;
1972 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1973 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
", " +
1985 if (
name_ ==
"adj1_" + n) {
1986 if (iind == oind)
return true;
1994 bool symmetric)
const {
1997 "Symmetry exploitation in Jacobian assumes dense expression. "
1998 "A potential workaround is to apply densify().");
2030 if (w*
static_cast<double>(nsweep_fwd) <= (1-w)*
static_cast<double>(nsweep_adj)) {
2031 sp = get_jac_sparsity_gen<true>(oind, iind);
2033 sp = get_jac_sparsity_gen<false>(oind, iind);
2046 std::vector<casadi_int> mapping;
2069 bool symmetric)
const {
2070 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2072 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
2075 for (
bool c : {
false,
true}) {
2079 casadi_int ind = iind + oind *
n_in_;
2095 sp_is_compact =
true;
2107 if (sp_is_compact == compact) {
2134 bool compact,
bool symmetric,
2135 bool allow_forward,
bool allow_reverse)
const {
2137 casadi_assert(allow_forward || allow_reverse,
"Inconsistent options");
2146 casadi_assert_dev(allow_forward);
2149 if (
verbose_) casadi_message(
"FunctionInternal::getPartition star_coloring");
2152 casadi_message(
"Star coloring completed: " +
str(D1.
size2())
2153 +
" directional derivatives needed ("
2154 +
str(A.
size1()) +
" without coloring).");
2163 if (w==1) allow_forward =
false;
2164 if (w==0) allow_reverse =
false;
2165 casadi_assert(allow_forward || allow_reverse,
"Conflicting ad weights");
2168 double best_coloring = std::numeric_limits<double>::infinity();
2171 bool test_fwd_first = allow_forward && w*
static_cast<double>(A.
size1()) <=
2172 (1-w)*
static_cast<double>(A.
size2());
2173 casadi_int mode_fwd = test_fwd_first ? 0 : 1;
2176 for (casadi_int mode=0; mode<2; ++mode) {
2178 bool fwd = mode==mode_fwd;
2181 if (!allow_forward && fwd)
continue;
2182 if (!allow_reverse && !fwd)
continue;
2186 if (
verbose_) casadi_message(
"Unidirectional coloring (forward mode)");
2187 bool d = best_coloring>=w*
static_cast<double>(A.
size1());
2188 casadi_int max_colorings_to_test =
2189 d ? A.
size1() :
static_cast<casadi_int
>(floor(best_coloring/w));
2193 casadi_message(
"Forward mode coloring interrupted (more than "
2194 +
str(max_colorings_to_test) +
" needed).");
2198 casadi_message(
"Forward mode coloring completed: "
2199 +
str(D1.
size2()) +
" directional derivatives needed ("
2200 +
str(A.
size1()) +
" without coloring).");
2203 best_coloring = w*
static_cast<double>(D1.
size2());
2206 if (
verbose_) casadi_message(
"Unidirectional coloring (adjoint mode)");
2207 bool d = best_coloring>=(1-w)*
static_cast<double>(A.
size2());
2208 casadi_int max_colorings_to_test =
2209 d ? A.
size2() :
static_cast<casadi_int
>(floor(best_coloring/(1-w)));
2214 casadi_message(
"Adjoint mode coloring interrupted (more than "
2215 +
str(max_colorings_to_test) +
" needed).");
2219 casadi_message(
"Adjoint mode coloring completed: "
2220 +
str(D2.
size2()) +
" directional derivatives needed ("
2221 +
str(A.
size2()) +
" without coloring).");
2224 best_coloring = (1-w)*
static_cast<double>(D2.
size2());
2233 casadi_error(
"'eval_dm' not defined for " +
class_name());
2238 bool always_inline,
bool never_inline)
const {
2243 casadi_assert(!always_inline,
"'eval_sx' not defined for " +
class_name() +
2244 " in combination with always_inline true");
2251 casadi_int highest_index = 0;
2254 for (
const std::string& n : name_io) {
2256 size_t end = n.find(
'_');
2257 if (end >= n.size())
continue;
2259 if (end < prefix.size())
continue;
2261 if (n.compare(0, prefix.size(), prefix) != 0)
continue;
2263 size_t begin = prefix.size();
2265 casadi_int this_index;
2271 this_index = std::stoi(n.substr(begin, end - begin));
2274 if (this_index > highest_index) highest_index = this_index;
2278 if (highest_index == 0) {
2279 return prefix +
"_";
2281 return prefix + std::to_string(highest_index + 1) +
"_";
2286 casadi_assert_dev(nfwd>=0);
2301 std::vector<std::string> inames;
2304 for (i=0; i<
n_in_; ++i) inames.push_back(pref +
name_in_[i]);
2306 std::vector<std::string> onames;
2315 opts[
"derivative_of"] =
self();
2319 f =
get_forward(nfwd, fname, inames, onames, opts);
2332 casadi_error(
"Unknown 'fd_method': " +
fd_method_);
2351 casadi_assert_dev(nadj>=0);
2366 std::vector<std::string> inames;
2371 std::vector<std::string> onames;
2372 for (casadi_int i=0; i<
n_in_; ++i) onames.push_back(pref +
name_in_[i]);
2376 opts[
"derivative_of"] =
self();
2379 f =
get_reverse(nadj, fname, inames, onames, opts);
2396 get_forward(casadi_int nfwd,
const std::string& name,
2397 const std::vector<std::string>& inames,
2398 const std::vector<std::string>& onames,
2399 const Dict& opts)
const {
2400 casadi_error(
"'get_forward' not defined for " +
class_name());
2404 get_reverse(casadi_int nadj,
const std::string& name,
2405 const std::vector<std::string>& inames,
2406 const std::vector<std::string>& onames,
2407 const Dict& opts)
const {
2408 casadi_error(
"'get_reverse' not defined for " +
class_name());
2412 const Dict& options)
const {
2413 casadi_error(
"'export_code' not defined for " +
class_name());
2417 casadi_int n = s.size();
2419 std::stringstream ss;
2420 for (casadi_int i=0;i<n;++i) {
2424 casadi_assert_dev(s==ss.str());
2429 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
nnz_in(iind);
2435 for (casadi_int oind=0; oind<
n_out_; ++oind) ret +=
nnz_out(oind);
2441 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
numel_in(iind);
2452 bool always_inline,
bool never_inline)
const {
2458 if (always_inline) {
2459 casadi_assert(!never_inline,
"Inconsistent options for " +
str(
name_));
2473 "Derivatives cannot be calculated for " +
name_);
2478 std::string fname =
"jac_" +
name_;
2481 std::vector<std::string> inames;
2482 for (casadi_int i=0; i<
n_in_; ++i) inames.push_back(
name_in_[i]);
2483 for (casadi_int i=0; i<
n_out_; ++i) inames.push_back(
"out_" +
name_out_[i]);
2485 std::vector<std::string> onames;
2487 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2488 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2494 opts[
"derivative_of"] =
self();
2499 casadi_assert(f.
n_in() == inames.size(),
2500 "Mismatching input signature, expected " +
str(inames));
2501 casadi_assert(f.
n_out() == onames.size(),
2502 "Mismatching output signature, expected " +
str(onames));
2511 const std::vector<std::string>& inames,
2512 const std::vector<std::string>& onames,
2513 const Dict& opts)
const {
2514 casadi_error(
"'get_jacobian' not defined for " +
class_name());
2520 g <<
"static " <<
signature(fname) <<
" {\n";
2528 Function F = shared_from_this<Function>();
2530 std::string dump_counter = g.
shorthand(cg_name +
"_dump_counter");
2531 g.
auxiliaries <<
"static int " << dump_counter <<
" = 0;\n";
2534 std::string dump_mutex = g.
local_mutex(F, cg_name +
"_dump_mutex");
2535 g <<
"CASADI_MUTEX_LOCK(&" << dump_mutex <<
");\n";
2536 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2537 g <<
"CASADI_MUTEX_UNLOCK(&" << dump_mutex <<
");\n";
2539 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2563 return "int " + fname +
"(const casadi_real** arg, casadi_real** res, "
2564 "casadi_int* iw, casadi_real* w, int mem)";
2568 std::vector<std::string> args;
2570 args.push_back(
"const casadi_real* " +
str(e));
2573 args.push_back(
"casadi_real* " +
str(e));
2575 args.push_back(
"const casadi_real** arg");
2576 args.push_back(
"casadi_real** res");
2577 args.push_back(
"casadi_int* iw");
2578 args.push_back(
"casadi_real* w");
2579 args.push_back(
"int mem");
2580 return "int " + fname +
"_unrolled(" +
join(args,
", ") +
")";
2586 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2587 g.
auxiliaries <<
"static int " << ref_counter <<
" = 0;\n";
2589 Function F = shared_from_this<Function>();
2593 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2594 g <<
"if (" << ref_counter <<
"==0) CASADI_MUTEX_INIT(&" << mtx <<
");\n";
2598 g << ref_counter <<
"++;\n";
2602 std::set<void*> added;
2603 Function F = shared_from_this<Function>();
2605 if (f->has_refcount_in_deps_) {
2606 std::string cg_name = f->codegen_name(g,
false);
2607 auto i = added.insert(f.get());
2609 std::string incref = g.
shorthand(cg_name +
"_incref");
2610 g << incref <<
"();\n";
2619 std::set<void*> added;
2620 Function F = shared_from_this<Function>();
2622 if (f->has_refcount_in_deps_) {
2623 std::string cg_name = f->codegen_name(g,
false);
2624 auto i = added.insert(f.get());
2626 std::string decref = g.
shorthand(cg_name +
"_decref");
2627 g << decref <<
"();\n";
2634 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2635 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2637 g << ref_counter <<
"--;\n";
2638 g <<
"if (" << ref_counter <<
"==0) {\n";
2640 g <<
"while (" << mem_counter <<
">0) {\n";
2641 g <<
free_mem <<
"(--" << mem_counter <<
");\n";
2645 Function F = shared_from_this<Function>();
2648 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2649 g <<
"CASADI_MUTEX_DESTROY(&" << mtx <<
");\n";
2665 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2666 g <<
"return " + mem_counter +
"++;\n";
2672 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2673 std::string stack = g.
shorthand(name +
"_unused_stack");
2674 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2675 std::string mem_array = g.
shorthand(name +
"_mem");
2680 g.
auxiliaries <<
"static int " << mem_counter <<
" = 0;\n";
2681 g.
auxiliaries <<
"static int " << stack_counter <<
" = -1;\n";
2682 g.
auxiliaries <<
"static int " << stack <<
"[CASADI_MAX_NUM_THREADS];\n";
2684 " " << mem_array <<
"[CASADI_MAX_NUM_THREADS];\n\n";
2687 Function F = shared_from_this<Function>();
2689 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2690 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2694 g.
local(
"mid",
"int");
2696 g <<
"if (" << stack_counter <<
">=0) {\n";
2699 g <<
"if (" << mem_counter <<
"==CASADI_MAX_NUM_THREADS) {\n";
2703 g <<
"if (mid<0) {\n";
2706 g <<
"if (" <<
init_mem <<
"(mid)) {\n";
2715 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2716 std::string stack = g.
shorthand(name +
"_unused_stack");
2719 Function F = shared_from_this<Function>();
2720 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2721 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2725 g << stack <<
"[++" << stack_counter <<
"] = mem;\n";
2738 g << g.
declare(
"int " +
name_ +
"_checkout(void)") <<
" {\n";
2741 g <<
"return " <<
checkout <<
"();\n";
2748 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2752 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2757 g << g.
declare(
"void " +
name_ +
"_incref(void)") <<
" {\n";
2759 std::string incref = g.
shorthand(name +
"_incref");
2760 g << incref <<
"();\n";
2763 << g.
declare(
"void " +
name_ +
"_decref(void)") <<
" {\n";
2765 std::string decref = g.
shorthand(name +
"_decref");
2766 g << decref <<
"();\n";
2772 <<
" { return " <<
n_in_ <<
";}\n\n"
2774 <<
" { return " <<
n_out_ <<
";}\n\n";
2777 g << g.
declare(
"casadi_real " +
name_ +
"_default_in(casadi_int i)") <<
" {\n"
2778 <<
"switch (i) {\n";
2779 for (casadi_int i=0; i<
n_in_; ++i) {
2781 if (def!=0) g <<
"case " << i <<
": return " << g.
constant(def) <<
";\n";
2783 g <<
"default: return 0;\n}\n"
2787 g << g.
declare(
"const char* " +
name_ +
"_name_in(casadi_int i)") <<
" {\n"
2788 <<
"switch (i) {\n";
2789 for (casadi_int i=0; i<
n_in_; ++i) {
2790 g <<
"case " << i <<
": return \"" <<
name_in_[i] <<
"\";\n";
2792 g <<
"default: return 0;\n}\n"
2796 g << g.
declare(
"const char* " +
name_ +
"_name_out(casadi_int i)") <<
" {\n"
2797 <<
"switch (i) {\n";
2798 for (casadi_int i=0; i<
n_out_; ++i) {
2799 g <<
"case " << i <<
": return \"" <<
name_out_[i] <<
"\";\n";
2801 g <<
"default: return 0;\n}\n"
2809 "int " +
name_ +
"_work(casadi_int *sz_arg, casadi_int* sz_res, "
2810 "casadi_int *sz_iw, casadi_int *sz_w)")
2821 "int " +
name_ +
"_work_bytes(casadi_int *sz_arg, casadi_int* sz_res, "
2822 "casadi_int *sz_iw, casadi_int *sz_w)")
2824 <<
"if (sz_arg) *sz_arg = " <<
codegen_sz_arg(g) <<
"*sizeof(const casadi_real*);\n"
2825 <<
"if (sz_res) *sz_res = " <<
codegen_sz_res(g) <<
"*sizeof(casadi_real*);\n"
2826 <<
"if (sz_iw) *sz_iw = " <<
codegen_sz_iw(g) <<
"*sizeof(casadi_int);\n"
2827 <<
"if (sz_w) *sz_w = " <<
codegen_sz_w(g) <<
"*sizeof(casadi_real);\n"
2842 g << g.
declare(
"int " +
name_ +
"_diff_in(casadi_int i)") <<
" {\n"
2843 <<
"switch (i) {\n";
2844 for (casadi_int i=0; i<
n_in_; ++i) {
2845 g <<
"case " << i <<
": return " <<
is_diff_in_[i] <<
";\n";
2847 g <<
"default: return -1;\n}\n"
2853 g << g.
declare(
"int " +
name_ +
"_diff_out(casadi_int i)") <<
" {\n"
2854 <<
"switch (i) {\n";
2855 for (casadi_int i=0; i<
n_out_; ++i) {
2856 g <<
"case " << i <<
": return " <<
is_diff_out_[i] <<
";\n";
2858 g <<
"default: return -1;\n}\n"
2865 g <<
"#ifdef MATLAB_MEX_FILE\n";
2868 g <<
"void mex_" <<
name_
2869 <<
"(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {\n"
2870 <<
"casadi_int i;\n";
2875 for (casadi_int i=0; i<
n_in_; ++i) {
2880 sz_w += i_nnz + o_nnz;
2883 std::string fw =
"w+" +
str(i_nnz + o_nnz);
2886 casadi_int offset=0;
2890 g <<
"casadi_real* res[" <<
sz_res() <<
"] = {0};\n";
2893 g <<
"if (argc>" <<
n_in_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2894 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. Too many input arguments "
2895 <<
"(%d, max " <<
n_in_ <<
")\", argc);\n";
2897 g <<
"if (resc>" <<
n_out_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2898 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. "
2899 <<
"Too many output arguments (%d, max " <<
n_out_ <<
")\", resc);\n";
2901 for (casadi_int i=0; i<
n_in_; ++i) {
2902 std::string p =
"argv[" +
str(i) +
"]";
2903 g <<
"if (--argc>=0) arg[" << i <<
"] = "
2908 for (casadi_int i=0; i<
n_out_; ++i) {
2914 g <<
"if (--resc>=0) ";
2917 g << g.
res(i) <<
" = w+" <<
str(offset) <<
";\n";
2920 g <<
name_ <<
"_incref();\n";
2921 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2924 g <<
"i = " <<
name_ <<
"(arg, res, iw, " << fw <<
", mem);\n"
2925 <<
"if (i) mexErrMsgIdAndTxt(\"Casadi:RuntimeError\",\"Evaluation of \\\"" <<
name_
2926 <<
"\\\" failed.\");\n";
2927 g <<
name_ <<
"_release(mem);\n";
2928 g <<
name_ <<
"_decref();\n";
2931 for (casadi_int i=0; i<
n_out_; ++i) {
2932 g <<
"if (" << g.
res(i) <<
") resv[" << i <<
"] = "
2943 g <<
"casadi_int main_" <<
name_ <<
"(casadi_int argc, char* argv[]) {\n";
2945 g <<
"casadi_int j;\n";
2946 g <<
"casadi_real* a;\n";
2947 g <<
"const casadi_real* r;\n";
2948 g <<
"casadi_int flag;\n";
2949 if (needs_mem) g <<
"int mem;\n";
2959 g <<
"const casadi_real* arg[" <<
sz_arg() <<
"];\n";
2962 g <<
"casadi_real* res[" <<
sz_res() <<
"];\n";
2965 for (casadi_int i=0; i<
n_in_; ++i) {
2966 g <<
"arg[" << i <<
"] = w+" << off <<
";\n";
2969 for (casadi_int i=0; i<
n_out_; ++i) {
2970 g <<
"res[" << i <<
"] = w+" << off <<
";\n";
2976 <<
"for (j=0; j<" <<
nnz_in() <<
"; ++j) "
2977 <<
"if (scanf(\"%lg\", a++)<=0) return 2;\n";
2980 g <<
name_ <<
"_incref();\n";
2984 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2988 g <<
"flag = " <<
name_ <<
"(arg, res, iw, w+" << off <<
", ";
2996 g <<
name_ <<
"_release(mem);\n";
3000 g <<
name_ <<
"_decref();\n";
3003 g <<
"if (flag) return flag;\n";
3006 g <<
"r = w+" <<
nnz_in() <<
";\n"
3007 <<
"for (j=0; j<" <<
nnz_out() <<
"; ++j) "
3008 << g.
printf(
"%.16e ",
"*r++") <<
"\n";
3011 g << g.
printf(
"\\n") <<
"\n";
3020 g << g.
declare(
"casadi_functions* " +
name_ +
"_functions(void)") <<
" {\n"
3021 <<
"static casadi_functions fun = {\n"
3022 <<
name_ <<
"_incref,\n"
3023 <<
name_ <<
"_decref,\n"
3024 <<
name_ <<
"_checkout,\n"
3025 <<
name_ <<
"_release,\n"
3026 <<
name_ <<
"_default_in,\n"
3027 <<
name_ <<
"_n_in,\n"
3028 <<
name_ <<
"_n_out,\n"
3029 <<
name_ <<
"_name_in,\n"
3030 <<
name_ <<
"_name_out,\n"
3031 <<
name_ <<
"_sparsity_in,\n"
3032 <<
name_ <<
"_sparsity_out,\n"
3033 <<
name_ <<
"_work,\n"
3047 if (e.f.get()==
this)
return e.codegen_name;
3052 if (e.f.get()==
this)
return "f" +
str(i);
3055 casadi_error(
"Function '" +
name_ +
"' not found");
3060 std::string mem_array = g.
shorthand(name +
"_mem");
3061 return mem_array+
"[" + index +
"]";
3069 casadi_warning(
"The function \"" +
name_ +
"\", which is of type \""
3070 +
class_name() +
"\" cannot be code generated. The generation "
3071 "will proceed, but compilation of the code will not be possible.");
3072 g <<
"#error Code generation not supported for " <<
class_name() <<
"\n";
3077 casadi_error(
"'generate_dependencies' not defined for " +
class_name());
3083 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3084 if (res[oind]==
nullptr)
continue;
3085 std::fill_n(res[oind],
nnz_out(oind), ~
static_cast<bvec_t>(0));
3093 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3095 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3099 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3101 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3110 casadi_int* iw,
bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const {
3115 casadi_int d1 = sp.
size2();
3116 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3117 for (casadi_int cc=0; cc<d1; ++cc) {
3118 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3119 res[oind][row[el]] |= arg[iind][cc];
3128 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3130 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3133 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3135 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3142 casadi_int d1 = sp.
size2();
3143 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3144 for (casadi_int cc=0; cc<d1; ++cc) {
3145 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3146 arg[iind][cc] |= res[oind][row[el]];
3158 size_t& sz_iw,
size_t& sz_w)
const {
3161 sz_iw = this->
sz_iw();
3162 sz_w = this->
sz_w();
3182 sz_arg_tmp_ = std::max(sz_arg_tmp_,
sz_arg);
3190 sz_res_tmp_ = std::max(sz_res_tmp_,
sz_res);
3196 sz_iw_per_ +=
sz_iw;
3198 sz_iw_tmp_ = std::max(sz_iw_tmp_,
sz_iw);
3206 sz_w_tmp_ = std::max(sz_w_tmp_,
sz_w);
3225 for (
const auto& s : m->fstats) {
3226 stats[
"n_call_" +s.first] = s.second.n_call;
3227 stats[
"t_wall_" +s.first] = s.second.t_wall;
3228 stats[
"t_proc_" +s.first] = s.second.t_proc;
3236 casadi_assert(m->stats_available,
3237 "No stats available: Function '" +
name_ +
"' not set up. "
3238 "To get statistics, first evaluate it numerically.");
3283 call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3284 const std::vector<std::vector<MX> >& fseed,
3285 std::vector<std::vector<MX> >& fsens,
3286 bool always_inline,
bool never_inline)
const {
3287 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3288 casadi_assert(!always_inline,
"Class " +
class_name() +
3289 " cannot be inlined in an MX expression");
3293 "Derivatives cannot be calculated for " +
name_);
3296 casadi_int nfwd = fseed.size();
3300 if (nfwd==0)
return;
3303 casadi_int npar = 1;
3304 for (
auto&& r : fseed) {
3307 fsens, always_inline, never_inline);
3315 std::vector<MX> darg = arg;
3316 darg.insert(darg.end(), res.begin(), res.end());
3317 std::vector<MX> J =
jacobian()(darg);
3319 std::vector<MX> v(nfwd), all_fseed(
n_in_);
3320 for (
size_t i = 0; i <
n_in_; ++i) {
3321 for (
size_t d = 0; d < nfwd; ++d) v[d] = vec(fseed.at(d).at(i));
3322 all_fseed[i] = horzcat(v);
3325 std::vector<MX> all_fsens(
n_out_);
3326 std::vector<MX>::const_iterator J_it = J.begin();
3327 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3328 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3330 MX a = mtimes(*J_it++, all_fseed[iind]);
3331 all_fsens[oind] = all_fsens[oind].is_empty(
true) ? a : all_fsens[oind] + a;
3335 for (
size_t d = 0; d < nfwd; ++d) fsens[d].resize(
n_out_);
3336 for (
size_t i = 0; i <
n_out_; ++i) {
3337 v = horzsplit(all_fsens[i]);
3338 casadi_assert_dev(v.size() == nfwd);
3339 for (
size_t d = 0; d < nfwd; ++d) fsens[d][i] = reshape(v[d],
size_out(i));
3348 casadi_int offset = 0;
3349 while (offset<nfwd) {
3351 casadi_int nfwd_batch = std::min(nfwd-offset, max_nfwd);
3354 std::vector<MX> darg;
3356 darg.insert(darg.end(), arg.begin(), arg.end());
3357 darg.insert(darg.end(), res.begin(), res.end());
3358 std::vector<MX> v(nfwd_batch);
3359 for (casadi_int i=0; i<
n_in_; ++i) {
3360 for (casadi_int d=0; d<nfwd_batch; ++d) v[d] = fseed[offset+d][i];
3361 darg.push_back(horzcat(v));
3366 std::vector<MX> x = dfcn(darg);
3368 casadi_assert_dev(x.size()==
n_out_);
3371 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d].resize(
n_out_);
3372 for (casadi_int i=0; i<
n_out_; ++i) {
3375 casadi_assert_dev(v.size()==nfwd_batch);
3377 v = std::vector<MX>(nfwd_batch,
MX(
size_out(i)));
3379 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d][i] = v[d];
3383 offset += nfwd_batch;
3389 call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3390 const std::vector<std::vector<MX> >& aseed,
3391 std::vector<std::vector<MX> >& asens,
3392 bool always_inline,
bool never_inline)
const {
3393 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3394 casadi_assert(!always_inline,
"Class " +
class_name() +
3395 " cannot be inlined in an MX expression");
3399 "Derivatives cannot be calculated for " +
name_);
3402 casadi_int nadj = aseed.size();
3406 if (nadj==0)
return;
3409 casadi_int npar = 1;
3410 for (
auto&& r : aseed) {
3413 asens, always_inline, never_inline);
3421 std::vector<MX> darg = arg;
3422 darg.insert(darg.end(), res.begin(), res.end());
3423 std::vector<MX> J =
jacobian()(darg);
3425 std::vector<MX> v(nadj), all_aseed(
n_out_);
3426 for (
size_t i = 0; i <
n_out_; ++i) {
3427 for (
size_t d = 0; d < nadj; ++d) v[d] = vec(aseed.at(d).at(i));
3428 all_aseed[i] = horzcat(v);
3431 std::vector<MX> all_asens(
n_in_);
3432 std::vector<MX>::const_iterator J_it = J.begin();
3433 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3434 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3436 MX a = mtimes((*J_it++).
T(), all_aseed[oind]);
3437 all_asens[iind] = all_asens[iind].is_empty(
true) ? a : all_asens[iind] + a;
3441 for (
size_t d = 0; d < nadj; ++d) asens[d].resize(
n_in_);
3442 for (
size_t i = 0; i <
n_in_; ++i) {
3443 v = horzsplit(all_asens[i]);
3444 casadi_assert_dev(v.size() == nadj);
3445 for (
size_t d = 0; d < nadj; ++d) {
3446 if (asens[d][i].is_empty(
true)) {
3447 asens[d][i] = reshape(v[d],
size_in(i));
3449 asens[d][i] += reshape(v[d],
size_in(i));
3459 casadi_int offset = 0;
3460 while (offset<nadj) {
3462 casadi_int nadj_batch = std::min(nadj-offset, max_nadj);
3465 std::vector<MX> darg;
3467 darg.insert(darg.end(), arg.begin(), arg.end());
3468 darg.insert(darg.end(), res.begin(), res.end());
3469 std::vector<MX> v(nadj_batch);
3470 for (casadi_int i=0; i<
n_out_; ++i) {
3471 for (casadi_int d=0; d<nadj_batch; ++d) v[d] = aseed[offset+d][i];
3472 darg.push_back(horzcat(v));
3477 std::vector<MX> x = dfcn(darg);
3478 casadi_assert_dev(x.size()==
n_in_);
3481 for (casadi_int d=0; d<nadj_batch; ++d) asens[offset+d].resize(
n_in_);
3482 for (casadi_int i=0; i<
n_in_; ++i) {
3485 casadi_assert_dev(v.size()==nadj_batch);
3487 v = std::vector<MX>(nadj_batch,
MX(
size_in(i)));
3489 for (casadi_int d=0; d<nadj_batch; ++d) {
3490 if (asens[offset+d][i].is_empty(
true)) {
3491 asens[offset+d][i] = v[d];
3493 asens[offset+d][i] += v[d];
3498 offset += nadj_batch;
3504 call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3505 const std::vector<std::vector<SX> >& fseed,
3506 std::vector<std::vector<SX> >& fsens,
3507 bool always_inline,
bool never_inline)
const {
3508 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3509 if (fseed.empty()) {
3513 casadi_error(
"'forward' (SX) not defined for " +
class_name());
3517 call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3518 const std::vector<std::vector<SX> >& aseed,
3519 std::vector<std::vector<SX> >& asens,
3520 bool always_inline,
bool never_inline)
const {
3521 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3522 if (aseed.empty()) {
3526 casadi_error(
"'reverse' (SX) not defined for " +
class_name());
3568 std::vector<SX> ret(
n_in_);
3569 for (casadi_int i=0; i<ret.size(); ++i) {
3576 std::vector<SX> ret(
n_out_);
3577 for (casadi_int i=0; i<ret.size(); ++i) {
3584 std::vector<DM> ret(
n_in_);
3585 for (casadi_int i=0; i<ret.size(); ++i) {
3592 std::vector<DM> ret(
n_out_);
3593 for (casadi_int i=0; i<ret.size(); ++i) {
3608 std::vector<MX> ret(
n_in_);
3609 for (casadi_int i=0; i<ret.size(); ++i) {
3616 std::vector<MX> ret(
n_out_);
3617 for (casadi_int i=0; i<ret.size(); ++i) {
3624 return type ==
"FunctionInternal";
3628 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const {
3632 casadi_error(
"'free_mx' only defined for 'MXFunction'");
3636 casadi_error(
"'free_sx' only defined for 'SXFunction'");
3641 casadi_error(
"'generate_lifted' only defined for 'MXFunction'");
3645 casadi_error(
"'n_instructions' not defined for " +
class_name());
3649 casadi_error(
"'instruction_id' not defined for " +
class_name());
3653 casadi_error(
"'instruction_input' not defined for " +
class_name());
3657 casadi_error(
"'instruction_constant' not defined for " +
class_name());
3661 casadi_error(
"'instruction_output' not defined for " +
class_name());
3665 casadi_error(
"'instruction_MX' not defined for " +
class_name());
3669 casadi_error(
"'instructions_sx' not defined for " +
class_name());
3673 casadi_error(
"'n_nodes' not defined for " +
class_name());
3678 const std::string& parallelization) {
3679 if (x.empty())
return x;
3681 casadi_assert(x.size()==
n_in_,
"mapsum_mx: Wrong number_i of arguments");
3683 casadi_int npar = 1;
3685 std::vector<MX> x_mod(x.size());
3686 for (casadi_int i=0; i<
n_in_; ++i) {
3697 for (casadi_int i=0; i<x_mod.size(); ++i) {
3698 n = std::max(x_mod[i].size2() /
size2_in(i), n);
3701 std::vector<casadi_int> reduce_in;
3702 for (casadi_int i=0; i<x_mod.size(); ++i) {
3703 if (x_mod[i].size2()/
size2_in(i)!=n) {
3704 reduce_in.push_back(i);
3716 if (arg.
size()==inp.
size())
return true;
3738 casadi_assert(
nnz_in()==arg.size(),
3739 "Dimension mismatch. Expecting " +
str(
nnz_in()) +
3740 ", got " +
str(arg.size()) +
" instead.");
3742 std::vector<DM> ret =
dm_in();
3743 casadi_int offset = 0;
3744 for (casadi_int i=0;i<
n_in_;++i) {
3746 std::copy(arg.begin()+offset, arg.begin()+offset+
nnz_in(i), r.
ptr());
3753 casadi_assert(
nnz_out()==res.size(),
3754 "Dimension mismatch. Expecting " +
str(
nnz_out()) +
3755 ", got " +
str(res.size()) +
" instead.");
3757 std::vector<DM> ret =
dm_out();
3758 casadi_int offset = 0;
3759 for (casadi_int i=0;i<
n_out_;++i) {
3761 std::copy(res.begin()+offset, res.begin()+offset+
nnz_out(i), r.
ptr());
3769 casadi_int npar = -1;
3775 std::vector<double> ret(
nnz_in());
3776 casadi_int offset = 0;
3777 for (casadi_int i=0;i<
n_in_;++i) {
3778 const double* e = arg2.at(i).ptr();
3779 std::copy(e, e+
nnz_in(i), ret.begin()+offset);
3787 casadi_int npar = -1;
3793 std::vector<double> ret(
nnz_out());
3794 casadi_int offset = 0;
3795 for (casadi_int i=0;i<
n_out_;++i) {
3796 const double* e = res2.at(i).ptr();
3797 std::copy(e, e+
nnz_out(i), ret.begin()+offset);
3804 casadi_int* iw,
double* w)
const {
3812 for (
auto&& i : mem_) {
3821 if (
name_ ==
"jac_" + n) {
3823 }
else if (
name_ ==
"adj1_" + n) {
3834 if (
name_ ==
"jac_" + n) {
3836 }
else if (
name_ ==
"adj1_" + n) {
3847 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
3868 if (
name_ ==
"jac_" + n) {
3882 std::vector<casadi_int> row, colind;
3883 row.reserve(sp_out.
nnz() * sp_in.
nnz());
3884 colind.reserve(sp_in.
numel() + 1);
3886 for (casadi_int c1 = 0; c1 < sp_in.
size2(); ++c1) {
3887 for (casadi_int k1 = sp_in.
colind(c1); k1 < sp_in.
colind(c1 + 1); ++k1) {
3888 casadi_int e1 = sp_in.
row(k1) + sp_in.
size1() * c1;
3890 colind.resize(e1 + 1, row.size());
3892 for (casadi_int c2 = 0; c2 < sp_out.
size2(); ++c2) {
3893 for (casadi_int k2 = sp_out.
colind(c2); k2 < sp_out.
colind(c2 + 1); ++k2) {
3894 row.push_back(sp_out.
row(k2) + sp_out.
size1() * c2);
3900 colind.resize(sp_in.
numel() + 1, row.size());
3903 }
else if (
name_ ==
"adj1_" + n) {
3913 #ifdef CASADI_WITH_THREAD
3914 std::lock_guard<std::mutex> lock(mtx_);
3916 return mem_.at(ind);
3920 return ind<mem_.size();
3924 #ifdef CASADI_WITH_THREAD
3925 std::lock_guard<std::mutex> lock(mtx_);
3927 if (unused_.empty()) {
3933 casadi_error(
"Failed to create or initialize memory object");
3935 return static_cast<int>(mem_.size()) - 1;
3938 int m = unused_.top();
3945 #ifdef CASADI_WITH_THREAD
3946 std::lock_guard<std::mutex> lock(mtx_);
3952 factory(
const std::string& name,
3953 const std::vector<std::string>& s_in,
3954 const std::vector<std::string>& s_out,
3956 const Dict& opts)
const {
3957 return wrap().
factory(name, s_in, s_out, aux, opts);
3962 return std::vector<std::string>();
3967 return std::find(fnames.begin(), fnames.end(), fname)!=fnames.end();
3971 casadi_error(
"'get_function' not defined for " +
class_name());
3978 const Function& dep, casadi_int max_depth)
const {
3980 if (!dep.
is_null() && all_fun.find(dep.
get()) == all_fun.end()) {
3981 size_t index = all_fun.size();
3982 all_fun[dep.
get()] = std::make_pair(dep, index);
3984 if (max_depth > 0) dep->
find(all_fun, max_depth - 1);
3989 casadi_int max_depth)
const {
3996 which_depends(
const std::string& s_in,
const std::vector<std::string>& s_out,
3997 casadi_int order,
bool tr)
const {
3998 Function f = shared_from_this<Function>();
4004 const std::vector<std::pair<std::string, casadi_int> >& tasks)
const {
4005 casadi_assert(tasks.empty(),
"simplify passes not supported for " +
class_name());
4010 casadi_error(
"'oracle' not defined for " +
class_name());
4016 const std::vector<casadi_int>& order_in,
4017 const std::vector<casadi_int>& order_out,
const Dict& opts)
const {
4018 return wrap().
slice(name, order_in, order_out, opts);
4023 for (casadi_int i=0; i<
n_in_; ++i) {
4027 for (casadi_int i=0; i<
n_out_; ++i) {
4035 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
4037 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
4039 casadi_int ind = iind + oind *
n_in_;
4047 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
4052 std::vector<DM> argv(
n_in_);
4053 for (casadi_int i=0; i<
n_in_; ++i) {
4055 casadi_copy(arg[i], argv[i].nnz(), argv[i].ptr());
4059 std::vector<DM> resv =
eval_dm(argv);
4062 casadi_assert(resv.size()==
n_out_,
4063 "Expected " +
str(
n_out_) +
" outputs, got " +
str(resv.size()) +
".");
4066 for (casadi_int i=0; i<
n_out_; ++i) {
4071 casadi_error(
"Shape mismatch for output " +
str(i) +
": got " + resv[i].dim() +
", "
4075 if (res[i])
casadi_copy(resv[i].ptr(), resv[i].nnz(), res[i]);
4079 }
catch(std::exception& e) {
4080 casadi_error(
"Failed to evaluate 'eval_dm' for " +
name_ +
":\n" + e.what());
4085 casadi_error(
"'eval' not defined for " +
class_name());
4094 for (
auto &&s : fstats) {
4095 name_len = std::max(s.first.size(), name_len);
4097 name_len = std::max(
name_.size(), name_len);
4101 sprint(namefmt,
sizeof(namefmt),
"%%%ds ",
static_cast<casadi_int
>(name_len));
4106 print(
" : %8s %10s %8s %10s %9s\n",
"t_proc",
"(avg)",
"t_wall",
"(avg)",
"n_eval");
4109 char buffer_proc[10];
4110 char buffer_wall[10];
4111 char buffer_proc_avg[10];
4112 char buffer_wall_avg[10];
4115 for (
const auto &s : fstats) {
4116 if (s.second.n_call!=0) {
4117 print(namefmt, s.first.c_str());
4120 format_time(buffer_proc_avg, s.second.t_proc/s.second.n_call);
4121 format_time(buffer_wall_avg, s.second.t_wall/s.second.n_call);
4122 print(
" | %s (%s) %s (%s) %9d\n",
4123 buffer_proc, buffer_proc_avg,
4124 buffer_wall, buffer_wall_avg, s.second.n_call);
4131 casadi_assert_dev(time>=0);
4132 double log_time = log10(time);
4133 int magn =
static_cast<int>(floor(log_time));
4134 int iprefix =
static_cast<int>(floor(log_time/3));
4136 sprint(buffer, 10,
" 0");
4140 sprint(buffer, 10,
" inf");
4143 char prefixes[] =
"TGMk munp";
4144 char prefix = prefixes[4-iprefix];
4146 int rem = magn-3*iprefix;
4147 double time_normalized = time/pow(10, 3*iprefix);
4150 sprint(buffer, 10,
" %1.2f%cs", time_normalized, prefix);
4151 }
else if (rem==1) {
4152 sprint(buffer, 10,
" %2.2f%cs", time_normalized, prefix);
4154 sprint(buffer, 10,
"%3.2f%cs", time_normalized, prefix);
4161 va_start(args, fmt);
4163 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4167 casadi_assert(n>=0 && n<buf_sz,
"Print failure while processing '" + std::string(fmt) +
"'");
4173 va_start(args, fmt);
4176 size_t buf_sz =
sizeof(buf);
4177 char* buf_dyn =
nullptr;
4179 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4181 if (n>
static_cast<casadi_int
>(buf_sz)) {
4182 buf_sz =
static_cast<size_t>(n+1);
4183 buf_dyn =
new char[buf_sz];
4184 n = vsnprintf(buf_dyn, buf_sz, fmt, args);
4187 if (n>=0)
uout() << (buf_dyn ? buf_dyn : buf) << std::flush;
4192 casadi_assert(n>=0,
"Print failure while processing '" + std::string(fmt) +
"'");
4197 bool always_inline,
bool never_inline)
const {
4199 eval_mx(arg, res, always_inline, never_inline);
4202 std::vector<std::vector<MX>> v(npar, arg);
4204 for (
int i=0; i<
n_in_; ++i) {
4206 t = horzsplit(arg[i],
size2_in(i));
4207 casadi_assert_dev(t.size()==npar);
4208 for (
int p=0; p<npar; ++p) v[p][i] = t[p];
4212 for (
int p=0; p<npar; ++p) {
4213 eval_mx(v[p], t, always_inline, never_inline);
4219 for (
int i=0; i<
n_out_; ++i) {
4220 for (
int p=0; p<npar; ++p) t[p] = v[p][i];
4221 res[i] = horzcat(t);
4231 default:
return "SOLVER_RET_UNKNOWN";
4236 s.
version(
"ProtoFunction", 2);
4246 int version = s.
version(
"ProtoFunction", 1, 2);
4261 s.
version(
"FunctionInternal", 9);
4269 s.
pack(
"FunctionInternal::jit",
jit_);
4277 casadi_assert(binary_ptr,
"Could not open library '" +
compiler_.
library() +
"'.");
4278 s.
pack(
"FunctionInternal::jit_binary", *binary_ptr);
4330 s.
pack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4331 s.
pack(
"FunctionInternal::sz_res_per", sz_res_per_);
4332 s.
pack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4333 s.
pack(
"FunctionInternal::sz_w_per", sz_w_per_);
4334 s.
pack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4335 s.
pack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4336 s.
pack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4337 s.
pack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4346 int version = s.
version(
"FunctionInternal", 1, 9);
4362 std::string library;
4363 s.
unpack(
"FunctionInternal::jit_library", library);
4369 std::stringstream ss;
4370 s.
unpack(
"FunctionInternal::jit_binary", ss);
4373 s.
unpack(
"FunctionInternal::jit_binary", *binary_ptr);
4450 s.
unpack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4451 s.
unpack(
"FunctionInternal::sz_res_per", sz_res_per_);
4452 s.
unpack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4453 s.
unpack(
"FunctionInternal::sz_w_per", sz_w_per_);
4454 s.
unpack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4455 s.
unpack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4456 s.
unpack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4457 s.
unpack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4473 std::string base_function;
4474 s.
unpack(
"FunctionInternal::base_function", base_function);
4477 "FunctionInternal::deserialize: not found '" + base_function +
"'");
4480 ret.
own(it->second(s));
static ProtoFunction * deserialize(DeserializingStream &s)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static int eval_sx(const Function &f, const SXElem **arg, SXElem **res)
static std::vector< MX > create(const Function &fcn, const std::vector< MX > &arg)
Create function call node.
static ProtoFunction * deserialize(DeserializingStream &s)
Helper class for C code generation.
void scope_add_cleanup(const std::string &code)
Add cleanup code to be executed upon scope exit.
const std::set< std::string > & local_mutexes(const Function &f) const
Get all mutex names associated with a function.
void add_io_sparsities(const std::string &name, const std::vector< Sparsity > &sp_in, const std::vector< Sparsity > &sp_out)
Add io sparsity patterns of a function.
void scope_enter()
Enter a local scope.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void add(const Function &f, bool with_jac_sparsity=false)
Add a function (name generated)
void flush(std::ostream &s)
Flush the buffer to a stream of choice.
std::string to_mex(const Sparsity &sp, const std::string &arg)
Create matrix in MATLAB's MEX format.
std::string printf(const std::string &str, const std::vector< std::string > &arg=std::vector< std::string >())
Printf.
bool thread_safe() const
Emit thead safe code chekout/release?
static std::string array(const std::string &type, const std::string &name, casadi_int len, const std::string &def=std::string())
void generate_dump(const Function &f, const std::string &arr, bool is_input)
Generate dump_in or dump_out code for a function call.
std::string generate(const std::string &prefix="")
Generate file(s)
void generate_print(const Function &f, const std::string &arr, bool is_input)
Generate print_in or print_out code for a function call.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string from_mex(std::string &arg, const std::string &res, std::size_t res_off, const Sparsity &sp_res, const std::string &w)
Get matrix from MATLAB's MEX format.
std::string res(casadi_int i) const
Refer to resuly.
std::string declare(std::string s)
Declare a function.
void scope_exit()
Exit a local scope.
std::string local_mutex(const Function &f, const std::string &name) const
Access a static mutex associated with a function.
std::vector< FunctionMeta > added_functions_
std::string shorthand(const std::string &name) const
Get a shorthand.
void scope_return(const std::string &value)
Return from a scope with a value.
std::stringstream auxiliaries
void define_local_mutex(const Function &f, const std::string &name)
Declare a static mutex associated with a function.
void deserialize(DeserializingStream &s, SDPToSOCPMem &m)
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static std::string absolute(const std::string &path)
static bool is_absolute(const std::string &path)
static std::string ensure_trailing_slash(const std::string &path)
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
static std::unique_ptr< std::istream > ifstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::in, bool fail=true)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
static ProtoFunction * deserialize(DeserializingStream &s)
Internal class for Function.
bool has_refcount_
Reference counting in codegen?
casadi_int size1_in(casadi_int ind) const
Input/output dimensions.
virtual std::string codegen_mem_type() const
Thread-local memory object type.
std::string jit_serialize_
Serialize behaviour.
void finish_trace(std::ostream &trace, double **res, int ret) const
std::string diff_prefix(const std::string &prefix) const
Determine prefix for differentiated functions.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
Dict get_stats(void *mem) const override
Get all statistics.
void init(const Dict &opts) override
Initialize.
virtual void call_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Forward mode AD, virtual functions overloaded in derived classes.
void finalize() override
Finalize the object creation.
std::vector< M > project_arg(const std::vector< M > &arg, casadi_int npar) const
Project sparsities.
Function forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
virtual bool has_sprev() const
Is the class able to propagate seeds through the algorithm?
virtual size_t codegen_sz_res(const CodeGenerator &g) const
Get required lengths, for codegen.
const std::vector< DM > dm_in() const
Get function input(s) and output(s)
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
void tocache_if_missing(Function &f, const std::string &suffix="") const
Save function to cache, only if missing.
Function map(casadi_int n, const std::string ¶llelization) const
Generate/retrieve cached serial map.
double jac_penalty_
Penalty factor for using a complete Jacobian to calculate directional derivatives.
void call_gen(const MXVector &arg, MXVector &res, casadi_int npar, bool always_inline, bool never_inline) const
Call a function, overloaded.
virtual casadi_int n_nodes() const
Number of nodes in the algorithm.
std::vector< Sparsity > sparsity_in_
Input and output sparsity.
std::vector< Sparsity > jac_sparsity_[2]
Cache for sparsities of the Jacobian blocks.
virtual double ad_weight() const
Weighting factor for chosing forward/reverse mode.
virtual const std::vector< SX > sx_in() const
Get function input(s) and output(s)
static Function deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
virtual void codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
virtual void export_code(const std::string &lang, std::ostream &stream, const Dict &options) const
Export function in a specific language.
virtual bool has_forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
void print_in(std::ostream &stream, const double **arg, bool truncate) const
Print inputs.
void generate_in(const std::string &fname, const double **arg) const
Export an input file that can be passed to generate C code with a main.
static std::string forward_name(const std::string &fcn, casadi_int nfwd)
Helper function: Get name of forward derivative function.
virtual void jit_dependencies(const std::string &fname)
Jit dependencies.
virtual size_t codegen_sz_arg(const CodeGenerator &g) const
Get required lengths, for codegen.
void check_arg(const std::vector< M > &arg, casadi_int &npar) const
Check if input arguments have correct length and dimensions.
std::vector< std::vector< M > > replace_fseed(const std::vector< std::vector< M >> &fseed, casadi_int npar) const
Replace 0-by-0 forward seeds.
std::vector< bool > is_diff_out_
virtual bool adjViaJac(casadi_int nadj) const
Calculate derivatives by multiplying the full Jacobian and multiplying.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
virtual MX instruction_MX(casadi_int k) const
get MX expression associated with instruction
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
std::string jit_name_
Name if jit source file.
std::string compiler_plugin_
Just-in-time compiler.
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
virtual size_t codegen_sz_iw(const CodeGenerator &g) const
Get required lengths, for codegen.
casadi_release_t release_
Release redirected to a C function.
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Input/output dimensions.
virtual bool has_eval_dm() const
Evaluate with DM matrices.
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const
Evaluate numerically.
casadi_int numel_out() const
Number of input/output elements.
Function custom_jacobian_
std::string definition() const
Get function signature: name:(inputs)->(outputs)
const Sparsity & sparsity_in(casadi_int ind) const
Input/output sparsity.
static std::string get_jit_directory(const Dict &jit_options)
Get JIT directory from options.
Sparsity to_compact(casadi_int oind, casadi_int iind, const Sparsity &sp) const
Convert to compact Jacobian sparsity pattern.
Sparsity get_jac_sparsity_hierarchical_symm(casadi_int oind, casadi_int iind) const
void * user_data_
User-set field.
std::vector< M > replace_arg(const std::vector< M > &arg, casadi_int npar) const
Replace 0-by-0 inputs.
virtual const std::vector< MX > mx_in() const
Get function input(s) and output(s)
virtual void call_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Reverse mode, virtual functions overloaded in derived classes.
virtual bool has_jac_sparsity(casadi_int oind, casadi_int iind) const
Get Jacobian sparsity.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
void print_dimensions(std::ostream &stream) const
Print dimensions of inputs and outputs.
virtual void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const
Set the (persistent) work vectors.
std::string jit_base_name_
std::string signature_unrolled(const std::string &fname) const
Code generate the function.
virtual size_t codegen_sz_w(const CodeGenerator &g) const
Get required lengths, for codegen.
virtual bool is_a(const std::string &type, bool recursive) const
Check if the function is of a particular type.
Dict codegen_options_
Options of the code generator of jit.
const std::vector< DM > dm_out() const
Get function input(s) and output(s)
Sparsity & jac_sparsity(casadi_int oind, casadi_int iind, bool compact, bool symmetric) const
Get Jacobian sparsity.
static std::map< std::string, ProtoFunction *(*)(DeserializingStream &)> deserialize_map
double ad_weight_
Weighting factor for derivative calculation and sparsity pattern calculation.
casadi_int numel_in() const
Number of input/output elements.
virtual bool has_jacobian() const
Return Jacobian of all input elements with respect to all output elements.
Sparsity from_compact(casadi_int oind, casadi_int iind, const Sparsity &sp) const
Convert from compact Jacobian sparsity pattern.
~FunctionInternal() override=0
Destructor.
std::vector< Function > registered_functions_
void set_jac_sparsity(casadi_int oind, casadi_int iind, const Sparsity &sp)
Populate jac_sparsity_ and jac_sparsity_compact_ during initialization.
bool inputs_check_
Errors are thrown if numerical values of inputs look bad.
virtual std::vector< SX > free_sx() const
Get free variables (SX)
static void print_canonical(std::ostream &stream, const Sparsity &sp, const double *nz)
Print canonical representation of a numeric matrix.
bool jit_
Use just-in-time compiler.
void add_embedded(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, const Function &dep, casadi_int max_depth) const
eval_t eval_
Numerical evaluation redirected to a C function.
bool has_refcount_in_deps_
Reference counting in dependent functions.
bool has_derivative() const
Can derivatives be calculated in any way?
virtual std::vector< std::string > get_free() const
Print free variables.
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
virtual std::vector< MX > free_mx() const
Get free variables (MX)
void * alloc_mem() const override
Create memory block.
virtual bool uses_output() const
Do the derivative functions need nondifferentiated outputs?
virtual void find(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, casadi_int max_depth) const
virtual double sp_weight() const
Weighting factor for chosing forward/reverse mode,.
std::string codegen_mem(CodeGenerator &g, const std::string &index="mem") const
Get thread-local memory object.
virtual SX instructions_sx() const
get SX expression associated with instructions
Sparsity get_jac_sparsity_hierarchical(casadi_int oind, casadi_int iind) const
A flavor of get_jac_sparsity_gen that does hierarchical block structure recognition.
virtual void generate_lifted(Function &vdef_fcn, Function &vinit_fcn) const
Extract the functions needed for the Lifted Newton method.
bool incache(const std::string &fname, Function &f, const std::string &suffix="") const
Get function in cache.
virtual Function simplify_passes(const std::vector< std::pair< std::string, casadi_int > > &tasks) const
Apply an ordered list of simplify passes (used by transform)
virtual std::string codegen_name(const CodeGenerator &g, bool ns=true) const
Get name in codegen.
size_t n_in_
Number of inputs and outputs.
void codegen(CodeGenerator &g, const std::string &fname) const
Generate code the function.
virtual casadi_int instruction_id(casadi_int k) const
Get an atomic operation operator index.
size_t sz_res() const
Get required length of res field.
virtual void eval_mx(const MXVector &arg, MXVector &res, bool always_inline, bool never_inline) const
Evaluate with symbolic matrices.
virtual void codegen_release(CodeGenerator &g) const
Codegen for release.
virtual std::vector< casadi_int > instruction_input(casadi_int k) const
Get the (integer) input arguments of an atomic operation.
virtual size_t get_n_out()
Are all inputs and outputs scalar.
virtual void codegen_body(CodeGenerator &g) const
Generate code for the function body.
virtual int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w, void *mem, bool always_inline, bool never_inline) const
Evaluate with symbolic scalars.
casadi_int size2_out(casadi_int ind) const
Input/output dimensions.
virtual void codegen_alloc_mem(CodeGenerator &g) const
Codegen decref for alloc_mem.
virtual void set_temp(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (temporary) work vectors.
bool matching_arg(const std::vector< M > &arg, casadi_int &npar) const
Check if input arguments that needs to be replaced.
std::vector< M > project_res(const std::vector< M > &arg, casadi_int npar) const
Project sparsities.
casadi_int size1_out(casadi_int ind) const
Input/output dimensions.
virtual void codegen_checkout(CodeGenerator &g) const
Codegen for checkout.
void get_partition(casadi_int iind, casadi_int oind, Sparsity &D1, Sparsity &D2, bool compact, bool symmetric, bool allow_forward, bool allow_reverse) const
Get the unidirectional or bidirectional partition.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Input/output dimensions.
WeakCache< std::string, Function > cache_
Function cache.
virtual int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate sparsity forward.
casadi_checkout_t checkout_
Checkout redirected to a C function.
virtual int eval_activity(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate signal activity forward.
std::vector< double > nz_in(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
casadi_int nnz_in() const
Number of input/output nonzeros.
virtual void disp_more(std::ostream &stream) const
Print more.
static const Options options_
Options.
virtual std::vector< DM > eval_dm(const std::vector< DM > &arg) const
Evaluate with DM matrices.
FunctionInternal(const std::string &name)
Constructor.
Function wrap_as_needed(const std::string &name, const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
std::vector< MX > mapsum_mx(const std::vector< MX > &arg, const std::string ¶llelization)
Parallel evaluation.
virtual Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const
Return function that calculates adjoint derivatives.
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.
std::vector< Sparsity > sparsity_out_
Function reverse(casadi_int nadj) const
Return function that calculates adjoint derivatives.
std::vector< M > replace_res(const std::vector< M > &res, casadi_int npar) const
Replace 0-by-0 outputs.
virtual const Function & oracle() const
Get oracle.
virtual bool get_diff_in(casadi_int i)
Which inputs are differentiable.
bool jit_temp_suffix_
Use a temporary name.
virtual std::vector< std::string > get_function() const
signal_t incref_
Incref/decref redirected to C functions.
void serialize_type(SerializingStream &s) const override
Serialize type information.
virtual std::string get_name_out(casadi_int i)
Names of function input and outputs.
casadi_int max_num_dir_
Maximum number of sensitivity directions.
virtual double instruction_constant(casadi_int k) const
Get the floating point output argument of an atomic operation.
virtual bool fwdViaJac(casadi_int nfwd) const
Calculate derivatives by multiplying the full Jacobian and multiplying.
virtual Sparsity get_sparsity_out(casadi_int i)
Get sparsity of a given output.
const Sparsity & sparsity_out(casadi_int ind) const
Input/output sparsity.
bool matching_res(const std::vector< M > &arg, casadi_int &npar) const
Check if output arguments that needs to be replaced.
void disp(std::ostream &stream, bool more) const override
Display object.
size_t sz_w() const
Get required length of w field.
virtual int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate sparsity backwards.
virtual Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const
Get Jacobian sparsity.
virtual void merge(const std::vector< MX > &arg, std::vector< MX > &subs_from, std::vector< MX > &subs_to) const
List merge opportunitities.
bool jit_cleanup_
Cleanup jit source file.
virtual bool codegen_needs_mem() const
Is thread-local memory object needed?
virtual bool has_function(const std::string &fname) const
Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind) const
Get the sparsity pattern via sparsity seed propagation.
std::string jit_directory_
std::unique_ptr< std::ostream > open_trace(const double **arg, casadi_int dump_id) const
virtual Dict info() const
void print_out(std::ostream &stream, double **res, bool truncate) const
Print outputs.
virtual void codegen_declarations(CodeGenerator &g) const
Generate code for the declarations of the C function.
int eval_gen(const double **arg, double **res, casadi_int *iw, double *w, void *mem, bool always_inline, bool never_inline) const
Evaluate numerically.
virtual bool jac_is_symm(casadi_int oind, casadi_int iind) const
Is a Jacobian block known to be symmetric a priori?
virtual const std::vector< MX > mx_out() const
Get function input(s) and output(s)
virtual std::vector< casadi_int > instruction_output(casadi_int k) const
Get the (integer) output argument of an atomic operation.
virtual int sp_forward_block(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem, casadi_int oind, casadi_int iind) const
Propagate sparsity forward, specific block.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
std::string signature(const std::string &fname) const
Code generate the function.
void reset_dump_count()
Reset the counter used to name dump files.
virtual const std::vector< SX > sx_out() const
Get function input(s) and output(s)
bool all_scalar() const
Are all inputs and outputs scalar.
virtual Function get_jacobian(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const
Return Jacobian of all input elements with respect to all output elements.
std::vector< double > nz_out(const std::vector< DM > &res) const
Convert from/to flat vector of input/output nonzeros.
casadi_int nnz_out() const
Number of input/output nonzeros.
void tocache(const Function &f, const std::string &suffix="") const
Save function to cache.
size_t sz_arg() const
Get required length of arg field.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
void generate_out(const std::string &fname, double **res) const
virtual bool has_codegen() const
Is codegen supported?
static bool check_mat(const Sparsity &arg, const Sparsity &inp, casadi_int &npar)
void codegen_meta(CodeGenerator &g) const
Generate meta-information allowing a user to evaluate a generated function.
Function jacobian() const
Return Jacobian of all input elements with respect to all output elements.
virtual void codegen_init_mem(CodeGenerator &g) const
Codegen decref for init_mem.
virtual bool has_free() const
Does the function have free variables.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
static void trace_values(std::ostream &trace, const double *values, casadi_int nnz)
virtual bool has_reverse(casadi_int nadj) const
Return function that calculates adjoint derivatives.
virtual std::string generate_dependencies(const std::string &fname, const Dict &opts) const
Export / Generate C code for the dependency function.
virtual std::vector< MX > symbolic_output(const std::vector< MX > &arg) const
Get a vector of symbolic variables corresponding to the outputs.
std::vector< bool > is_diff_in_
Are inputs and outputs differentiable?
size_t sz_iw() const
Get required length of iw field.
void change_option(const std::string &option_name, const GenericType &option_value) override
Change option after object creation for debugging.
static std::string string_from_UnifiedReturnStatus(UnifiedReturnStatus status)
virtual casadi_int n_instructions() const
Get the number of atomic operations.
Dict cache_init_
Values to prepopulate the function cache with.
void free_mem(void *mem) const override
Free memory block.
std::vector< std::string > name_out_
virtual bool get_diff_out(casadi_int i)
Which outputs are differentiable.
Function derivative_of_
If the function is the derivative of another function.
Dict generate_options(const std::string &target) const override
Reconstruct options dict.
virtual bool has_spfwd() const
Is the class able to propagate seeds through the algorithm?
static std::string reverse_name(const std::string &fcn, casadi_int nadj)
Helper function: Get name of adjoint derivative function.
std::vector< std::vector< M > > replace_aseed(const std::vector< std::vector< M >> &aseed, casadi_int npar) const
Replace 0-by-0 reverse seeds.
Dict cache() const
Get all functions in the cache.
virtual std::string get_name_in(casadi_int i)
Names of function input and outputs.
casadi_int size2_in(casadi_int ind) const
Input/output dimensions.
virtual size_t get_n_in()
Number of function inputs and outputs.
virtual Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const
Return function that calculates forward derivatives.
void codegen_sparsities(CodeGenerator &g) const
Codegen sparsities.
virtual double get_default_in(casadi_int ind) const
Get default input value.
std::vector< std::string > name_in_
Input and output scheme.
virtual void codegen_incref(CodeGenerator &g) const
Codegen incref for dependencies.
virtual std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order, bool tr=false) const
Which variables enter with some order.
virtual Sparsity get_sparsity_in(casadi_int i)
Get sparsity of a given input.
Function forward(casadi_int nfwd) const
Get a function computing nfwd forward directional derivatives.
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.
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
Find which entries of an input the outputs depend on, linearly or not.
void assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const
Raise an error unless input i is nrow-by-ncol.
const Sparsity & sparsity_out(casadi_int ind) const
Get the sparsity pattern of an output, by index or name.
FunctionInternal * get() const
const std::vector< std::string > & name_in() const
Get the names of all inputs, in order.
const std::string & name() const
Get the name given at construction ("null" for a null object)
Function wrap() const
Wrap in an MXFunction whose graph is a single call to this function.
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in this function, recursively.
Function reverse(casadi_int nadj) const
Get a function computing nadj reverse (adjoint) directional derivatives.
Function jacobian() const
Get a function computing all Jacobian blocks at once.
static Function create(FunctionInternal *node)
Create from node.
static bool check_name(const std::string &name)
Check whether a string is a valid function name.
bool is_diff_out(casadi_int ind) const
Check which inputs or outputs are marked differentiable.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Get the shape of an output: rows, columns or both.
const Sparsity & sparsity_in(casadi_int ind) const
Get the sparsity pattern of an input, by index or name.
void assert_sparsity_out(casadi_int i, const Sparsity &sp, casadi_int n=1, bool allow_all_zero_sparse=true) const
Raise an error unless output i has the sparsity sp repeated n.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
bool is_diff_in(casadi_int ind) const
Check which inputs or outputs are marked differentiable.
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
Create a function with a subset or reordering of the inputs and outputs.
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate with a list or a dict of arguments; the result has the same form.
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get the sparsity patterns of all Jacobian blocks.
std::map< std::string, std::vector< std::string > > AuxOut
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
Build a function computing derivatives by naming inputs and outputs.
const std::vector< std::string > & name_out() const
Get the names of all outputs, in order.
static Matrix< Scalar > sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
static MatType zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
bool is_null() const
Is a null pointer?
Generic data type, can hold different types such as bool, casadi_int, std::string etc.
std::string to_string() const
Convert to a type.
static std::string getTempWorkDir()
static casadi_int getMaxNumDir()
static bool hierarchical_sparsity
std::string library() const
Get library name.
signal_t get_function(const std::string &symname)
Get a function pointer for numerical evaluation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static Function create(const std::string ¶llelization, const Function &f, casadi_int n)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static void print_default(std::ostream &stream, const Sparsity &sp, const double *nonzeros, bool truncate=true)
Print default style.
const Sparsity & sparsity() const
Const access the sparsity - reference to data member.
void to_file(const std::string &filename, const std::string &format="") const
Write a numerical matrix to a text file (DM only)
static Matrix< casadi_int > triplet(const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, const Matrix< casadi_int > &d)
Construct a sparse matrix from triplet form (row indices, column indices, values)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into a plugin instance (dispatches on the plugin name)
Base class for FunctionInternal and LinsolInternal.
void print_option(const std::string &name, std::ostream &stream) const
Print all information there is to know about a certain option.
bool error_on_fail_
Throw an exception on failure?
void construct(const Dict &opts)
Construct.
virtual int init_mem(void *mem) const
Initalize memory block.
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
virtual void * alloc_mem() const
Create memory block.
virtual const Options & get_options() const
Options.
bool regularity_check_
Errors are thrown when NaN is produced.
virtual Dict generate_options(const std::string &target) const
Reconstruct options dict.
void serialize(SerializingStream &s) const
Serialize an object.
ProtoFunction(const std::string &name)
Constructor.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
virtual void free_mem(void *mem) const
Free memory block.
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
void print_time(const std::map< std::string, FStats > &fstats) const
Print timing statistics.
int checkout() const
Checkout a memory object.
virtual void init(const Dict &opts)
Initialize.
void format_time(char *buffer, double time) const
Format time in a fixed width 8 format.
virtual Dict get_stats(void *mem) const
Get all statistics.
void * memory(int ind) const
Memory objects.
void print_options(std::ostream &stream) const
Print list of options.
bool has_memory(int ind) const
Check for existance of memory object.
bool verbose_
Verbose printout.
virtual void finalize()
Finalize the object creation.
virtual std::string serialize_base_function() const
String used to identify the immediate FunctionInternal subclass.
virtual void check_mem_count(casadi_int n) const
Check for validatity of memory object count.
void sprint(char *buf, size_t buf_sz, const char *fmt,...) const
C-style formatted printing to string.
void release(int mem) const
Release a memory object.
bool has_option(const std::string &option_name) const
Does a particular option exist.
static const Options options_
Options.
void clear_mem()
Clear all memory (called from destructor)
~ProtoFunction() override=0
Destructor.
virtual void change_option(const std::string &option_name, const GenericType &option_value)
Change option after object creation for debugging.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
The basic scalar symbolic class of CasADi.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
virtual std::string class_name() const =0
Readable name of the internal class.
static ProtoFunction * deserialize(DeserializingStream &s)
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Nonzero index of entry (rr, cc), or -1 if it is a structural zero.
bool is_vector() const
Check whether the pattern is a row or a column vector.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Pattern of the submatrix with rows rr and columns cc.
casadi_int numel() const
Total number of entries, structural zeros included, i.e. size1()*size2()
casadi_int size1() const
Number of rows.
Sparsity star_coloring(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Star coloring of a symmetric pattern (greedy distance-2 coloring)
std::string dim(bool with_nz=false) const
Dimensions as a string "nrow x ncol", optionally with the number of nonzeros.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
Sparsity T() const
Transposed pattern.
bool is_scalar(bool scalar_and_dense=false) const
Check whether the pattern is 1-by-1.
void enlargeColumns(casadi_int ncol, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the pattern in place by inserting empty columns.
void enlargeRows(casadi_int nrow, const std::vector< casadi_int > &rr, bool ind1=false)
Enlarge the pattern in place by inserting empty rows.
casadi_int nnz() const
Number of structural nonzeros.
casadi_int size2() const
Number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
std::pair< casadi_int, casadi_int > size() const
Shape as a pair (number of rows, number of columns)
static Sparsity scalar(bool dense_scalar=true)
Create a 1-by-1 sparsity pattern.
bool is_empty(bool both=false) const
Check whether the pattern has a zero dimension.
double density() const
Percentage of nonzeros: 100*nnz()/numel()
Sparsity uni_coloring(const Sparsity &AT=Sparsity(), casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Unidirectional (column) coloring for compressed Jacobian evaluation.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
bool is_dense() const
Check whether every entry is a structural nonzero, i.e. nnz() == numel()
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern from the (row, col) index of every nonzero.
bool is_symmetric() const
Check whether the pattern equals its transpose.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
T get_from_dict(const std::map< std::string, T > &d, const std::string &key, const T &default_value)
std::string join(const std::vector< std::string > &l, const std::string &delim)
unsigned long long bvec_t
int(* casadi_checkout_t)(void)
Function pointer types for the C API.
Dict combine(const Dict &first, const Dict &second, bool recurse)
Combine two dicts. First has priority.
M replace_mat(const M &arg, const Sparsity &inp, casadi_int npar)
void bvec_clear(bvec_t *s, casadi_int begin, casadi_int end)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
int(* eval_t)(const double **arg, double **res, casadi_int *iw, double *w, int)
Function pointer types for the C API.
std::vector< MX > MXVector
void assert_read(std::istream &stream, const std::string &s)
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.
void(* casadi_release_t)(int)
Function pointer types for the C API.
void normalized_setup(std::istream &stream)
void(* signal_t)(void)
Function pointer types for the C API.
bool all(const std::vector< bool > &v)
Check if all arguments are true.
std::vector< T > diff(const std::vector< T > &values)
diff
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
bool remove(const std::string &path)
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
bvec_t bvec_or(const bvec_t *arg, casadi_int n)
Bit-wise or operation on bvec_t array.
std::string filename(const std::string &path)
std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory)
void normalized_out(std::ostream &stream, double val)
void bvec_toggle(bvec_t *s, casadi_int begin, casadi_int end, casadi_int j)
Function memory with temporary work vectors.
Options metadata for a class.
static bool is_sane(const Dict &opts)
Is the dictionary sane.
void print_all(std::ostream &stream) const
Print list of options.
static Dict sanitize(const Dict &opts, bool top_level=true)
Sanitize a options dictionary.
const Options::Entry * find(const std::string &name) const
void check(const Dict &opts) const
Check if options exist.
void print_one(const std::string &name, std::ostream &stream) const
Print all information there is to know about a certain option.
Function memory with temporary work vectors.
void add_stat(const std::string &s)