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 "The function is a derivative of another function. "
262 "The type of derivative (directional derivative, Jacobian) "
263 "is inferred from the function name."}},
266 "Specify the maximum number of directions for derivative functions."
267 " Overrules the builtin optimized_num_dir."}},
270 "Enable derivative calculation using generated functions for"
271 " Jacobian-times-vector products - typically using forward mode AD"
272 " - if available. [default: true]"}},
275 "Enable derivative calculation using generated functions for"
276 " transposed Jacobian-times-vector products - typically using reverse mode AD"
277 " - if available. [default: true]"}},
280 "Enable derivative calculation using generated functions for"
281 " Jacobians of all differentiable outputs with respect to all differentiable inputs"
282 " - if available. [default: true]"}},
285 "Enable derivative calculation by finite differencing. [default: false]]"}},
288 "Options to be passed to the finite difference instance"}},
291 "Method for finite differencing [default 'central']"}},
294 "Print numerical values of inputs [default: false]"}},
297 "Print numerical values of outputs [default: false]"}},
300 "When printing numerical matrices, use a format that is "
301 "exact and reproducible in generated C code."}},
304 "Acceptable number of inputs and outputs. Warn if exceeded."}},
307 "Dump numerical values of inputs to file (readable with DM.from_file) [default: false] "
308 "A counter is used to generate unique names. "
309 "The counter may be reset using reset_dump_count."}},
312 "Dump numerical values of outputs to file (readable with DM.from_file) [default: false] "
313 "A counter is used to generate unique names. "
314 "The counter may be reset using reset_dump_count."}},
317 "Dump function to file upon first evaluation. [false]"}},
320 "Directory to dump inputs/outputs and traces to. Make sure the directory exists [.]"}},
323 "Choose file format to dump matrices. See DM.from_file [mtx]"}},
326 "Options to be passed to a forward mode constructor"}},
329 "Options to be passed to a reverse mode constructor"}},
332 "Options to be passed to a Jacobian constructor"}},
335 "Default options to be used to populate forward_options, reverse_options, and "
336 "jacobian_options before those options are merged in."}},
339 "Override CasADi's AD. Use together with 'jac_penalty': 0. "
340 "Note: Highly experimental. Syntax may break often."}},
343 "Indicate for each input if it should be differentiable."}},
346 "Indicate for each output if it should be differentiable."}},
349 "After construction, expand this Function. Default: False"}},
350 {
"post_expand_options",
352 "Options to be passed to post-construction expansion. Default: empty"}},
355 "Prepopulate the function cache. Default: empty"}},
356 {
"external_transform",
358 "List of external_transform instruction arguments. Default: empty"}}
364 for (
auto&& op : opts) {
365 if (op.first==
"verbose") {
367 }
else if (op.first==
"print_time") {
369 }
else if (op.first==
"record_time") {
371 }
else if (op.first==
"regularity_check") {
373 }
else if (op.first==
"error_on_fail") {
394 if (target!=
"tmp") opts[
"jit"] =
jit_;
406 if (target==
"clone" || target==
"tmp") {
427 opts[
"dump"] =
dump_;
428 if (target==
"clone") {
432 if (target==
"forward") {
436 if (target==
"reverse") {
445 if (option_name ==
"print_in") {
447 }
else if (option_name ==
"print_out") {
449 }
else if (option_name ==
"print_canonical") {
451 }
else if (option_name==
"ad_weight") {
453 }
else if (option_name==
"ad_weight_sp") {
455 }
else if (option_name==
"dump") {
456 dump_ = option_value;
457 }
else if (option_name==
"dump_in") {
459 }
else if (option_name==
"dump_out") {
461 }
else if (option_name==
"dump_dir") {
463 }
else if (option_name==
"dump_format") {
483 for (
auto&& op : opts) {
484 if (op.first==
"jac_penalty") {
486 }
else if (op.first==
"user_data") {
488 }
else if (op.first==
"inputs_check") {
490 }
else if (op.first==
"gather_stats") {
491 casadi_warning(
"Deprecated option \"gather_stats\": Always enabled");
492 }
else if (op.first==
"jit") {
494 }
else if (op.first==
"jit_cleanup") {
496 }
else if (op.first==
"jit_serialize") {
499 "jit_serialize option not understood. Pick one of source, link, embed.");
500 }
else if (op.first==
"compiler") {
502 }
else if (op.first==
"jit_options") {
504 }
else if (op.first==
"jit_name") {
506 }
else if (op.first==
"jit_temp_suffix") {
508 }
else if (op.first==
"derivative_of") {
510 }
else if (op.first==
"ad_weight") {
512 }
else if (op.first==
"ad_weight_sp") {
514 }
else if (op.first==
"max_num_dir") {
516 }
else if (op.first==
"enable_forward") {
518 }
else if (op.first==
"enable_reverse") {
520 }
else if (op.first==
"enable_jacobian") {
522 }
else if (op.first==
"enable_fd") {
524 }
else if (op.first==
"fd_options") {
526 }
else if (op.first==
"fd_method") {
528 }
else if (op.first==
"print_in") {
530 }
else if (op.first==
"print_out") {
532 }
else if (op.first==
"print_canonical") {
534 }
else if (op.first==
"max_io") {
536 }
else if (op.first==
"dump_in") {
538 }
else if (op.first==
"dump_out") {
540 }
else if (op.first==
"dump") {
542 }
else if (op.first==
"dump_dir") {
544 }
else if (op.first==
"dump_format") {
546 }
else if (op.first==
"forward_options") {
548 }
else if (op.first==
"reverse_options") {
550 }
else if (op.first==
"jacobian_options") {
552 }
else if (op.first==
"der_options") {
554 }
else if (op.first==
"custom_jacobian") {
557 "Inconsistent naming of custom Jacobian, expected: jac_" +
name_);
559 }
else if (op.first==
"always_inline") {
561 }
else if (op.first==
"never_inline") {
563 }
else if (op.first==
"is_diff_in") {
565 }
else if (op.first==
"is_diff_out") {
567 }
else if (op.first==
"cache") {
581 casadi_warning(
"Function " +
name_ +
" has many inputs (" +
str(
n_in_) +
" > "
583 +
"Changing the problem formulation is strongly encouraged.");
589 casadi_warning(
"Function " +
name_ +
" has many outputs (" +
str(
n_out_) +
" > "
591 +
"Changing the problem formulation is strongly encouraged.");
600 +
" inputs, but is_diff_in has length " +
str(
is_diff_in_.size()) +
".");
609 +
" outputs, but is_diff_out has length " +
str(
is_diff_out_.size()) +
".");
618 +
" inputs, but sparsity_in has length " +
str(
sparsity_in_.size()) +
".");
627 +
" outputs, but sparsity_out has length " +
str(
sparsity_out_.size()) +
".");
636 +
" inputs, but name_in has length " +
str(
name_in_.size()) +
".");
645 +
" outputs, but name_out has length " +
str(
name_out_.size()) +
".");
651 if (c.first != f.
name()) {
652 casadi_warning(
"Cannot add '" + c.first +
"' a.k.a. '" + f.
name()
653 +
"' to cache. Mismatching names not implemented.");
660 sz_arg_per_ +=
n_in_;
676 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
697 if (
name_ ==
"jac_" + n) {
701 }
else if (
name_ ==
"adj1_" + n) {
715 std::string directory;
716 directory =
get_from_dict(jit_options,
"directory", std::string(
""));
721 jit_directory = directory;
723 jit_directory = jit_directory + directory;
739 for (
const Function& f : shared_from_this<Function>().find_functions(0)) {
740 if (f->has_refcount_in_deps_) {
756 if (
verbose_) casadi_message(
"Codegenerating function '" +
name_ +
"'.");
760 opts[
"prefix"] =
"jit";
763 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"'..");
765 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"' done.");
773 casadi_assert(
eval_!=
nullptr,
"Cannot load JIT'ed function.");
791 casadi_assert_dev(mem==0);
797 std::ostream& of = *of_ptr;
801 for (casadi_int i=0; i<
n_in_; ++i) {
802 const double* v = arg[i];
803 for (casadi_int k=0;k<
nnz_in(i);++k) {
813 std::ostream& of = *of_ptr;
817 for (casadi_int i=0; i<
n_out_; ++i) {
818 const double* v = res[i];
819 for (casadi_int k=0;k<
nnz_out(i);++k) {
820 normalized_out(of, v ? v[k] : std::numeric_limits<double>::quiet_NaN());
827 trace_values(std::ostream& trace,
const double* values, casadi_int nnz) {
833 for (casadi_int i = 0; i < nnz; ++i) {
835 double v = values[i];
838 }
else if (isinf(v)) {
839 trace << (v < 0 ?
"\"-inf\"" :
"\"inf\"");
848 open_trace(
const double** arg, casadi_int dump_id)
const {
849 if (dump_id < 0) dump_id = get_dump_id();
852 << std::setw(6) << dump_id <<
".trace.jsonl";
854 std::ostream& trace = *output;
856 trace <<
"{\"event\":\"header\",\"format\":\"casadi_trace\",\"version\":1,"
858 <<
"\",\"dump_id\":" << dump_id <<
"}\n";
859 trace <<
"{\"event\":\"inputs\",\"values\":[";
860 for (casadi_int i = 0; i <
n_in_; ++i) {
869 finish_trace(std::ostream& trace,
double** res,
int ret)
const {
871 trace <<
"{\"event\":\"outputs\",\"values\":[";
872 for (casadi_int i = 0; i <
n_out_; ++i) {
878 trace <<
"{\"event\":\"end\",\"status\":" << ret <<
"}\n";
880 casadi_assert(trace.good(),
"Failed to write dump_trace for '" +
name_ +
"'");
883 void FunctionInternal::dump_in(casadi_int
id,
const double** arg)
const {
884 std::stringstream ss;
885 ss << std::setfill(
'0') << std::setw(6) << id;
886 std::string count = ss.str();
887 for (casadi_int i=0;i<
n_in_;++i) {
893 casadi_message(
"dump_in for " +
name_ +
" -> " + name);
898 void FunctionInternal::dump_out(casadi_int
id,
double** res)
const {
899 std::stringstream ss;
900 ss << std::setfill(
'0') << std::setw(6) << id;
901 std::string count = ss.str();
902 for (casadi_int i=0;i<
n_out_;++i) {
908 casadi_message(
"dump_out for " +
name_ +
" -> " + name);
913 void FunctionInternal::dump()
const {
917 casadi_int FunctionInternal::get_dump_id()
const {
925 m->t_total = &m->fstats.at(
"total");
927 m->t_total =
nullptr;
933 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
934 for (casadi_int i=0; i<
n_in_; ++i) {
935 stream <<
"Input " << i <<
" (" <<
name_in_[i] <<
"): ";
944 stream <<
"NULL" << std::endl;
950 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
951 for (casadi_int i=0; i<
n_out_; ++i) {
952 stream <<
"Output " << i <<
" (" <<
name_out_[i] <<
"): ";
961 stream <<
"NULL" << std::endl;
971 for (casadi_int i=0; i<sz; ++i) {
972 if (i>0) stream <<
", ";
982 const Sparsity& sp,
const double* nz) {
987 stream << sp.
dim(
false) <<
": ";
990 for (casadi_int i=0; i<sp.
nnz(); ++i) {
991 if (i>0) stream <<
", ";
997 stream <<
", colind: [";
998 for (casadi_int i=0; i<sp.
size2()+1; ++i) {
999 if (i>0) stream <<
", ";
1000 stream << sp.
colind()[i];
1003 stream <<
", row: [";
1004 for (casadi_int i=0; i<sp.
nnz(); ++i) {
1005 if (i>0) stream <<
", ";
1006 stream << sp.
row()[i];
1023 eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
1024 bool always_inline,
bool never_inline)
const {
1026 if (
dump_in_) dump_in(dump_id, arg);
1027 if (
dump_ && dump_id==0) dump();
1032 for (casadi_int i=0;i<
n_in_;++i) {
1033 casadi_assert(arg[i]==
nullptr || arg[i]+
nnz_in(i)<=w || arg[i]>=w+
sz_w(),
1034 "Memory corruption detected for input " +
name_in_[i] +
".\n"+
1036 " intersects with w " +
str(w)+
"-"+
str(w+
sz_w())+
".");
1038 for (casadi_int i=0;i<
n_out_;++i) {
1039 casadi_assert(res[i]==
nullptr || res[i]+
nnz_out(i)<=w || res[i]>=w+
sz_w(),
1040 "Memory corruption detected for output " +
name_out_[i]);
1043 for (
auto&& s : m->fstats) s.second.reset();
1044 if (m->t_total) m->t_total->tic();
1045 m->dump_id = dump_id;
1052 #ifdef CASADI_WITH_THREAD
1053 std::lock_guard<std::mutex> lock(mtx_);
1057 ret =
eval_(arg, res, iw, w, mem_);
1059 #ifdef CASADI_WITH_THREAD
1060 std::lock_guard<std::mutex> lock(mtx_);
1065 ret =
eval(arg, res, iw, w, mem);
1067 if (m->t_total) m->t_total->toc();
1075 for (casadi_int i = 0; i <
n_out_; ++i) {
1077 if (!res[i])
continue;
1079 casadi_int nnz = this->
nnz_out(i);
1080 for (casadi_int nz = 0; nz < nnz; ++nz) {
1081 if (isnan(res[i][nz]) || isinf(res[i][nz])) {
1083 casadi_error(
str(res[i][nz]) +
" detected for output " +
name_out_[i] +
" at "
1093 stream <<
" Number of inputs: " <<
n_in_ << std::endl;
1094 for (casadi_int i=0; i<
n_in_; ++i) {
1095 stream <<
" Input " << i <<
" (\"" <<
name_in_[i] <<
"\"): "
1098 stream <<
" Number of outputs: " <<
n_out_ << std::endl;
1099 for (casadi_int i=0; i<
n_out_; ++i) {
1100 stream <<
" Output " << i <<
" (\"" <<
name_out_[i] <<
"\"): "
1119 if (option_name ==
"verbose") {
1121 }
else if (option_name ==
"regularity_check") {
1125 casadi_error(
"Option '" + option_name +
"' cannot be changed");
1131 return std::vector<std::string>();
1135 std::stringstream s;
1140 for (casadi_int i=0; i<
n_in_; ++i) {
1146 for (casadi_int i=0; i<
n_out_; ++i) {
1158 stream << std::endl;
1168 std::vector<std::string> keys;
1169 std::vector<Function> entries;
1170 cache_.cache(keys, entries);
1172 for (
size_t i=0; i<keys.size(); ++i) {
1174 std::string s = keys[i];
1175 casadi_assert_dev(s.size() > 0);
1177 std::replace(s.begin(), s.end(),
':',
'_');
1179 if (s.back() ==
'_') s.resize(s.size() - 1);
1181 ret[s] = entries[i];
1188 const std::string& suffix)
const {
1189 return cache_.incache(fname +
":" + suffix, f);
1197 cache_.tocache_if_missing(f.
name() +
":" + suffix, f);
1202 if (parallelization==
"serial") {
1204 std::string fname =
"map" +
str(n) +
"_" +
name_;
1208 casadi_assert_dev(f.
name()==fname);
1224 if (opts.empty() && name==
name_)
return shared_from_this<Function>();
1226 Dict my_opts = opts;
1228 if (my_opts.find(
"ad_weight")==my_opts.end())
1230 if (my_opts.find(
"ad_weight_sp")==my_opts.end())
1232 if (my_opts.find(
"max_num_dir")==my_opts.end())
1235 std::vector<MX> arg =
mx_in();
1236 std::vector<MX> res =
self()(arg);
1256 std::vector<MX> arg =
mx_in();
1257 std::vector<MX> res =
self()(arg);
1272 for (casadi_int i=begin; i<end; ++i) {
1273 s[i] ^= (
bvec_t(1) << j);
1278 for (casadi_int i=begin; i<end; ++i) {
1286 for (casadi_int i=begin; i<end; ++i) r |= s[i];
1291 template<
bool fwd>
struct JacSparsityTraits {};
1292 template<>
struct JacSparsityTraits<true> {
1293 typedef const bvec_t* arg_t;
1294 static inline void sp(
const FunctionInternal *f,
1296 casadi_int* iw,
bvec_t* w,
void* mem) {
1297 std::vector<const bvec_t*> argm(f->sz_arg(),
nullptr);
1298 std::vector<bvec_t> wm(f->nnz_in(),
bvec_t(0));
1301 for (casadi_int i=0;i<f->n_in_;++i) {
1302 if (f->is_diff_in_[i]) {
1305 argm[i] = arg[i] ? wp :
nullptr;
1309 f->sp_forward(
get_ptr(argm), res, iw, w, mem);
1310 for (casadi_int i=0;i<f->n_out_;++i) {
1311 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1315 template<>
struct JacSparsityTraits<false> {
1317 static inline void sp(
const FunctionInternal *f,
1319 casadi_int* iw,
bvec_t* w,
void* mem) {
1320 for (casadi_int i=0;i<f->n_out_;++i) {
1321 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1323 f->sp_reverse(arg, res, iw, w, mem);
1324 for (casadi_int i=0;i<f->n_in_;++i) {
1325 if (!f->is_diff_in_[i] && arg[i])
casadi_clear(arg[i], f->nnz_in(i));
1337 std::vector<typename JacSparsityTraits<fwd>::arg_t> arg(
sz_arg(),
nullptr);
1338 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1339 std::vector<casadi_int> iw(
sz_iw());
1340 std::vector<bvec_t> w(
sz_w(), 0);
1343 std::vector<bvec_t> seed(
nz_in, 0);
1345 std::vector<bvec_t> sens(
nz_out, 0);
1347 if (!fwd) std::swap(seed, sens);
1350 casadi_int nsweep = seed.size() /
bvec_size;
1355 casadi_message(
str(nsweep) + std::string(fwd ?
" forward" :
" reverse") +
" sweeps "
1356 "needed for " +
str(seed.size()) +
" directions");
1360 casadi_int progress = -10;
1363 std::vector<casadi_int> jcol, jrow;
1366 for (casadi_int s=0; s<nsweep; ++s) {
1370 casadi_int progress_new = (s*100)/nsweep;
1372 if (progress_new / 10 > progress / 10) {
1373 progress = progress_new;
1374 casadi_message(
str(progress) +
" %");
1382 casadi_int ndir_local = seed.size()-offset;
1383 ndir_local = std::min(
static_cast<casadi_int
>(
bvec_size), ndir_local);
1385 for (casadi_int i=0; i<ndir_local; ++i) {
1386 seed[offset+i] |=
bvec_t(1)<<i;
1394 for (casadi_int el=0; el<sens.size(); ++el) {
1397 bvec_t spsens = sens[el];
1408 for (casadi_int i=0; i<ndir_local; ++i) {
1411 if ((
bvec_t(1) << i) & spsens) {
1414 jrow.push_back(i+offset);
1421 for (casadi_int i=0; i<ndir_local; ++i) {
1427 if (!fwd) swap(jrow, jcol);
1430 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(ret.
size()) +
", "
1437 casadi_int iind)
const {
1441 casadi_int nz =
nnz_in(iind);
1442 casadi_assert_dev(nz==
nnz_out(oind));
1445 std::vector<const bvec_t*> arg(
sz_arg(),
nullptr);
1446 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1447 std::vector<casadi_int> iw(
sz_iw());
1448 std::vector<bvec_t> w(
sz_w());
1451 std::vector<bvec_t> seed(nz, 0);
1455 std::vector<bvec_t> sens(nz, 0);
1459 std::vector<casadi_int> jcol, jrow;
1462 std::vector<casadi_int> coarse(2, 0); coarse[1] = nz;
1465 std::vector<casadi_int> fine;
1473 casadi_int granularity = nz;
1475 casadi_int nsweeps = 0;
1477 bool hasrun =
false;
1479 while (!hasrun || coarse.size()!=nz+1) {
1480 if (
verbose_) casadi_message(
"Block size: " +
str(granularity));
1492 casadi_message(
"Star coloring on " +
str(r.
dim()) +
": "
1493 +
str(
D.size2()) +
" <-> " +
str(
D.size1()));
1497 std::fill(seed.begin(), seed.end(), 0);
1500 for (casadi_int k=0; k<coarse.size()-1; ++k) {
1501 casadi_int
diff = coarse[k+1]-coarse[k];
1502 casadi_int new_diff =
diff/subdivision;
1503 if (
diff%subdivision>0) new_diff++;
1504 std::vector<casadi_int> temp =
range(coarse[k], coarse[k+1], new_diff);
1505 fine.insert(fine.end(), temp.begin(), temp.end());
1507 if (fine.back()!=coarse.back()) fine.push_back(coarse.back());
1509 granularity = fine[1] - fine[0];
1512 casadi_int bvec_i = 0;
1515 std::vector<casadi_int> fine_lookup =
lookupvector(fine, nz+1);
1518 std::vector<casadi_int> lookup_col;
1519 std::vector<casadi_int> lookup_row;
1520 std::vector<casadi_int> lookup_value;
1523 casadi_int n_fine_blocks_max = 0;
1524 for (casadi_int i=0;i<coarse.size()-1;++i) {
1525 casadi_int del = fine_lookup[coarse[i+1]]-fine_lookup[coarse[i]];
1526 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1530 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1533 casadi_int fci_offset = 0;
1537 bool f_finished =
false;
1540 while (!f_finished) {
1543 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1544 casadi_int cci =
D.row(k);
1547 casadi_int fci_start = fine_lookup[coarse[cci]];
1548 casadi_int fci_end = fine_lookup[coarse[cci+1]];
1551 casadi_int bvec_i_mod = 0;
1553 casadi_int value = -bvec_i + fci_offset + fci_start;
1558 for (casadi_int fci = fci_offset; fci<std::min(fci_end-fci_start, fci_cap); ++fci) {
1562 for (casadi_int cri=r.
colind(cci);cri<r.
colind(cci+1);++cri) {
1563 lookup_col.push_back(r.
row(cri));
1564 lookup_row.push_back(bvec_i+bvec_i_mod);
1565 lookup_value.push_back(value);
1576 bvec_i += std::min(n_fine_blocks_max, fci_cap);
1586 IM lookup =
IM::triplet(lookup_row, lookup_col, lookup_value,
1589 std::reverse(lookup_col.begin(), lookup_col.end());
1590 std::reverse(lookup_row.begin(), lookup_row.end());
1591 std::reverse(lookup_value.begin(), lookup_value.end());
1595 duplicates = sparsify(duplicates);
1606 for (casadi_int cri=0; cri<coarse.size()-1; ++cri) {
1609 for (casadi_int fri=fine_lookup[coarse[cri]];fri<fine_lookup[coarse[cri+1]];++fri) {
1614 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1615 if (spsens & (
bvec_t(1) << bvec_i)) {
1618 if (ind==-1)
continue;
1619 casadi_int lk = lookup->at(ind);
1621 jrow.push_back(bvec_i+lk);
1622 jcol.push_back(fri);
1623 jrow.push_back(fri);
1624 jcol.push_back(bvec_i+lk);
1632 std::fill(seed.begin(), seed.end(), 0);
1637 lookup_value.clear();
1640 if (n_fine_blocks_max>fci_cap) {
1641 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1663 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1664 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
1679 std::vector<bvec_t> s_in(
nz_in, 0);
1680 std::vector<bvec_t> s_out(
nz_out, 0);
1683 std::vector<const bvec_t*> arg_fwd(
sz_arg(),
nullptr);
1684 std::vector<bvec_t*> arg_adj(
sz_arg(),
nullptr);
1685 arg_fwd[iind] = arg_adj[iind] =
get_ptr(s_in);
1686 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1688 std::vector<casadi_int> iw(
sz_iw());
1689 std::vector<bvec_t> w(
sz_w());
1692 std::vector<casadi_int> jcol, jrow;
1695 std::vector<casadi_int> coarse_col(2, 0); coarse_col[1] =
nz_out;
1697 std::vector<casadi_int> coarse_row(2, 0); coarse_row[1] =
nz_in;
1700 std::vector<casadi_int> fine_col;
1703 std::vector<casadi_int> fine_row;
1711 casadi_int granularity_row =
nz_in;
1712 casadi_int granularity_col =
nz_out;
1714 bool use_fwd =
true;
1716 casadi_int nsweeps = 0;
1718 bool hasrun =
false;
1724 std::vector<bvec_t> bvec_lookup;
1727 bvec_lookup.push_back(
bvec_t(1) << i);
1730 while (!hasrun || coarse_col.size()!=
nz_out+1 || coarse_row.size()!=
nz_in+1) {
1732 casadi_message(
"Block size: " +
str(granularity_col) +
" x " +
str(granularity_row));
1753 casadi_message(
"Coloring on " +
str(r.
dim()) +
" (fwd seeps: " +
str(D1.
size2()) +
1754 " , adj sweeps: " +
str(D2.
size1()) +
")");
1758 double fwd_cost =
static_cast<double>(use_fwd ? granularity_row : granularity_col) *
1759 sp_w*
static_cast<double>(D1.
size2());
1760 double adj_cost =
static_cast<double>(use_fwd ? granularity_col : granularity_row) *
1761 (1-sp_w)*
static_cast<double>(D2.
size2());
1762 use_fwd = fwd_cost <= adj_cost;
1764 casadi_message(std::string(use_fwd ?
"Forward" :
"Reverse") +
" mode chosen "
1765 "(fwd cost: " +
str(fwd_cost) +
", adj cost: " +
str(adj_cost) +
")");
1777 for (casadi_int i=0; i<nz_seed; ++i) seed_v[i]=0;
1784 std::swap(coarse_col, coarse_row);
1785 std::swap(granularity_col, granularity_row);
1790 for (casadi_int k=0;k<coarse_col.size()-1;++k) {
1791 casadi_int
diff = coarse_col[k+1]-coarse_col[k];
1792 casadi_int new_diff =
diff/subdivision;
1793 if (
diff%subdivision>0) new_diff++;
1794 std::vector<casadi_int> temp =
range(coarse_col[k], coarse_col[k+1], new_diff);
1795 fine_col.insert(fine_col.end(), temp.begin(), temp.end());
1798 for (casadi_int k=0;k<coarse_row.size()-1;++k) {
1799 casadi_int
diff = coarse_row[k+1]-coarse_row[k];
1800 casadi_int new_diff =
diff/subdivision;
1801 if (
diff%subdivision>0) new_diff++;
1802 std::vector<casadi_int> temp =
range(coarse_row[k], coarse_row[k+1], new_diff);
1803 fine_row.insert(fine_row.end(), temp.begin(), temp.end());
1805 if (fine_row.back()!=coarse_row.back()) fine_row.push_back(coarse_row.back());
1806 if (fine_col.back()!=coarse_col.back()) fine_col.push_back(coarse_col.back());
1808 granularity_col = fine_col[1] - fine_col[0];
1809 granularity_row = fine_row[1] - fine_row[0];
1812 casadi_int bvec_i = 0;
1815 std::vector<casadi_int> fine_col_lookup =
lookupvector(fine_col, nz_sens+1);
1816 std::vector<casadi_int> fine_row_lookup =
lookupvector(fine_row, nz_seed+1);
1819 std::vector<casadi_int> lookup_col;
1820 std::vector<casadi_int> lookup_row;
1821 std::vector<casadi_int> lookup_value;
1825 casadi_int n_fine_blocks_max = 0;
1826 for (casadi_int i=0;i<coarse_row.size()-1;++i) {
1827 casadi_int del = fine_row_lookup[coarse_row[i+1]]-fine_row_lookup[coarse_row[i]];
1828 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1832 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1834 casadi_int fci_offset = 0;
1838 bool f_finished =
false;
1841 while (!f_finished) {
1844 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1845 casadi_int cci =
D.row(k);
1848 casadi_int fci_start = fine_row_lookup[coarse_row[cci]];
1849 casadi_int fci_end = fine_row_lookup[coarse_row[cci+1]];
1852 casadi_int bvec_i_mod = 0;
1854 casadi_int value = -bvec_i + fci_offset + fci_start;
1857 for (casadi_int fci = fci_offset; fci < std::min(fci_end-fci_start, fci_cap); ++fci) {
1861 for (casadi_int cri=rT.
colind(cci);cri<rT.
colind(cci+1);++cri) {
1862 lookup_col.push_back(rT.
row(cri));
1863 lookup_row.push_back(bvec_i+bvec_i_mod);
1864 lookup_value.push_back(value);
1868 bvec_toggle(seed_v, fine_row[fci+fci_start], fine_row[fci+fci_start+1],
1875 bvec_i+= std::min(n_fine_blocks_max, fci_cap);
1890 JacSparsityTraits<true>::sp(
this,
get_ptr(arg_fwd),
get_ptr(res),
1893 std::fill(w.begin(), w.end(), 0);
1894 JacSparsityTraits<false>::sp(
this,
get_ptr(arg_adj),
get_ptr(res),
1902 for (casadi_int cri=0;cri<coarse_col.size()-1;++cri) {
1905 for (casadi_int fri=fine_col_lookup[coarse_col[cri]];
1906 fri<fine_col_lookup[coarse_col[cri+1]];++fri) {
1908 bvec_or(sens_v, spsens, fine_col[fri], fine_col[fri+1]);
1911 if (!spsens)
continue;
1914 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1915 if (spsens & bvec_lookup[bvec_i]) {
1918 if (ind==-1)
continue;
1919 jrow.push_back(bvec_i+lookup->at(ind));
1920 jcol.push_back(fri);
1927 std::fill(s_in.begin(), s_in.end(), 0);
1930 std::fill(s_out.begin(), s_out.end(), 0);
1935 lookup_value.clear();
1938 if (n_fine_blocks_max>fci_cap) {
1939 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1954 coarse_col = fine_col;
1955 coarse_row = fine_row;
1959 coarse_col = fine_row;
1960 coarse_row = fine_col;
1965 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1966 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
", " +
1978 if (
name_ ==
"adj1_" + n) {
1979 if (iind == oind)
return true;
1987 bool symmetric)
const {
1990 "Symmetry exploitation in Jacobian assumes dense expression. "
1991 "A potential workaround is to apply densify().");
2023 if (w*
static_cast<double>(nsweep_fwd) <= (1-w)*
static_cast<double>(nsweep_adj)) {
2024 sp = get_jac_sparsity_gen<true>(oind, iind);
2026 sp = get_jac_sparsity_gen<false>(oind, iind);
2039 std::vector<casadi_int> mapping;
2062 bool symmetric)
const {
2063 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2065 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
2068 for (
bool c : {
false,
true}) {
2072 casadi_int ind = iind + oind *
n_in_;
2088 sp_is_compact =
true;
2100 if (sp_is_compact == compact) {
2127 bool compact,
bool symmetric,
2128 bool allow_forward,
bool allow_reverse)
const {
2130 casadi_assert(allow_forward || allow_reverse,
"Inconsistent options");
2139 casadi_assert_dev(allow_forward);
2142 if (
verbose_) casadi_message(
"FunctionInternal::getPartition star_coloring");
2145 casadi_message(
"Star coloring completed: " +
str(D1.
size2())
2146 +
" directional derivatives needed ("
2147 +
str(A.
size1()) +
" without coloring).");
2156 if (w==1) allow_forward =
false;
2157 if (w==0) allow_reverse =
false;
2158 casadi_assert(allow_forward || allow_reverse,
"Conflicting ad weights");
2161 double best_coloring = std::numeric_limits<double>::infinity();
2164 bool test_fwd_first = allow_forward && w*
static_cast<double>(A.
size1()) <=
2165 (1-w)*
static_cast<double>(A.
size2());
2166 casadi_int mode_fwd = test_fwd_first ? 0 : 1;
2169 for (casadi_int mode=0; mode<2; ++mode) {
2171 bool fwd = mode==mode_fwd;
2174 if (!allow_forward && fwd)
continue;
2175 if (!allow_reverse && !fwd)
continue;
2179 if (
verbose_) casadi_message(
"Unidirectional coloring (forward mode)");
2180 bool d = best_coloring>=w*
static_cast<double>(A.
size1());
2181 casadi_int max_colorings_to_test =
2182 d ? A.
size1() :
static_cast<casadi_int
>(floor(best_coloring/w));
2186 casadi_message(
"Forward mode coloring interrupted (more than "
2187 +
str(max_colorings_to_test) +
" needed).");
2191 casadi_message(
"Forward mode coloring completed: "
2192 +
str(D1.
size2()) +
" directional derivatives needed ("
2193 +
str(A.
size1()) +
" without coloring).");
2196 best_coloring = w*
static_cast<double>(D1.
size2());
2199 if (
verbose_) casadi_message(
"Unidirectional coloring (adjoint mode)");
2200 bool d = best_coloring>=(1-w)*
static_cast<double>(A.
size2());
2201 casadi_int max_colorings_to_test =
2202 d ? A.
size2() :
static_cast<casadi_int
>(floor(best_coloring/(1-w)));
2207 casadi_message(
"Adjoint mode coloring interrupted (more than "
2208 +
str(max_colorings_to_test) +
" needed).");
2212 casadi_message(
"Adjoint mode coloring completed: "
2213 +
str(D2.
size2()) +
" directional derivatives needed ("
2214 +
str(A.
size2()) +
" without coloring).");
2217 best_coloring = (1-w)*
static_cast<double>(D2.
size2());
2226 casadi_error(
"'eval_dm' not defined for " +
class_name());
2231 bool always_inline,
bool never_inline)
const {
2236 casadi_assert(!always_inline,
"'eval_sx' not defined for " +
class_name() +
2237 " in combination with always_inline true");
2244 casadi_int highest_index = 0;
2247 for (
const std::string& n : name_io) {
2249 size_t end = n.find(
'_');
2250 if (end >= n.size())
continue;
2252 if (end < prefix.size())
continue;
2254 if (n.compare(0, prefix.size(), prefix) != 0)
continue;
2256 size_t begin = prefix.size();
2258 casadi_int this_index;
2264 this_index = std::stoi(n.substr(begin, end - begin));
2267 if (this_index > highest_index) highest_index = this_index;
2271 if (highest_index == 0) {
2272 return prefix +
"_";
2274 return prefix + std::to_string(highest_index + 1) +
"_";
2279 casadi_assert_dev(nfwd>=0);
2294 std::vector<std::string> inames;
2297 for (i=0; i<
n_in_; ++i) inames.push_back(pref +
name_in_[i]);
2299 std::vector<std::string> onames;
2308 opts[
"derivative_of"] =
self();
2312 f =
get_forward(nfwd, fname, inames, onames, opts);
2325 casadi_error(
"Unknown 'fd_method': " +
fd_method_);
2344 casadi_assert_dev(nadj>=0);
2359 std::vector<std::string> inames;
2364 std::vector<std::string> onames;
2365 for (casadi_int i=0; i<
n_in_; ++i) onames.push_back(pref +
name_in_[i]);
2369 opts[
"derivative_of"] =
self();
2372 f =
get_reverse(nadj, fname, inames, onames, opts);
2389 get_forward(casadi_int nfwd,
const std::string& name,
2390 const std::vector<std::string>& inames,
2391 const std::vector<std::string>& onames,
2392 const Dict& opts)
const {
2393 casadi_error(
"'get_forward' not defined for " +
class_name());
2397 get_reverse(casadi_int nadj,
const std::string& name,
2398 const std::vector<std::string>& inames,
2399 const std::vector<std::string>& onames,
2400 const Dict& opts)
const {
2401 casadi_error(
"'get_reverse' not defined for " +
class_name());
2405 const Dict& options)
const {
2406 casadi_error(
"'export_code' not defined for " +
class_name());
2410 casadi_int n = s.size();
2412 std::stringstream ss;
2413 for (casadi_int i=0;i<n;++i) {
2417 casadi_assert_dev(s==ss.str());
2422 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
nnz_in(iind);
2428 for (casadi_int oind=0; oind<
n_out_; ++oind) ret +=
nnz_out(oind);
2434 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
numel_in(iind);
2445 bool always_inline,
bool never_inline)
const {
2451 if (always_inline) {
2452 casadi_assert(!never_inline,
"Inconsistent options for " +
str(
name_));
2466 "Derivatives cannot be calculated for " +
name_);
2471 std::string fname =
"jac_" +
name_;
2474 std::vector<std::string> inames;
2475 for (casadi_int i=0; i<
n_in_; ++i) inames.push_back(
name_in_[i]);
2476 for (casadi_int i=0; i<
n_out_; ++i) inames.push_back(
"out_" +
name_out_[i]);
2478 std::vector<std::string> onames;
2480 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2481 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2487 opts[
"derivative_of"] =
self();
2492 casadi_assert(f.
n_in() == inames.size(),
2493 "Mismatching input signature, expected " +
str(inames));
2494 casadi_assert(f.
n_out() == onames.size(),
2495 "Mismatching output signature, expected " +
str(onames));
2504 const std::vector<std::string>& inames,
2505 const std::vector<std::string>& onames,
2506 const Dict& opts)
const {
2507 casadi_error(
"'get_jacobian' not defined for " +
class_name());
2513 g <<
"static " <<
signature(fname) <<
" {\n";
2521 Function F = shared_from_this<Function>();
2523 std::string dump_counter = g.
shorthand(cg_name +
"_dump_counter");
2524 g.
auxiliaries <<
"static int " << dump_counter <<
" = 0;\n";
2527 std::string dump_mutex = g.
local_mutex(F, cg_name +
"_dump_mutex");
2528 g <<
"CASADI_MUTEX_LOCK(&" << dump_mutex <<
");\n";
2529 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2530 g <<
"CASADI_MUTEX_UNLOCK(&" << dump_mutex <<
");\n";
2532 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2556 return "int " + fname +
"(const casadi_real** arg, casadi_real** res, "
2557 "casadi_int* iw, casadi_real* w, int mem)";
2561 std::vector<std::string> args;
2563 args.push_back(
"const casadi_real* " +
str(e));
2566 args.push_back(
"casadi_real* " +
str(e));
2568 args.push_back(
"const casadi_real** arg");
2569 args.push_back(
"casadi_real** res");
2570 args.push_back(
"casadi_int* iw");
2571 args.push_back(
"casadi_real* w");
2572 args.push_back(
"int mem");
2573 return "int " + fname +
"_unrolled(" +
join(args,
", ") +
")";
2579 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2580 g.
auxiliaries <<
"static int " << ref_counter <<
" = 0;\n";
2582 Function F = shared_from_this<Function>();
2586 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2587 g <<
"if (" << ref_counter <<
"==0) CASADI_MUTEX_INIT(&" << mtx <<
");\n";
2591 g << ref_counter <<
"++;\n";
2595 std::set<void*> added;
2596 Function F = shared_from_this<Function>();
2598 if (f->has_refcount_in_deps_) {
2599 std::string cg_name = f->codegen_name(g,
false);
2600 auto i = added.insert(f.get());
2602 std::string incref = g.
shorthand(cg_name +
"_incref");
2603 g << incref <<
"();\n";
2612 std::set<void*> added;
2613 Function F = shared_from_this<Function>();
2615 if (f->has_refcount_in_deps_) {
2616 std::string cg_name = f->codegen_name(g,
false);
2617 auto i = added.insert(f.get());
2619 std::string decref = g.
shorthand(cg_name +
"_decref");
2620 g << decref <<
"();\n";
2627 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2628 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2630 g << ref_counter <<
"--;\n";
2631 g <<
"if (" << ref_counter <<
"==0) {\n";
2633 g <<
"while (" << mem_counter <<
">0) {\n";
2634 g <<
free_mem <<
"(--" << mem_counter <<
");\n";
2638 Function F = shared_from_this<Function>();
2641 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2642 g <<
"CASADI_MUTEX_DESTROY(&" << mtx <<
");\n";
2658 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2659 g <<
"return " + mem_counter +
"++;\n";
2665 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2666 std::string stack = g.
shorthand(name +
"_unused_stack");
2667 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2668 std::string mem_array = g.
shorthand(name +
"_mem");
2673 g.
auxiliaries <<
"static int " << mem_counter <<
" = 0;\n";
2674 g.
auxiliaries <<
"static int " << stack_counter <<
" = -1;\n";
2675 g.
auxiliaries <<
"static int " << stack <<
"[CASADI_MAX_NUM_THREADS];\n";
2677 " " << mem_array <<
"[CASADI_MAX_NUM_THREADS];\n\n";
2680 Function F = shared_from_this<Function>();
2682 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2683 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2687 g.
local(
"mid",
"int");
2689 g <<
"if (" << stack_counter <<
">=0) {\n";
2692 g <<
"if (" << mem_counter <<
"==CASADI_MAX_NUM_THREADS) {\n";
2696 g <<
"if (mid<0) {\n";
2699 g <<
"if (" <<
init_mem <<
"(mid)) {\n";
2708 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2709 std::string stack = g.
shorthand(name +
"_unused_stack");
2712 Function F = shared_from_this<Function>();
2713 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2714 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2718 g << stack <<
"[++" << stack_counter <<
"] = mem;\n";
2731 g << g.
declare(
"int " +
name_ +
"_checkout(void)") <<
" {\n";
2734 g <<
"return " <<
checkout <<
"();\n";
2741 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2745 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2750 g << g.
declare(
"void " +
name_ +
"_incref(void)") <<
" {\n";
2752 std::string incref = g.
shorthand(name +
"_incref");
2753 g << incref <<
"();\n";
2756 << g.
declare(
"void " +
name_ +
"_decref(void)") <<
" {\n";
2758 std::string decref = g.
shorthand(name +
"_decref");
2759 g << decref <<
"();\n";
2765 <<
" { return " <<
n_in_ <<
";}\n\n"
2767 <<
" { return " <<
n_out_ <<
";}\n\n";
2770 g << g.
declare(
"casadi_real " +
name_ +
"_default_in(casadi_int i)") <<
" {\n"
2771 <<
"switch (i) {\n";
2772 for (casadi_int i=0; i<
n_in_; ++i) {
2774 if (def!=0) g <<
"case " << i <<
": return " << g.
constant(def) <<
";\n";
2776 g <<
"default: return 0;\n}\n"
2780 g << g.
declare(
"const char* " +
name_ +
"_name_in(casadi_int i)") <<
" {\n"
2781 <<
"switch (i) {\n";
2782 for (casadi_int i=0; i<
n_in_; ++i) {
2783 g <<
"case " << i <<
": return \"" <<
name_in_[i] <<
"\";\n";
2785 g <<
"default: return 0;\n}\n"
2789 g << g.
declare(
"const char* " +
name_ +
"_name_out(casadi_int i)") <<
" {\n"
2790 <<
"switch (i) {\n";
2791 for (casadi_int i=0; i<
n_out_; ++i) {
2792 g <<
"case " << i <<
": return \"" <<
name_out_[i] <<
"\";\n";
2794 g <<
"default: return 0;\n}\n"
2802 "int " +
name_ +
"_work(casadi_int *sz_arg, casadi_int* sz_res, "
2803 "casadi_int *sz_iw, casadi_int *sz_w)")
2814 "int " +
name_ +
"_work_bytes(casadi_int *sz_arg, casadi_int* sz_res, "
2815 "casadi_int *sz_iw, casadi_int *sz_w)")
2817 <<
"if (sz_arg) *sz_arg = " <<
codegen_sz_arg(g) <<
"*sizeof(const casadi_real*);\n"
2818 <<
"if (sz_res) *sz_res = " <<
codegen_sz_res(g) <<
"*sizeof(casadi_real*);\n"
2819 <<
"if (sz_iw) *sz_iw = " <<
codegen_sz_iw(g) <<
"*sizeof(casadi_int);\n"
2820 <<
"if (sz_w) *sz_w = " <<
codegen_sz_w(g) <<
"*sizeof(casadi_real);\n"
2835 g << g.
declare(
"int " +
name_ +
"_diff_in(casadi_int i)") <<
" {\n"
2836 <<
"switch (i) {\n";
2837 for (casadi_int i=0; i<
n_in_; ++i) {
2838 g <<
"case " << i <<
": return " <<
is_diff_in_[i] <<
";\n";
2840 g <<
"default: return -1;\n}\n"
2846 g << g.
declare(
"int " +
name_ +
"_diff_out(casadi_int i)") <<
" {\n"
2847 <<
"switch (i) {\n";
2848 for (casadi_int i=0; i<
n_out_; ++i) {
2849 g <<
"case " << i <<
": return " <<
is_diff_out_[i] <<
";\n";
2851 g <<
"default: return -1;\n}\n"
2858 g <<
"#ifdef MATLAB_MEX_FILE\n";
2861 g <<
"void mex_" <<
name_
2862 <<
"(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {\n"
2863 <<
"casadi_int i;\n";
2868 for (casadi_int i=0; i<
n_in_; ++i) {
2873 sz_w += i_nnz + o_nnz;
2876 std::string fw =
"w+" +
str(i_nnz + o_nnz);
2879 casadi_int offset=0;
2883 g <<
"casadi_real* res[" <<
sz_res() <<
"] = {0};\n";
2886 g <<
"if (argc>" <<
n_in_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2887 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. Too many input arguments "
2888 <<
"(%d, max " <<
n_in_ <<
")\", argc);\n";
2890 g <<
"if (resc>" <<
n_out_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2891 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. "
2892 <<
"Too many output arguments (%d, max " <<
n_out_ <<
")\", resc);\n";
2894 for (casadi_int i=0; i<
n_in_; ++i) {
2895 std::string p =
"argv[" +
str(i) +
"]";
2896 g <<
"if (--argc>=0) arg[" << i <<
"] = "
2901 for (casadi_int i=0; i<
n_out_; ++i) {
2907 g <<
"if (--resc>=0) ";
2910 g << g.
res(i) <<
" = w+" <<
str(offset) <<
";\n";
2913 g <<
name_ <<
"_incref();\n";
2914 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2917 g <<
"i = " <<
name_ <<
"(arg, res, iw, " << fw <<
", mem);\n"
2918 <<
"if (i) mexErrMsgIdAndTxt(\"Casadi:RuntimeError\",\"Evaluation of \\\"" <<
name_
2919 <<
"\\\" failed.\");\n";
2920 g <<
name_ <<
"_release(mem);\n";
2921 g <<
name_ <<
"_decref();\n";
2924 for (casadi_int i=0; i<
n_out_; ++i) {
2925 g <<
"if (" << g.
res(i) <<
") resv[" << i <<
"] = "
2936 g <<
"casadi_int main_" <<
name_ <<
"(casadi_int argc, char* argv[]) {\n";
2938 g <<
"casadi_int j;\n";
2939 g <<
"casadi_real* a;\n";
2940 g <<
"const casadi_real* r;\n";
2941 g <<
"casadi_int flag;\n";
2942 if (needs_mem) g <<
"int mem;\n";
2952 g <<
"const casadi_real* arg[" <<
sz_arg() <<
"];\n";
2955 g <<
"casadi_real* res[" <<
sz_res() <<
"];\n";
2958 for (casadi_int i=0; i<
n_in_; ++i) {
2959 g <<
"arg[" << i <<
"] = w+" << off <<
";\n";
2962 for (casadi_int i=0; i<
n_out_; ++i) {
2963 g <<
"res[" << i <<
"] = w+" << off <<
";\n";
2969 <<
"for (j=0; j<" <<
nnz_in() <<
"; ++j) "
2970 <<
"if (scanf(\"%lg\", a++)<=0) return 2;\n";
2973 g <<
name_ <<
"_incref();\n";
2977 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2981 g <<
"flag = " <<
name_ <<
"(arg, res, iw, w+" << off <<
", ";
2989 g <<
name_ <<
"_release(mem);\n";
2993 g <<
name_ <<
"_decref();\n";
2996 g <<
"if (flag) return flag;\n";
2999 g <<
"r = w+" <<
nnz_in() <<
";\n"
3000 <<
"for (j=0; j<" <<
nnz_out() <<
"; ++j) "
3001 << g.
printf(
"%.16e ",
"*r++") <<
"\n";
3004 g << g.
printf(
"\\n") <<
"\n";
3013 g << g.
declare(
"casadi_functions* " +
name_ +
"_functions(void)") <<
" {\n"
3014 <<
"static casadi_functions fun = {\n"
3015 <<
name_ <<
"_incref,\n"
3016 <<
name_ <<
"_decref,\n"
3017 <<
name_ <<
"_checkout,\n"
3018 <<
name_ <<
"_release,\n"
3019 <<
name_ <<
"_default_in,\n"
3020 <<
name_ <<
"_n_in,\n"
3021 <<
name_ <<
"_n_out,\n"
3022 <<
name_ <<
"_name_in,\n"
3023 <<
name_ <<
"_name_out,\n"
3024 <<
name_ <<
"_sparsity_in,\n"
3025 <<
name_ <<
"_sparsity_out,\n"
3026 <<
name_ <<
"_work,\n"
3040 if (e.f.get()==
this)
return e.codegen_name;
3045 if (e.f.get()==
this)
return "f" +
str(i);
3048 casadi_error(
"Function '" +
name_ +
"' not found");
3053 std::string mem_array = g.
shorthand(name +
"_mem");
3054 return mem_array+
"[" + index +
"]";
3062 casadi_warning(
"The function \"" +
name_ +
"\", which is of type \""
3063 +
class_name() +
"\" cannot be code generated. The generation "
3064 "will proceed, but compilation of the code will not be possible.");
3065 g <<
"#error Code generation not supported for " <<
class_name() <<
"\n";
3070 casadi_error(
"'generate_dependencies' not defined for " +
class_name());
3076 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3077 if (res[oind]==
nullptr)
continue;
3078 std::fill_n(res[oind],
nnz_out(oind), ~
static_cast<bvec_t>(0));
3086 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3088 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3092 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3094 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3103 casadi_int* iw,
bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const {
3108 casadi_int d1 = sp.
size2();
3109 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3110 for (casadi_int cc=0; cc<d1; ++cc) {
3111 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3112 res[oind][row[el]] |= arg[iind][cc];
3121 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3123 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3126 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3128 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3135 casadi_int d1 = sp.
size2();
3136 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3137 for (casadi_int cc=0; cc<d1; ++cc) {
3138 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3139 arg[iind][cc] |= res[oind][row[el]];
3151 size_t& sz_iw,
size_t& sz_w)
const {
3154 sz_iw = this->
sz_iw();
3155 sz_w = this->
sz_w();
3175 sz_arg_tmp_ = std::max(sz_arg_tmp_,
sz_arg);
3183 sz_res_tmp_ = std::max(sz_res_tmp_,
sz_res);
3189 sz_iw_per_ +=
sz_iw;
3191 sz_iw_tmp_ = std::max(sz_iw_tmp_,
sz_iw);
3199 sz_w_tmp_ = std::max(sz_w_tmp_,
sz_w);
3218 for (
const auto& s : m->fstats) {
3219 stats[
"n_call_" +s.first] = s.second.n_call;
3220 stats[
"t_wall_" +s.first] = s.second.t_wall;
3221 stats[
"t_proc_" +s.first] = s.second.t_proc;
3229 casadi_assert(m->stats_available,
3230 "No stats available: Function '" +
name_ +
"' not set up. "
3231 "To get statistics, first evaluate it numerically.");
3276 call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3277 const std::vector<std::vector<MX> >& fseed,
3278 std::vector<std::vector<MX> >& fsens,
3279 bool always_inline,
bool never_inline)
const {
3280 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3281 casadi_assert(!always_inline,
"Class " +
class_name() +
3282 " cannot be inlined in an MX expression");
3286 "Derivatives cannot be calculated for " +
name_);
3289 casadi_int nfwd = fseed.size();
3293 if (nfwd==0)
return;
3296 casadi_int npar = 1;
3297 for (
auto&& r : fseed) {
3300 fsens, always_inline, never_inline);
3308 std::vector<MX> darg = arg;
3309 darg.insert(darg.end(), res.begin(), res.end());
3310 std::vector<MX> J =
jacobian()(darg);
3312 std::vector<MX> v(nfwd), all_fseed(
n_in_);
3313 for (
size_t i = 0; i <
n_in_; ++i) {
3314 for (
size_t d = 0; d < nfwd; ++d) v[d] = vec(fseed.at(d).at(i));
3315 all_fseed[i] = horzcat(v);
3318 std::vector<MX> all_fsens(
n_out_);
3319 std::vector<MX>::const_iterator J_it = J.begin();
3320 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3321 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3323 MX a = mtimes(*J_it++, all_fseed[iind]);
3324 all_fsens[oind] = all_fsens[oind].is_empty(
true) ? a : all_fsens[oind] + a;
3328 for (
size_t d = 0; d < nfwd; ++d) fsens[d].resize(
n_out_);
3329 for (
size_t i = 0; i <
n_out_; ++i) {
3330 v = horzsplit(all_fsens[i]);
3331 casadi_assert_dev(v.size() == nfwd);
3332 for (
size_t d = 0; d < nfwd; ++d) fsens[d][i] = reshape(v[d],
size_out(i));
3341 casadi_int offset = 0;
3342 while (offset<nfwd) {
3344 casadi_int nfwd_batch = std::min(nfwd-offset, max_nfwd);
3347 std::vector<MX> darg;
3349 darg.insert(darg.end(), arg.begin(), arg.end());
3350 darg.insert(darg.end(), res.begin(), res.end());
3351 std::vector<MX> v(nfwd_batch);
3352 for (casadi_int i=0; i<
n_in_; ++i) {
3353 for (casadi_int d=0; d<nfwd_batch; ++d) v[d] = fseed[offset+d][i];
3354 darg.push_back(horzcat(v));
3359 std::vector<MX> x = dfcn(darg);
3361 casadi_assert_dev(x.size()==
n_out_);
3364 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d].resize(
n_out_);
3365 for (casadi_int i=0; i<
n_out_; ++i) {
3368 casadi_assert_dev(v.size()==nfwd_batch);
3370 v = std::vector<MX>(nfwd_batch,
MX(
size_out(i)));
3372 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d][i] = v[d];
3376 offset += nfwd_batch;
3382 call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3383 const std::vector<std::vector<MX> >& aseed,
3384 std::vector<std::vector<MX> >& asens,
3385 bool always_inline,
bool never_inline)
const {
3386 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3387 casadi_assert(!always_inline,
"Class " +
class_name() +
3388 " cannot be inlined in an MX expression");
3392 "Derivatives cannot be calculated for " +
name_);
3395 casadi_int nadj = aseed.size();
3399 if (nadj==0)
return;
3402 casadi_int npar = 1;
3403 for (
auto&& r : aseed) {
3406 asens, always_inline, never_inline);
3414 std::vector<MX> darg = arg;
3415 darg.insert(darg.end(), res.begin(), res.end());
3416 std::vector<MX> J =
jacobian()(darg);
3418 std::vector<MX> v(nadj), all_aseed(
n_out_);
3419 for (
size_t i = 0; i <
n_out_; ++i) {
3420 for (
size_t d = 0; d < nadj; ++d) v[d] = vec(aseed.at(d).at(i));
3421 all_aseed[i] = horzcat(v);
3424 std::vector<MX> all_asens(
n_in_);
3425 std::vector<MX>::const_iterator J_it = J.begin();
3426 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3427 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3429 MX a = mtimes((*J_it++).
T(), all_aseed[oind]);
3430 all_asens[iind] = all_asens[iind].is_empty(
true) ? a : all_asens[iind] + a;
3434 for (
size_t d = 0; d < nadj; ++d) asens[d].resize(
n_in_);
3435 for (
size_t i = 0; i <
n_in_; ++i) {
3436 v = horzsplit(all_asens[i]);
3437 casadi_assert_dev(v.size() == nadj);
3438 for (
size_t d = 0; d < nadj; ++d) {
3439 if (asens[d][i].is_empty(
true)) {
3440 asens[d][i] = reshape(v[d],
size_in(i));
3442 asens[d][i] += reshape(v[d],
size_in(i));
3452 casadi_int offset = 0;
3453 while (offset<nadj) {
3455 casadi_int nadj_batch = std::min(nadj-offset, max_nadj);
3458 std::vector<MX> darg;
3460 darg.insert(darg.end(), arg.begin(), arg.end());
3461 darg.insert(darg.end(), res.begin(), res.end());
3462 std::vector<MX> v(nadj_batch);
3463 for (casadi_int i=0; i<
n_out_; ++i) {
3464 for (casadi_int d=0; d<nadj_batch; ++d) v[d] = aseed[offset+d][i];
3465 darg.push_back(horzcat(v));
3470 std::vector<MX> x = dfcn(darg);
3471 casadi_assert_dev(x.size()==
n_in_);
3474 for (casadi_int d=0; d<nadj_batch; ++d) asens[offset+d].resize(
n_in_);
3475 for (casadi_int i=0; i<
n_in_; ++i) {
3478 casadi_assert_dev(v.size()==nadj_batch);
3480 v = std::vector<MX>(nadj_batch,
MX(
size_in(i)));
3482 for (casadi_int d=0; d<nadj_batch; ++d) {
3483 if (asens[offset+d][i].is_empty(
true)) {
3484 asens[offset+d][i] = v[d];
3486 asens[offset+d][i] += v[d];
3491 offset += nadj_batch;
3497 call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3498 const std::vector<std::vector<SX> >& fseed,
3499 std::vector<std::vector<SX> >& fsens,
3500 bool always_inline,
bool never_inline)
const {
3501 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3502 if (fseed.empty()) {
3506 casadi_error(
"'forward' (SX) not defined for " +
class_name());
3510 call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3511 const std::vector<std::vector<SX> >& aseed,
3512 std::vector<std::vector<SX> >& asens,
3513 bool always_inline,
bool never_inline)
const {
3514 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3515 if (aseed.empty()) {
3519 casadi_error(
"'reverse' (SX) not defined for " +
class_name());
3561 std::vector<SX> ret(
n_in_);
3562 for (casadi_int i=0; i<ret.size(); ++i) {
3569 std::vector<SX> ret(
n_out_);
3570 for (casadi_int i=0; i<ret.size(); ++i) {
3577 std::vector<DM> ret(
n_in_);
3578 for (casadi_int i=0; i<ret.size(); ++i) {
3585 std::vector<DM> ret(
n_out_);
3586 for (casadi_int i=0; i<ret.size(); ++i) {
3601 std::vector<MX> ret(
n_in_);
3602 for (casadi_int i=0; i<ret.size(); ++i) {
3609 std::vector<MX> ret(
n_out_);
3610 for (casadi_int i=0; i<ret.size(); ++i) {
3617 return type ==
"FunctionInternal";
3621 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const {
3625 casadi_error(
"'free_mx' only defined for 'MXFunction'");
3629 casadi_error(
"'free_sx' only defined for 'SXFunction'");
3634 casadi_error(
"'generate_lifted' only defined for 'MXFunction'");
3638 casadi_error(
"'n_instructions' not defined for " +
class_name());
3642 casadi_error(
"'instruction_id' not defined for " +
class_name());
3646 casadi_error(
"'instruction_input' not defined for " +
class_name());
3650 casadi_error(
"'instruction_constant' not defined for " +
class_name());
3654 casadi_error(
"'instruction_output' not defined for " +
class_name());
3658 casadi_error(
"'instruction_MX' not defined for " +
class_name());
3662 casadi_error(
"'instructions_sx' not defined for " +
class_name());
3666 casadi_error(
"'n_nodes' not defined for " +
class_name());
3671 const std::string& parallelization) {
3672 if (x.empty())
return x;
3674 casadi_assert(x.size()==
n_in_,
"mapsum_mx: Wrong number_i of arguments");
3676 casadi_int npar = 1;
3678 std::vector<MX> x_mod(x.size());
3679 for (casadi_int i=0; i<
n_in_; ++i) {
3690 for (casadi_int i=0; i<x_mod.size(); ++i) {
3691 n = std::max(x_mod[i].size2() /
size2_in(i), n);
3694 std::vector<casadi_int> reduce_in;
3695 for (casadi_int i=0; i<x_mod.size(); ++i) {
3696 if (x_mod[i].size2()/
size2_in(i)!=n) {
3697 reduce_in.push_back(i);
3709 if (arg.
size()==inp.
size())
return true;
3731 casadi_assert(
nnz_in()==arg.size(),
3732 "Dimension mismatch. Expecting " +
str(
nnz_in()) +
3733 ", got " +
str(arg.size()) +
" instead.");
3735 std::vector<DM> ret =
dm_in();
3736 casadi_int offset = 0;
3737 for (casadi_int i=0;i<
n_in_;++i) {
3739 std::copy(arg.begin()+offset, arg.begin()+offset+
nnz_in(i), r.
ptr());
3746 casadi_assert(
nnz_out()==res.size(),
3747 "Dimension mismatch. Expecting " +
str(
nnz_out()) +
3748 ", got " +
str(res.size()) +
" instead.");
3750 std::vector<DM> ret =
dm_out();
3751 casadi_int offset = 0;
3752 for (casadi_int i=0;i<
n_out_;++i) {
3754 std::copy(res.begin()+offset, res.begin()+offset+
nnz_out(i), r.
ptr());
3762 casadi_int npar = -1;
3768 std::vector<double> ret(
nnz_in());
3769 casadi_int offset = 0;
3770 for (casadi_int i=0;i<
n_in_;++i) {
3771 const double* e = arg2.at(i).ptr();
3772 std::copy(e, e+
nnz_in(i), ret.begin()+offset);
3780 casadi_int npar = -1;
3786 std::vector<double> ret(
nnz_out());
3787 casadi_int offset = 0;
3788 for (casadi_int i=0;i<
n_out_;++i) {
3789 const double* e = res2.at(i).ptr();
3790 std::copy(e, e+
nnz_out(i), ret.begin()+offset);
3797 casadi_int* iw,
double* w)
const {
3805 for (
auto&& i : mem_) {
3814 if (
name_ ==
"jac_" + n) {
3816 }
else if (
name_ ==
"adj1_" + n) {
3827 if (
name_ ==
"jac_" + n) {
3829 }
else if (
name_ ==
"adj1_" + n) {
3840 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
3861 if (
name_ ==
"jac_" + n) {
3875 std::vector<casadi_int> row, colind;
3876 row.reserve(sp_out.
nnz() * sp_in.
nnz());
3877 colind.reserve(sp_in.
numel() + 1);
3879 for (casadi_int c1 = 0; c1 < sp_in.
size2(); ++c1) {
3880 for (casadi_int k1 = sp_in.
colind(c1); k1 < sp_in.
colind(c1 + 1); ++k1) {
3881 casadi_int e1 = sp_in.
row(k1) + sp_in.
size1() * c1;
3883 colind.resize(e1 + 1, row.size());
3885 for (casadi_int c2 = 0; c2 < sp_out.
size2(); ++c2) {
3886 for (casadi_int k2 = sp_out.
colind(c2); k2 < sp_out.
colind(c2 + 1); ++k2) {
3887 row.push_back(sp_out.
row(k2) + sp_out.
size1() * c2);
3893 colind.resize(sp_in.
numel() + 1, row.size());
3896 }
else if (
name_ ==
"adj1_" + n) {
3906 #ifdef CASADI_WITH_THREAD
3907 std::lock_guard<std::mutex> lock(mtx_);
3909 return mem_.at(ind);
3913 return ind<mem_.size();
3917 #ifdef CASADI_WITH_THREAD
3918 std::lock_guard<std::mutex> lock(mtx_);
3920 if (unused_.empty()) {
3926 casadi_error(
"Failed to create or initialize memory object");
3928 return static_cast<int>(mem_.size()) - 1;
3931 int m = unused_.top();
3938 #ifdef CASADI_WITH_THREAD
3939 std::lock_guard<std::mutex> lock(mtx_);
3945 factory(
const std::string& name,
3946 const std::vector<std::string>& s_in,
3947 const std::vector<std::string>& s_out,
3949 const Dict& opts)
const {
3950 return wrap().
factory(name, s_in, s_out, aux, opts);
3955 return std::vector<std::string>();
3959 casadi_error(
"'get_function' not defined for " +
class_name());
3966 const Function& dep, casadi_int max_depth)
const {
3968 if (!dep.
is_null() && all_fun.find(dep.
get()) == all_fun.end()) {
3969 size_t index = all_fun.size();
3970 all_fun[dep.
get()] = std::make_pair(dep, index);
3972 if (max_depth > 0) dep->
find(all_fun, max_depth - 1);
3977 casadi_int max_depth)
const {
3984 which_depends(
const std::string& s_in,
const std::vector<std::string>& s_out,
3985 casadi_int order,
bool tr)
const {
3986 Function f = shared_from_this<Function>();
3992 const std::vector<std::pair<std::string, casadi_int> >& tasks)
const {
3993 casadi_assert(tasks.empty(),
"simplify passes not supported for " +
class_name());
3998 casadi_error(
"'oracle' not defined for " +
class_name());
4004 const std::vector<casadi_int>& order_in,
4005 const std::vector<casadi_int>& order_out,
const Dict& opts)
const {
4006 return wrap().
slice(name, order_in, order_out, opts);
4011 for (casadi_int i=0; i<
n_in_; ++i) {
4015 for (casadi_int i=0; i<
n_out_; ++i) {
4023 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
4025 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
4027 casadi_int ind = iind + oind *
n_in_;
4035 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
4040 std::vector<DM> argv(
n_in_);
4041 for (casadi_int i=0; i<
n_in_; ++i) {
4043 casadi_copy(arg[i], argv[i].nnz(), argv[i].ptr());
4047 std::vector<DM> resv =
eval_dm(argv);
4050 casadi_assert(resv.size()==
n_out_,
4051 "Expected " +
str(
n_out_) +
" outputs, got " +
str(resv.size()) +
".");
4054 for (casadi_int i=0; i<
n_out_; ++i) {
4059 casadi_error(
"Shape mismatch for output " +
str(i) +
": got " + resv[i].dim() +
", "
4063 if (res[i])
casadi_copy(resv[i].ptr(), resv[i].nnz(), res[i]);
4067 }
catch(std::exception& e) {
4068 casadi_error(
"Failed to evaluate 'eval_dm' for " +
name_ +
":\n" + e.what());
4073 casadi_error(
"'eval' not defined for " +
class_name());
4082 for (
auto &&s : fstats) {
4083 name_len = std::max(s.first.size(), name_len);
4085 name_len = std::max(
name_.size(), name_len);
4089 sprint(namefmt,
sizeof(namefmt),
"%%%ds ",
static_cast<casadi_int
>(name_len));
4094 print(
" : %8s %10s %8s %10s %9s\n",
"t_proc",
"(avg)",
"t_wall",
"(avg)",
"n_eval");
4097 char buffer_proc[10];
4098 char buffer_wall[10];
4099 char buffer_proc_avg[10];
4100 char buffer_wall_avg[10];
4103 for (
const auto &s : fstats) {
4104 if (s.second.n_call!=0) {
4105 print(namefmt, s.first.c_str());
4108 format_time(buffer_proc_avg, s.second.t_proc/s.second.n_call);
4109 format_time(buffer_wall_avg, s.second.t_wall/s.second.n_call);
4110 print(
" | %s (%s) %s (%s) %9d\n",
4111 buffer_proc, buffer_proc_avg,
4112 buffer_wall, buffer_wall_avg, s.second.n_call);
4119 casadi_assert_dev(time>=0);
4120 double log_time = log10(time);
4121 int magn =
static_cast<int>(floor(log_time));
4122 int iprefix =
static_cast<int>(floor(log_time/3));
4124 sprint(buffer, 10,
" 0");
4128 sprint(buffer, 10,
" inf");
4131 char prefixes[] =
"TGMk munp";
4132 char prefix = prefixes[4-iprefix];
4134 int rem = magn-3*iprefix;
4135 double time_normalized = time/pow(10, 3*iprefix);
4138 sprint(buffer, 10,
" %1.2f%cs", time_normalized, prefix);
4139 }
else if (rem==1) {
4140 sprint(buffer, 10,
" %2.2f%cs", time_normalized, prefix);
4142 sprint(buffer, 10,
"%3.2f%cs", time_normalized, prefix);
4149 va_start(args, fmt);
4151 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4155 casadi_assert(n>=0 && n<buf_sz,
"Print failure while processing '" + std::string(fmt) +
"'");
4161 va_start(args, fmt);
4164 size_t buf_sz =
sizeof(buf);
4165 char* buf_dyn =
nullptr;
4167 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4169 if (n>
static_cast<casadi_int
>(buf_sz)) {
4170 buf_sz =
static_cast<size_t>(n+1);
4171 buf_dyn =
new char[buf_sz];
4172 n = vsnprintf(buf_dyn, buf_sz, fmt, args);
4175 if (n>=0)
uout() << (buf_dyn ? buf_dyn : buf) << std::flush;
4180 casadi_assert(n>=0,
"Print failure while processing '" + std::string(fmt) +
"'");
4185 bool always_inline,
bool never_inline)
const {
4187 eval_mx(arg, res, always_inline, never_inline);
4190 std::vector<std::vector<MX>> v(npar, arg);
4192 for (
int i=0; i<
n_in_; ++i) {
4194 t = horzsplit(arg[i],
size2_in(i));
4195 casadi_assert_dev(t.size()==npar);
4196 for (
int p=0; p<npar; ++p) v[p][i] = t[p];
4200 for (
int p=0; p<npar; ++p) {
4201 eval_mx(v[p], t, always_inline, never_inline);
4207 for (
int i=0; i<
n_out_; ++i) {
4208 for (
int p=0; p<npar; ++p) t[p] = v[p][i];
4209 res[i] = horzcat(t);
4219 default:
return "SOLVER_RET_UNKNOWN";
4224 s.
version(
"ProtoFunction", 2);
4234 int version = s.
version(
"ProtoFunction", 1, 2);
4249 s.
version(
"FunctionInternal", 8);
4257 s.
pack(
"FunctionInternal::jit",
jit_);
4265 casadi_assert(binary_ptr,
"Could not open library '" +
compiler_.
library() +
"'.");
4266 s.
pack(
"FunctionInternal::jit_binary", *binary_ptr);
4317 s.
pack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4318 s.
pack(
"FunctionInternal::sz_res_per", sz_res_per_);
4319 s.
pack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4320 s.
pack(
"FunctionInternal::sz_w_per", sz_w_per_);
4321 s.
pack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4322 s.
pack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4323 s.
pack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4324 s.
pack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4333 int version = s.
version(
"FunctionInternal", 1, 8);
4349 std::string library;
4350 s.
unpack(
"FunctionInternal::jit_library", library);
4356 std::stringstream ss;
4357 s.
unpack(
"FunctionInternal::jit_binary", ss);
4360 s.
unpack(
"FunctionInternal::jit_binary", *binary_ptr);
4434 s.
unpack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4435 s.
unpack(
"FunctionInternal::sz_res_per", sz_res_per_);
4436 s.
unpack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4437 s.
unpack(
"FunctionInternal::sz_w_per", sz_w_per_);
4438 s.
unpack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4439 s.
unpack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4440 s.
unpack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4441 s.
unpack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4457 std::string base_function;
4458 s.
unpack(
"FunctionInternal::base_function", base_function);
4461 "FunctionInternal::deserialize: not found '" + base_function +
"'");
4464 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.
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?
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 that calculates nfwd forward 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
Which variables enter with some order.
void assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const
Assert that an input dimension is equal so some given value.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
FunctionInternal * get() const
const std::vector< std::string > & name_in() const
Get input scheme.
const std::string & name() const
Name of the function.
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in the expression graphs.
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
Function jacobian() const
Calculate all Jacobian blocks.
static Function create(FunctionInternal *node)
Create from node.
static bool check_name(const std::string &name)
Check if a string is a valid function name.
bool is_diff_out(casadi_int ind) const
Get differentiability of inputs/output.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Get output dimension.
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
void assert_sparsity_out(casadi_int i, const Sparsity &sp, casadi_int n=1, bool allow_all_zero_sparse=true) const
Assert that an output sparsity is a multiple of some given sparsity.
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
Get differentiability of inputs/output.
Function slice(const std::string &name, const std::vector< casadi_int > &order_in, const std::vector< casadi_int > &order_out, const Dict &opts=Dict()) const
returns a new function with a selection of inputs/outputs of the original
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate the function symbolically or numerically.
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity 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
const std::vector< std::string > & name_out() const
Get output scheme.
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
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.
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
Get the index of an existing non-zero element.
bool is_vector() const
Check if the pattern is a row or 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
Get a submatrix.
casadi_int numel() const
The total number of elements, including structural zeros, i.e. size2()*size1()
casadi_int size1() const
Get the number of rows.
Sparsity star_coloring(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a star coloring of a symmetric matrix:
std::string dim(bool with_nz=false) const
Get the dimension as a string.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Sparsity T() const
Transpose the matrix.
bool is_scalar(bool scalar_and_dense=false) const
Is scalar?
void enlargeColumns(casadi_int ncol, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the matrix along the second dimension (i.e. insert columns)
void enlargeRows(casadi_int nrow, const std::vector< casadi_int > &rr, bool ind1=false)
Enlarge the matrix along the first dimension (i.e. insert rows)
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
static Sparsity scalar(bool dense_scalar=true)
Create a scalar sparsity pattern *.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
double density() const
The percentage of nonzero.
Sparsity uni_coloring(const Sparsity &AT=Sparsity(), casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a unidirectional coloring: A greedy distance-2 coloring algorithm.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
bool is_dense() const
Is dense?
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 given the nonzeros in sparse triplet form *.
bool is_symmetric() const
Is symmetric?
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)