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 "filesystem_impl.hpp"
71 casadi_error(
"Function name is not valid. A valid function name is a std::string "
72 "starting with a letter followed by letters, numbers or "
73 "non-consecutive underscores. It may also not match the keywords "
74 "'null', 'jac' or 'hess'. Got '" +
name_ +
"'");
124 for (
void* m : mem_) {
125 if (m!=
nullptr) casadi_warning(
"Memory object has not been properly freed");
133 std::string jit_name = jit_directory +
jit_name_ +
".c";
134 if (
remove(jit_name.c_str())) casadi_warning(
"Failed to remove " + jit_name);
151 }
catch(std::exception& e) {
152 casadi_error(
"Error calling " +
class_name() +
"::init for '" +
name_ +
"':\n"
153 + std::string(e.what()));
159 }
catch(std::exception& e) {
160 casadi_error(
"Error calling " +
class_name() +
"::finalize for '" +
name_ +
"':\n"
161 + std::string(e.what()));
169 "Verbose evaluation -- for debugging"}},
172 "print information about execution time. Implies record_time."}},
175 "record information about execution time, for retrieval with stats()."}},
178 "Throw exceptions when NaN or Inf appears during evaluation"}},
181 "Throw exceptions when function evaluation fails (default true)."}}
189 "Weighting factor for derivative calculation."
190 "When there is an option of either using forward or reverse mode "
191 "directional derivatives, the condition ad_weight*nf<=(1-ad_weight)*na "
192 "is used where nf and na are estimates of the number of forward/reverse "
193 "mode directional derivatives needed. By default, ad_weight is calculated "
194 "automatically, but this can be overridden by setting this option. "
195 "In particular, 0 means forcing forward mode and 1 forcing reverse mode. "
196 "Leave unset for (class specific) heuristics."}},
199 "Weighting factor for sparsity pattern calculation calculation."
200 "Overrides default behavior. Set to 0 and 1 to force forward and "
201 "reverse mode respectively. Cf. option \"ad_weight\". "
202 "When set to -1, sparsity is completely ignored and dense matrices are used."}},
208 "Forbid inlining."}},
211 "When requested for a number of forward/reverse directions, "
212 "it may be cheaper to compute first the full jacobian and then "
213 "multiply with seeds, rather than obtain the requested directions "
214 "in a straightforward manner. "
215 "Casadi uses a heuristic to decide which is cheaper. "
216 "A high value of 'jac_penalty' makes it less likely for the heurstic "
217 "to chose the full Jacobian strategy. "
218 "The special value -1 indicates never to use the full Jacobian strategy"}},
221 "A user-defined field that can be used to identify "
222 "the function or pass additional information"}},
225 "Throw exceptions when the numerical values of the inputs don't make sense"}},
228 "Deprecated option (ignored): Statistics are now always collected."}},
231 "Deprecated option (ignored)"}},
234 "Deprecated option (ignored)"}},
237 "Use just-in-time compiler to speed up the evaluation"}},
240 "Cleanup up the temporary source file that jit creates. Default: true"}},
243 "Specify behaviour when serializing a jitted function: SOURCE|link|embed."}},
246 "The file name used to write out code. "
247 "The actual file names used depend on 'jit_temp_suffix' and include extensions. "
248 "Default: 'jit_tmp'"}},
251 "Use a temporary (seemingly random) filename suffix for generated code and libraries. "
252 "This is desired for thread-safety. "
253 "This behaviour may defeat caching compiler wrappers. "
257 "Just-in-time compiler plugin to be used."}},
260 "Options to be passed to the jit compiler."}},
263 "The function is a derivative of another function. "
264 "The type of derivative (directional derivative, Jacobian) "
265 "is inferred from the function name."}},
268 "Specify the maximum number of directions for derivative functions."
269 " Overrules the builtin optimized_num_dir."}},
272 "Enable derivative calculation using generated functions for"
273 " Jacobian-times-vector products - typically using forward mode AD"
274 " - if available. [default: true]"}},
277 "Enable derivative calculation using generated functions for"
278 " transposed Jacobian-times-vector products - typically using reverse mode AD"
279 " - if available. [default: true]"}},
282 "Enable derivative calculation using generated functions for"
283 " Jacobians of all differentiable outputs with respect to all differentiable inputs"
284 " - if available. [default: true]"}},
287 "Enable derivative calculation by finite differencing. [default: false]]"}},
290 "Options to be passed to the finite difference instance"}},
293 "Method for finite differencing [default 'central']"}},
296 "Print numerical values of inputs [default: false]"}},
299 "Print numerical values of outputs [default: false]"}},
302 "When printing numerical matrices, use a format that is "
303 "exact and reproducible in generated C code."}},
306 "Acceptable number of inputs and outputs. Warn if exceeded."}},
309 "Dump numerical values of inputs to file (readable with DM.from_file) [default: false] "
310 "A counter is used to generate unique names. "
311 "The counter may be reset using reset_dump_count."}},
314 "Dump numerical values of outputs to file (readable with DM.from_file) [default: false] "
315 "A counter is used to generate unique names. "
316 "The counter may be reset using reset_dump_count."}},
319 "Dump function to file upon first evaluation. [false]"}},
322 "Directory to dump inputs/outputs to. Make sure the directory exists [.]"}},
325 "Choose file format to dump matrices. See DM.from_file [mtx]"}},
328 "Options to be passed to a forward mode constructor"}},
331 "Options to be passed to a reverse mode constructor"}},
334 "Options to be passed to a Jacobian constructor"}},
337 "Default options to be used to populate forward_options, reverse_options, and "
338 "jacobian_options before those options are merged in."}},
341 "Override CasADi's AD. Use together with 'jac_penalty': 0. "
342 "Note: Highly experimental. Syntax may break often."}},
345 "Indicate for each input if it should be differentiable."}},
348 "Indicate for each output if it should be differentiable."}},
351 "After construction, expand this Function. Default: False"}},
352 {
"post_expand_options",
354 "Options to be passed to post-construction expansion. Default: empty"}},
357 "Prepopulate the function cache. Default: empty"}},
358 {
"external_transform",
360 "List of external_transform instruction arguments. Default: empty"}}
366 for (
auto&& op : opts) {
367 if (op.first==
"verbose") {
369 }
else if (op.first==
"print_time") {
371 }
else if (op.first==
"record_time") {
373 }
else if (op.first==
"regularity_check") {
375 }
else if (op.first==
"error_on_fail") {
396 if (target!=
"tmp") opts[
"jit"] =
jit_;
408 if (target==
"clone" || target==
"tmp") {
429 opts[
"dump"] =
dump_;
435 if (option_name ==
"print_in") {
437 }
else if (option_name ==
"print_out") {
439 }
else if (option_name ==
"print_canonical") {
441 }
else if (option_name==
"ad_weight") {
443 }
else if (option_name==
"ad_weight_sp") {
445 }
else if (option_name==
"dump") {
446 dump_ = option_value;
447 }
else if (option_name==
"dump_in") {
449 }
else if (option_name==
"dump_out") {
451 }
else if (option_name==
"dump_dir") {
453 }
else if (option_name==
"dump_format") {
473 for (
auto&& op : opts) {
474 if (op.first==
"jac_penalty") {
476 }
else if (op.first==
"user_data") {
478 }
else if (op.first==
"inputs_check") {
480 }
else if (op.first==
"gather_stats") {
481 casadi_warning(
"Deprecated option \"gather_stats\": Always enabled");
482 }
else if (op.first==
"input_scheme") {
483 casadi_warning(
"Deprecated option: \"input_scheme\" set via constructor");
484 }
else if (op.first==
"output_scheme") {
485 casadi_warning(
"Deprecated option: \"output_scheme\" set via constructor");
486 }
else if (op.first==
"jit") {
488 }
else if (op.first==
"jit_cleanup") {
490 }
else if (op.first==
"jit_serialize") {
493 "jit_serialize option not understood. Pick one of source, link, embed.");
494 }
else if (op.first==
"compiler") {
496 }
else if (op.first==
"jit_options") {
498 }
else if (op.first==
"jit_name") {
500 }
else if (op.first==
"jit_temp_suffix") {
502 }
else if (op.first==
"derivative_of") {
504 }
else if (op.first==
"ad_weight") {
506 }
else if (op.first==
"ad_weight_sp") {
508 }
else if (op.first==
"max_num_dir") {
510 }
else if (op.first==
"enable_forward") {
512 }
else if (op.first==
"enable_reverse") {
514 }
else if (op.first==
"enable_jacobian") {
516 }
else if (op.first==
"enable_fd") {
518 }
else if (op.first==
"fd_options") {
520 }
else if (op.first==
"fd_method") {
522 }
else if (op.first==
"print_in") {
524 }
else if (op.first==
"print_out") {
526 }
else if (op.first==
"print_canonical") {
528 }
else if (op.first==
"max_io") {
530 }
else if (op.first==
"dump_in") {
532 }
else if (op.first==
"dump_out") {
534 }
else if (op.first==
"dump") {
536 }
else if (op.first==
"dump_dir") {
538 }
else if (op.first==
"dump_format") {
540 }
else if (op.first==
"forward_options") {
542 }
else if (op.first==
"reverse_options") {
544 }
else if (op.first==
"jacobian_options") {
546 }
else if (op.first==
"der_options") {
548 }
else if (op.first==
"custom_jacobian") {
551 "Inconsistent naming of custom Jacobian, expected: jac_" +
name_);
553 }
else if (op.first==
"always_inline") {
555 }
else if (op.first==
"never_inline") {
557 }
else if (op.first==
"is_diff_in") {
559 }
else if (op.first==
"is_diff_out") {
561 }
else if (op.first==
"cache") {
575 casadi_warning(
"Function " +
name_ +
" has many inputs (" +
str(
n_in_) +
" > "
577 +
"Changing the problem formulation is strongly encouraged.");
583 casadi_warning(
"Function " +
name_ +
" has many outputs (" +
str(
n_out_) +
" > "
585 +
"Changing the problem formulation is strongly encouraged.");
594 +
" inputs, but is_diff_in has length " +
str(
is_diff_in_.size()) +
".");
603 +
" outputs, but is_diff_out has length " +
str(
is_diff_out_.size()) +
".");
612 +
" inputs, but sparsity_in has length " +
str(
sparsity_in_.size()) +
".");
621 +
" outputs, but sparsity_out has length " +
str(
sparsity_out_.size()) +
".");
630 +
" inputs, but name_in has length " +
str(
name_in_.size()) +
".");
639 +
" outputs, but name_out has length " +
str(
name_out_.size()) +
".");
645 if (c.first != f.
name()) {
646 casadi_warning(
"Cannot add '" + c.first +
"' a.k.a. '" + f.
name()
647 +
"' to cache. Mismatching names not implemented.");
654 sz_arg_per_ +=
n_in_;
670 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
691 if (
name_ ==
"jac_" + n) {
695 }
else if (
name_ ==
"adj1_" + n) {
713 if (
verbose_) casadi_message(
"Codegenerating function '" +
name_ +
"'.");
717 opts[
"prefix"] =
"jit";
720 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"'..");
723 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"' done.");
729 casadi_assert(
eval_!=
nullptr,
"Cannot load JIT'ed function.");
746 casadi_assert_dev(mem==0);
752 std::ostream& of = *of_ptr;
756 for (casadi_int i=0; i<
n_in_; ++i) {
757 const double* v = arg[i];
758 for (casadi_int k=0;k<
nnz_in(i);++k) {
768 std::ostream& of = *of_ptr;
772 for (casadi_int i=0; i<
n_out_; ++i) {
773 const double* v = res[i];
774 for (casadi_int k=0;k<
nnz_out(i);++k) {
775 normalized_out(of, v ? v[k] : std::numeric_limits<double>::quiet_NaN());
781 void FunctionInternal::dump_in(casadi_int
id,
const double** arg)
const {
782 std::stringstream ss;
783 ss << std::setfill(
'0') << std::setw(6) << id;
784 std::string count = ss.str();
785 for (casadi_int i=0;i<
n_in_;++i) {
790 uout() <<
"dump_in -> " << name << std::endl;
794 void FunctionInternal::dump_out(casadi_int
id,
double** res)
const {
795 std::stringstream ss;
796 ss << std::setfill(
'0') << std::setw(6) << id;
797 std::string count = ss.str();
798 for (casadi_int i=0;i<
n_out_;++i) {
805 void FunctionInternal::dump()
const {
809 casadi_int FunctionInternal::get_dump_id()
const {
817 m->t_total = &m->fstats.at(
"total");
819 m->t_total =
nullptr;
825 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
826 for (casadi_int i=0; i<
n_in_; ++i) {
827 stream <<
"Input " << i <<
" (" <<
name_in_[i] <<
"): ";
836 stream <<
"NULL" << std::endl;
842 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
843 for (casadi_int i=0; i<
n_out_; ++i) {
844 stream <<
"Output " << i <<
" (" <<
name_out_[i] <<
"): ";
853 stream <<
"NULL" << std::endl;
863 for (casadi_int i=0; i<sz; ++i) {
864 if (i>0) stream <<
", ";
874 const Sparsity& sp,
const double* nz) {
879 stream << sp.
dim(
false) <<
": ";
882 for (casadi_int i=0; i<sp.
nnz(); ++i) {
883 if (i>0) stream <<
", ";
889 stream <<
", colind: [";
890 for (casadi_int i=0; i<sp.
size2(); ++i) {
891 if (i>0) stream <<
", ";
895 stream <<
", row: [";
896 for (casadi_int i=0; i<sp.
nnz(); ++i) {
897 if (i>0) stream <<
", ";
898 stream << sp.
row()[i];
915 eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
916 bool always_inline,
bool never_inline)
const {
918 if (
dump_in_) dump_in(dump_id, arg);
919 if (
dump_ && dump_id==0) dump();
924 for (casadi_int i=0;i<
n_in_;++i) {
925 casadi_assert(arg[i]==0 || arg[i]+
nnz_in(i)<=w || arg[i]>=w+
sz_w(),
926 "Memory corruption detected for input " +
name_in_[i] +
".\n"+
928 " intersects with w " +
str(w)+
"-"+
str(w+
sz_w())+
".");
930 for (casadi_int i=0;i<
n_out_;++i) {
931 casadi_assert(res[i]==0 || res[i]+
nnz_out(i)<=w || res[i]>=w+
sz_w(),
932 "Memory corruption detected for output " +
name_out_[i]);
935 for (
auto&& s : m->fstats) s.second.reset();
936 if (m->t_total) m->t_total->tic();
943 #ifdef CASADI_WITH_THREAD
944 std::lock_guard<std::mutex> lock(mtx_);
948 ret =
eval_(arg, res, iw, w, mem_);
950 #ifdef CASADI_WITH_THREAD
951 std::lock_guard<std::mutex> lock(mtx_);
956 ret =
eval(arg, res, iw, w, mem);
958 if (m->t_total) m->t_total->toc();
966 for (casadi_int i = 0; i <
n_out_; ++i) {
968 if (!res[i])
continue;
970 casadi_int nnz = this->
nnz_out(i);
971 for (casadi_int nz = 0; nz < nnz; ++nz) {
972 if (isnan(res[i][nz]) || isinf(res[i][nz])) {
974 casadi_error(
str(res[i][nz]) +
" detected for output " +
name_out_[i] +
" at "
984 stream <<
" Number of inputs: " <<
n_in_ << std::endl;
985 for (casadi_int i=0; i<
n_in_; ++i) {
986 stream <<
" Input " << i <<
" (\"" <<
name_in_[i] <<
"\"): "
989 stream <<
" Number of outputs: " <<
n_out_ << std::endl;
990 for (casadi_int i=0; i<
n_out_; ++i) {
991 stream <<
" Output " << i <<
" (\"" <<
name_out_[i] <<
"\"): "
1010 if (option_name ==
"verbose") {
1012 }
else if (option_name ==
"regularity_check") {
1016 casadi_error(
"Option '" + option_name +
"' cannot be changed");
1022 return std::vector<std::string>();
1026 std::stringstream s;
1031 for (casadi_int i=0; i<
n_in_; ++i) {
1037 for (casadi_int i=0; i<
n_out_; ++i) {
1049 stream << std::endl;
1059 std::vector<std::string> keys;
1060 std::vector<Function> entries;
1061 cache_.cache(keys, entries);
1063 for (
size_t i=0; i<keys.size(); ++i) {
1065 std::string s = keys[i];
1066 casadi_assert_dev(s.size() > 0);
1068 std::replace(s.begin(), s.end(),
':',
'_');
1070 if (s.back() ==
'_') s.resize(s.size() - 1);
1072 ret[s] = entries[i];
1079 const std::string& suffix)
const {
1080 return cache_.incache(fname +
":" + suffix, f);
1088 cache_.tocache_if_missing(f.
name() +
":" + suffix, f);
1093 if (parallelization==
"serial") {
1095 std::string fname =
"map" +
str(n) +
"_" +
name_;
1099 casadi_assert_dev(f.
name()==fname);
1111 if (opts.empty())
return shared_from_this<Function>();
1112 std::string fname =
"wrap_" +
name_;
1114 Dict my_opts = opts;
1116 if (my_opts.find(
"ad_weight")==my_opts.end())
1118 if (my_opts.find(
"ad_weight_sp")==my_opts.end())
1120 if (my_opts.find(
"max_num_dir")==my_opts.end())
1123 std::vector<MX> arg =
mx_in();
1124 std::vector<MX> res =
self()(arg);
1130 std::string fname =
"wrap_" +
name_;
1141 std::vector<MX> arg =
mx_in();
1142 std::vector<MX> res =
self()(arg);
1157 for (casadi_int i=begin; i<end; ++i) {
1158 s[i] ^= (
bvec_t(1) << j);
1163 for (casadi_int i=begin; i<end; ++i) {
1171 for (casadi_int i=begin; i<end; ++i) r |= s[i];
1176 template<
bool fwd>
struct JacSparsityTraits {};
1177 template<>
struct JacSparsityTraits<true> {
1178 typedef const bvec_t* arg_t;
1179 static inline void sp(
const FunctionInternal *f,
1181 casadi_int* iw,
bvec_t* w,
void* mem) {
1182 std::vector<const bvec_t*> argm(f->sz_arg(),
nullptr);
1183 std::vector<bvec_t> wm(f->nnz_in(),
bvec_t(0));
1186 for (casadi_int i=0;i<f->n_in_;++i) {
1187 if (f->is_diff_in_[i]) {
1190 argm[i] = arg[i] ? wp :
nullptr;
1194 f->sp_forward(
get_ptr(argm), res, iw, w, mem);
1195 for (casadi_int i=0;i<f->n_out_;++i) {
1196 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1200 template<>
struct JacSparsityTraits<false> {
1202 static inline void sp(
const FunctionInternal *f,
1204 casadi_int* iw,
bvec_t* w,
void* mem) {
1205 for (casadi_int i=0;i<f->n_out_;++i) {
1206 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1208 f->sp_reverse(arg, res, iw, w, mem);
1209 for (casadi_int i=0;i<f->n_in_;++i) {
1210 if (!f->is_diff_in_[i] && arg[i])
casadi_clear(arg[i], f->nnz_in(i));
1222 std::vector<typename JacSparsityTraits<fwd>::arg_t> arg(
sz_arg(),
nullptr);
1223 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1224 std::vector<casadi_int> iw(
sz_iw());
1225 std::vector<bvec_t> w(
sz_w(), 0);
1228 std::vector<bvec_t> seed(
nz_in, 0);
1230 std::vector<bvec_t> sens(
nz_out, 0);
1232 if (!fwd) std::swap(seed, sens);
1235 casadi_int nsweep = seed.size() /
bvec_size;
1240 casadi_message(
str(nsweep) + std::string(fwd ?
" forward" :
" reverse") +
" sweeps "
1241 "needed for " +
str(seed.size()) +
" directions");
1245 casadi_int progress = -10;
1248 std::vector<casadi_int> jcol, jrow;
1251 for (casadi_int s=0; s<nsweep; ++s) {
1255 casadi_int progress_new = (s*100)/nsweep;
1257 if (progress_new / 10 > progress / 10) {
1258 progress = progress_new;
1259 casadi_message(
str(progress) +
" %");
1267 casadi_int ndir_local = seed.size()-offset;
1268 ndir_local = std::min(
static_cast<casadi_int
>(
bvec_size), ndir_local);
1270 for (casadi_int i=0; i<ndir_local; ++i) {
1271 seed[offset+i] |=
bvec_t(1)<<i;
1279 for (casadi_int el=0; el<sens.size(); ++el) {
1282 bvec_t spsens = sens[el];
1293 for (casadi_int i=0; i<ndir_local; ++i) {
1296 if ((
bvec_t(1) << i) & spsens) {
1299 jrow.push_back(i+offset);
1306 for (casadi_int i=0; i<ndir_local; ++i) {
1312 if (!fwd) swap(jrow, jcol);
1315 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(ret.
size()) +
", "
1322 casadi_int iind)
const {
1326 casadi_int nz =
nnz_in(iind);
1327 casadi_assert_dev(nz==
nnz_out(oind));
1330 std::vector<const bvec_t*> arg(
sz_arg(),
nullptr);
1331 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1332 std::vector<casadi_int> iw(
sz_iw());
1333 std::vector<bvec_t> w(
sz_w());
1336 std::vector<bvec_t> seed(nz, 0);
1340 std::vector<bvec_t> sens(nz, 0);
1344 std::vector<casadi_int> jcol, jrow;
1347 std::vector<casadi_int> coarse(2, 0); coarse[1] = nz;
1350 std::vector<casadi_int> fine;
1358 casadi_int granularity = nz;
1360 casadi_int nsweeps = 0;
1362 bool hasrun =
false;
1364 while (!hasrun || coarse.size()!=nz+1) {
1365 if (
verbose_) casadi_message(
"Block size: " +
str(granularity));
1377 casadi_message(
"Star coloring on " +
str(r.
dim()) +
": "
1378 +
str(
D.size2()) +
" <-> " +
str(
D.size1()));
1382 std::fill(seed.begin(), seed.end(), 0);
1385 for (casadi_int k=0; k<coarse.size()-1; ++k) {
1386 casadi_int
diff = coarse[k+1]-coarse[k];
1387 casadi_int new_diff =
diff/subdivision;
1388 if (
diff%subdivision>0) new_diff++;
1389 std::vector<casadi_int> temp =
range(coarse[k], coarse[k+1], new_diff);
1390 fine.insert(fine.end(), temp.begin(), temp.end());
1392 if (fine.back()!=coarse.back()) fine.push_back(coarse.back());
1394 granularity = fine[1] - fine[0];
1397 casadi_int bvec_i = 0;
1400 std::vector<casadi_int> fine_lookup =
lookupvector(fine, nz+1);
1403 std::vector<casadi_int> lookup_col;
1404 std::vector<casadi_int> lookup_row;
1405 std::vector<casadi_int> lookup_value;
1408 casadi_int n_fine_blocks_max = 0;
1409 for (casadi_int i=0;i<coarse.size()-1;++i) {
1410 casadi_int del = fine_lookup[coarse[i+1]]-fine_lookup[coarse[i]];
1411 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1415 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1418 casadi_int fci_offset = 0;
1422 bool f_finished =
false;
1425 while (!f_finished) {
1428 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1429 casadi_int cci =
D.row(k);
1432 casadi_int fci_start = fine_lookup[coarse[cci]];
1433 casadi_int fci_end = fine_lookup[coarse[cci+1]];
1436 casadi_int bvec_i_mod = 0;
1438 casadi_int value = -bvec_i + fci_offset + fci_start;
1443 for (casadi_int fci = fci_offset; fci<std::min(fci_end-fci_start, fci_cap); ++fci) {
1447 for (casadi_int cri=r.
colind(cci);cri<r.
colind(cci+1);++cri) {
1448 lookup_col.push_back(r.
row(cri));
1449 lookup_row.push_back(bvec_i+bvec_i_mod);
1450 lookup_value.push_back(value);
1461 bvec_i += std::min(n_fine_blocks_max, fci_cap);
1471 IM lookup =
IM::triplet(lookup_row, lookup_col, lookup_value,
1474 std::reverse(lookup_col.begin(), lookup_col.end());
1475 std::reverse(lookup_row.begin(), lookup_row.end());
1476 std::reverse(lookup_value.begin(), lookup_value.end());
1480 duplicates = sparsify(duplicates);
1491 for (casadi_int cri=0; cri<coarse.size()-1; ++cri) {
1494 for (casadi_int fri=fine_lookup[coarse[cri]];fri<fine_lookup[coarse[cri+1]];++fri) {
1499 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1500 if (spsens & (
bvec_t(1) << bvec_i)) {
1503 if (ind==-1)
continue;
1504 casadi_int lk = lookup->at(ind);
1506 jrow.push_back(bvec_i+lk);
1507 jcol.push_back(fri);
1508 jrow.push_back(fri);
1509 jcol.push_back(bvec_i+lk);
1517 std::fill(seed.begin(), seed.end(), 0);
1522 lookup_value.clear();
1525 if (n_fine_blocks_max>fci_cap) {
1526 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1548 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1549 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
1564 std::vector<bvec_t> s_in(
nz_in, 0);
1565 std::vector<bvec_t> s_out(
nz_out, 0);
1568 std::vector<const bvec_t*> arg_fwd(
sz_arg(),
nullptr);
1569 std::vector<bvec_t*> arg_adj(
sz_arg(),
nullptr);
1570 arg_fwd[iind] = arg_adj[iind] =
get_ptr(s_in);
1571 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1573 std::vector<casadi_int> iw(
sz_iw());
1574 std::vector<bvec_t> w(
sz_w());
1577 std::vector<casadi_int> jcol, jrow;
1580 std::vector<casadi_int> coarse_col(2, 0); coarse_col[1] =
nz_out;
1582 std::vector<casadi_int> coarse_row(2, 0); coarse_row[1] =
nz_in;
1585 std::vector<casadi_int> fine_col;
1588 std::vector<casadi_int> fine_row;
1596 casadi_int granularity_row =
nz_in;
1597 casadi_int granularity_col =
nz_out;
1599 bool use_fwd =
true;
1601 casadi_int nsweeps = 0;
1603 bool hasrun =
false;
1609 std::vector<bvec_t> bvec_lookup;
1612 bvec_lookup.push_back(
bvec_t(1) << i);
1615 while (!hasrun || coarse_col.size()!=
nz_out+1 || coarse_row.size()!=
nz_in+1) {
1617 casadi_message(
"Block size: " +
str(granularity_col) +
" x " +
str(granularity_row));
1638 casadi_message(
"Coloring on " +
str(r.
dim()) +
" (fwd seeps: " +
str(D1.
size2()) +
1639 " , adj sweeps: " +
str(D2.
size1()) +
")");
1643 double fwd_cost =
static_cast<double>(use_fwd ? granularity_row : granularity_col) *
1644 sp_w*
static_cast<double>(D1.
size2());
1645 double adj_cost =
static_cast<double>(use_fwd ? granularity_col : granularity_row) *
1646 (1-sp_w)*
static_cast<double>(D2.
size2());
1647 use_fwd = fwd_cost <= adj_cost;
1649 casadi_message(std::string(use_fwd ?
"Forward" :
"Reverse") +
" mode chosen "
1650 "(fwd cost: " +
str(fwd_cost) +
", adj cost: " +
str(adj_cost) +
")");
1662 for (casadi_int i=0; i<nz_seed; ++i) seed_v[i]=0;
1669 std::swap(coarse_col, coarse_row);
1670 std::swap(granularity_col, granularity_row);
1675 for (casadi_int k=0;k<coarse_col.size()-1;++k) {
1676 casadi_int
diff = coarse_col[k+1]-coarse_col[k];
1677 casadi_int new_diff =
diff/subdivision;
1678 if (
diff%subdivision>0) new_diff++;
1679 std::vector<casadi_int> temp =
range(coarse_col[k], coarse_col[k+1], new_diff);
1680 fine_col.insert(fine_col.end(), temp.begin(), temp.end());
1683 for (casadi_int k=0;k<coarse_row.size()-1;++k) {
1684 casadi_int
diff = coarse_row[k+1]-coarse_row[k];
1685 casadi_int new_diff =
diff/subdivision;
1686 if (
diff%subdivision>0) new_diff++;
1687 std::vector<casadi_int> temp =
range(coarse_row[k], coarse_row[k+1], new_diff);
1688 fine_row.insert(fine_row.end(), temp.begin(), temp.end());
1690 if (fine_row.back()!=coarse_row.back()) fine_row.push_back(coarse_row.back());
1691 if (fine_col.back()!=coarse_col.back()) fine_col.push_back(coarse_col.back());
1693 granularity_col = fine_col[1] - fine_col[0];
1694 granularity_row = fine_row[1] - fine_row[0];
1697 casadi_int bvec_i = 0;
1700 std::vector<casadi_int> fine_col_lookup =
lookupvector(fine_col, nz_sens+1);
1701 std::vector<casadi_int> fine_row_lookup =
lookupvector(fine_row, nz_seed+1);
1704 std::vector<casadi_int> lookup_col;
1705 std::vector<casadi_int> lookup_row;
1706 std::vector<casadi_int> lookup_value;
1710 casadi_int n_fine_blocks_max = 0;
1711 for (casadi_int i=0;i<coarse_row.size()-1;++i) {
1712 casadi_int del = fine_row_lookup[coarse_row[i+1]]-fine_row_lookup[coarse_row[i]];
1713 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1717 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1719 casadi_int fci_offset = 0;
1723 bool f_finished =
false;
1726 while (!f_finished) {
1729 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1730 casadi_int cci =
D.row(k);
1733 casadi_int fci_start = fine_row_lookup[coarse_row[cci]];
1734 casadi_int fci_end = fine_row_lookup[coarse_row[cci+1]];
1737 casadi_int bvec_i_mod = 0;
1739 casadi_int value = -bvec_i + fci_offset + fci_start;
1742 for (casadi_int fci = fci_offset; fci < std::min(fci_end-fci_start, fci_cap); ++fci) {
1746 for (casadi_int cri=rT.
colind(cci);cri<rT.
colind(cci+1);++cri) {
1747 lookup_col.push_back(rT.
row(cri));
1748 lookup_row.push_back(bvec_i+bvec_i_mod);
1749 lookup_value.push_back(value);
1753 bvec_toggle(seed_v, fine_row[fci+fci_start], fine_row[fci+fci_start+1],
1760 bvec_i+= std::min(n_fine_blocks_max, fci_cap);
1775 JacSparsityTraits<true>::sp(
this,
get_ptr(arg_fwd),
get_ptr(res),
1778 std::fill(w.begin(), w.end(), 0);
1779 JacSparsityTraits<false>::sp(
this,
get_ptr(arg_adj),
get_ptr(res),
1787 for (casadi_int cri=0;cri<coarse_col.size()-1;++cri) {
1790 for (casadi_int fri=fine_col_lookup[coarse_col[cri]];
1791 fri<fine_col_lookup[coarse_col[cri+1]];++fri) {
1793 bvec_or(sens_v, spsens, fine_col[fri], fine_col[fri+1]);
1796 if (!spsens)
continue;
1799 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1800 if (spsens & bvec_lookup[bvec_i]) {
1803 if (ind==-1)
continue;
1804 jrow.push_back(bvec_i+lookup->at(ind));
1805 jcol.push_back(fri);
1812 std::fill(s_in.begin(), s_in.end(), 0);
1815 std::fill(s_out.begin(), s_out.end(), 0);
1820 lookup_value.clear();
1823 if (n_fine_blocks_max>fci_cap) {
1824 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1839 coarse_col = fine_col;
1840 coarse_row = fine_row;
1844 coarse_col = fine_row;
1845 coarse_row = fine_col;
1850 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1851 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
", " +
1863 if (
name_ ==
"adj1_" + n) {
1864 if (iind == oind)
return true;
1872 bool symmetric)
const {
1875 "Symmetry exploitation in Jacobian assumes dense expression. "
1876 "A potential workaround is to apply densify().");
1908 if (w*
static_cast<double>(nsweep_fwd) <= (1-w)*
static_cast<double>(nsweep_adj)) {
1909 sp = get_jac_sparsity_gen<true>(oind, iind);
1911 sp = get_jac_sparsity_gen<false>(oind, iind);
1924 std::vector<casadi_int> mapping;
1947 bool symmetric)
const {
1948 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
1950 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
1953 for (
bool c : {
false,
true}) {
1957 casadi_int ind = iind + oind *
n_in_;
1973 sp_is_compact =
true;
1985 if (sp_is_compact == compact) {
2012 bool compact,
bool symmetric,
2013 bool allow_forward,
bool allow_reverse)
const {
2015 casadi_assert(allow_forward || allow_reverse,
"Inconsistent options");
2024 casadi_assert_dev(allow_forward);
2027 if (
verbose_) casadi_message(
"FunctionInternal::getPartition star_coloring");
2030 casadi_message(
"Star coloring completed: " +
str(D1.
size2())
2031 +
" directional derivatives needed ("
2032 +
str(A.
size1()) +
" without coloring).");
2041 if (w==1) allow_forward =
false;
2042 if (w==0) allow_reverse =
false;
2043 casadi_assert(allow_forward || allow_reverse,
"Conflicting ad weights");
2046 double best_coloring = std::numeric_limits<double>::infinity();
2049 bool test_fwd_first = allow_forward && w*
static_cast<double>(A.
size1()) <=
2050 (1-w)*
static_cast<double>(A.
size2());
2051 casadi_int mode_fwd = test_fwd_first ? 0 : 1;
2054 for (casadi_int mode=0; mode<2; ++mode) {
2056 bool fwd = mode==mode_fwd;
2059 if (!allow_forward && fwd)
continue;
2060 if (!allow_reverse && !fwd)
continue;
2064 if (
verbose_) casadi_message(
"Unidirectional coloring (forward mode)");
2065 bool d = best_coloring>=w*
static_cast<double>(A.
size1());
2066 casadi_int max_colorings_to_test =
2067 d ? A.
size1() :
static_cast<casadi_int
>(floor(best_coloring/w));
2071 casadi_message(
"Forward mode coloring interrupted (more than "
2072 +
str(max_colorings_to_test) +
" needed).");
2076 casadi_message(
"Forward mode coloring completed: "
2077 +
str(D1.
size2()) +
" directional derivatives needed ("
2078 +
str(A.
size1()) +
" without coloring).");
2081 best_coloring = w*
static_cast<double>(D1.
size2());
2084 if (
verbose_) casadi_message(
"Unidirectional coloring (adjoint mode)");
2085 bool d = best_coloring>=(1-w)*
static_cast<double>(A.
size2());
2086 casadi_int max_colorings_to_test =
2087 d ? A.
size2() :
static_cast<casadi_int
>(floor(best_coloring/(1-w)));
2092 casadi_message(
"Adjoint mode coloring interrupted (more than "
2093 +
str(max_colorings_to_test) +
" needed).");
2097 casadi_message(
"Adjoint mode coloring completed: "
2098 +
str(D2.
size2()) +
" directional derivatives needed ("
2099 +
str(A.
size2()) +
" without coloring).");
2102 best_coloring = (1-w)*
static_cast<double>(D2.
size2());
2111 casadi_error(
"'eval_dm' not defined for " +
class_name());
2116 bool always_inline,
bool never_inline)
const {
2121 casadi_assert(!always_inline,
"'eval_sx' not defined for " +
class_name() +
2122 " in combination with always_inline true");
2129 casadi_int highest_index = 0;
2132 for (
const std::string& n : name_io) {
2134 size_t end = n.find(
'_');
2135 if (end >= n.size())
continue;
2137 if (end < prefix.size())
continue;
2139 if (n.compare(0, prefix.size(), prefix) != 0)
continue;
2141 size_t begin = prefix.size();
2143 casadi_int this_index;
2149 this_index = std::stoi(n.substr(begin, end - begin));
2152 if (this_index > highest_index) highest_index = this_index;
2156 if (highest_index == 0) {
2157 return prefix +
"_";
2159 return prefix + std::to_string(highest_index + 1) +
"_";
2164 casadi_assert_dev(nfwd>=0);
2179 std::vector<std::string> inames;
2182 for (i=0; i<
n_in_; ++i) inames.push_back(pref +
name_in_[i]);
2184 std::vector<std::string> onames;
2190 opts[
"derivative_of"] =
self();
2194 f =
get_forward(nfwd, fname, inames, onames, opts);
2206 casadi_error(
"Unknown 'fd_method': " +
fd_method_);
2225 casadi_assert_dev(nadj>=0);
2240 std::vector<std::string> inames;
2245 std::vector<std::string> onames;
2246 for (casadi_int i=0; i<
n_in_; ++i) onames.push_back(pref +
name_in_[i]);
2250 opts[
"derivative_of"] =
self();
2253 f =
get_reverse(nadj, fname, inames, onames, opts);
2270 get_forward(casadi_int nfwd,
const std::string& name,
2271 const std::vector<std::string>& inames,
2272 const std::vector<std::string>& onames,
2273 const Dict& opts)
const {
2274 casadi_error(
"'get_forward' not defined for " +
class_name());
2278 get_reverse(casadi_int nadj,
const std::string& name,
2279 const std::vector<std::string>& inames,
2280 const std::vector<std::string>& onames,
2281 const Dict& opts)
const {
2282 casadi_error(
"'get_reverse' not defined for " +
class_name());
2286 const Dict& options)
const {
2287 casadi_error(
"'export_code' not defined for " +
class_name());
2291 casadi_int n = s.size();
2293 std::stringstream ss;
2294 for (casadi_int i=0;i<n;++i) {
2298 casadi_assert_dev(s==ss.str());
2303 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
nnz_in(iind);
2309 for (casadi_int oind=0; oind<
n_out_; ++oind) ret +=
nnz_out(oind);
2315 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
numel_in(iind);
2326 bool always_inline,
bool never_inline)
const {
2332 if (always_inline) {
2333 casadi_assert(!never_inline,
"Inconsistent options for " +
str(
name_));
2334 return wrap().
call(arg, res,
true);
2346 "Derivatives cannot be calculated for " +
name_);
2351 std::string fname =
"jac_" +
name_;
2354 std::vector<std::string> inames;
2355 for (casadi_int i=0; i<
n_in_; ++i) inames.push_back(
name_in_[i]);
2356 for (casadi_int i=0; i<
n_out_; ++i) inames.push_back(
"out_" +
name_out_[i]);
2358 std::vector<std::string> onames;
2360 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2361 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2367 opts[
"derivative_of"] =
self();
2372 casadi_assert(f.
n_in() == inames.size(),
2373 "Mismatching input signature, expected " +
str(inames));
2374 casadi_assert(f.
n_out() == onames.size(),
2375 "Mismatching output signature, expected " +
str(onames));
2384 const std::vector<std::string>& inames,
2385 const std::vector<std::string>& onames,
2386 const Dict& opts)
const {
2387 casadi_error(
"'get_jacobian' not defined for " +
class_name());
2393 g <<
"static " <<
signature(fname) <<
" {\n";
2414 return "int " + fname +
"(const casadi_real** arg, casadi_real** res, "
2415 "casadi_int* iw, casadi_real* w, int mem)";
2419 std::vector<std::string> args;
2421 args.push_back(
"const casadi_real* " +
str(e));
2424 args.push_back(
"casadi_real* " +
str(e));
2426 args.push_back(
"const casadi_real** arg");
2427 args.push_back(
"casadi_real** res");
2428 args.push_back(
"casadi_int* iw");
2429 args.push_back(
"casadi_real* w");
2430 args.push_back(
"int mem");
2431 return "int " + fname +
"_unrolled(" +
join(args,
", ") +
")";
2442 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2443 g <<
"return " + mem_counter +
"++;\n";
2449 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2450 std::string stack = g.
shorthand(name +
"_unused_stack");
2451 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2452 std::string mem_array = g.
shorthand(name +
"_mem");
2456 g.
auxiliaries <<
"static int " << mem_counter <<
" = 0;\n";
2457 g.
auxiliaries <<
"static int " << stack_counter <<
" = -1;\n";
2458 g.
auxiliaries <<
"static int " << stack <<
"[CASADI_MAX_NUM_THREADS];\n";
2460 " " << mem_array <<
"[CASADI_MAX_NUM_THREADS];\n\n";
2462 g <<
"if (" << stack_counter <<
">=0) {\n";
2463 g <<
"return " << stack <<
"[" << stack_counter <<
"--];\n";
2465 g <<
"if (" << mem_counter <<
"==CASADI_MAX_NUM_THREADS) return -1;\n";
2467 g <<
"if (mid<0) return -1;\n";
2468 g <<
"if(" <<
init_mem <<
"(mid)) return -1;\n";
2469 g <<
"return mid;\n";
2475 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2476 std::string stack = g.
shorthand(name +
"_unused_stack");
2477 g << stack <<
"[++" << stack_counter <<
"] = mem;\n";
2487 g << g.
declare(
"int " +
name_ +
"_alloc_mem(void)") <<
" {\n";
2489 g <<
"return " <<
codegen_name(g) <<
"_alloc_mem();\n";
2495 g << g.
declare(
"int " +
name_ +
"_init_mem(int mem)") <<
" {\n";
2497 g <<
"return " <<
codegen_name(g) <<
"_init_mem(mem);\n";
2503 g << g.
declare(
"void " +
name_ +
"_free_mem(int mem)") <<
" {\n";
2510 g << g.
declare(
"int " +
name_ +
"_checkout(void)") <<
" {\n";
2519 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2522 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2527 g << g.
declare(
"void " +
name_ +
"_incref(void)") <<
" {\n";
2530 << g.
declare(
"void " +
name_ +
"_decref(void)") <<
" {\n";
2536 <<
" { return " <<
n_in_ <<
";}\n\n"
2538 <<
" { return " <<
n_out_ <<
";}\n\n";
2541 g << g.
declare(
"casadi_real " +
name_ +
"_default_in(casadi_int i)") <<
" {\n"
2542 <<
"switch (i) {\n";
2543 for (casadi_int i=0; i<
n_in_; ++i) {
2545 if (def!=0) g <<
"case " << i <<
": return " << g.
constant(def) <<
";\n";
2547 g <<
"default: return 0;\n}\n"
2551 g << g.
declare(
"const char* " +
name_ +
"_name_in(casadi_int i)") <<
" {\n"
2552 <<
"switch (i) {\n";
2553 for (casadi_int i=0; i<
n_in_; ++i) {
2554 g <<
"case " << i <<
": return \"" <<
name_in_[i] <<
"\";\n";
2556 g <<
"default: return 0;\n}\n"
2560 g << g.
declare(
"const char* " +
name_ +
"_name_out(casadi_int i)") <<
" {\n"
2561 <<
"switch (i) {\n";
2562 for (casadi_int i=0; i<
n_out_; ++i) {
2563 g <<
"case " << i <<
": return \"" <<
name_out_[i] <<
"\";\n";
2565 g <<
"default: return 0;\n}\n"
2573 "int " +
name_ +
"_work(casadi_int *sz_arg, casadi_int* sz_res, "
2574 "casadi_int *sz_iw, casadi_int *sz_w)")
2585 "int " +
name_ +
"_work_bytes(casadi_int *sz_arg, casadi_int* sz_res, "
2586 "casadi_int *sz_iw, casadi_int *sz_w)")
2588 <<
"if (sz_arg) *sz_arg = " <<
codegen_sz_arg(g) <<
"*sizeof(const casadi_real*);\n"
2589 <<
"if (sz_res) *sz_res = " <<
codegen_sz_res(g) <<
"*sizeof(casadi_real*);\n"
2590 <<
"if (sz_iw) *sz_iw = " <<
codegen_sz_iw(g) <<
"*sizeof(casadi_int);\n"
2591 <<
"if (sz_w) *sz_w = " <<
codegen_sz_w(g) <<
"*sizeof(casadi_real);\n"
2606 g << g.
declare(
"int " +
name_ +
"_diff_in(casadi_int i)") <<
" {\n"
2607 <<
"switch (i) {\n";
2608 for (casadi_int i=0; i<
n_in_; ++i) {
2609 g <<
"case " << i <<
": return " <<
is_diff_in_[i] <<
";\n";
2611 g <<
"default: return -1;\n}\n"
2617 g << g.
declare(
"int " +
name_ +
"_diff_out(casadi_int i)") <<
" {\n"
2618 <<
"switch (i) {\n";
2619 for (casadi_int i=0; i<
n_out_; ++i) {
2620 g <<
"case " << i <<
": return " <<
is_diff_out_[i] <<
";\n";
2622 g <<
"default: return -1;\n}\n"
2629 g <<
"#ifdef MATLAB_MEX_FILE\n";
2632 g <<
"void mex_" <<
name_
2633 <<
"(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {\n"
2634 <<
"casadi_int i;\n";
2639 for (casadi_int i=0; i<
n_in_; ++i) {
2644 sz_w += i_nnz + o_nnz;
2647 std::string fw =
"w+" +
str(i_nnz + o_nnz);
2650 casadi_int offset=0;
2654 g <<
"casadi_real* res[" <<
sz_res() <<
"] = {0};\n";
2657 g <<
"if (argc>" <<
n_in_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2658 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. Too many input arguments "
2659 <<
"(%d, max " <<
n_in_ <<
")\", argc);\n";
2661 g <<
"if (resc>" <<
n_out_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2662 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. "
2663 <<
"Too many output arguments (%d, max " <<
n_out_ <<
")\", resc);\n";
2665 for (casadi_int i=0; i<
n_in_; ++i) {
2666 std::string p =
"argv[" +
str(i) +
"]";
2667 g <<
"if (--argc>=0) arg[" << i <<
"] = "
2672 for (casadi_int i=0; i<
n_out_; ++i) {
2678 g <<
"if (--resc>=0) ";
2681 g << g.
res(i) <<
" = w+" <<
str(offset) <<
";\n";
2684 g <<
name_ <<
"_incref();\n";
2685 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2688 g <<
"i = " <<
name_ <<
"(arg, res, iw, " << fw <<
", mem);\n"
2689 <<
"if (i) mexErrMsgIdAndTxt(\"Casadi:RuntimeError\",\"Evaluation of \\\"" <<
name_
2690 <<
"\\\" failed.\");\n";
2691 g <<
name_ <<
"_release(mem);\n";
2692 g <<
name_ <<
"_decref();\n";
2695 for (casadi_int i=0; i<
n_out_; ++i) {
2696 g <<
"if (" << g.
res(i) <<
") resv[" << i <<
"] = "
2707 g <<
"casadi_int main_" <<
name_ <<
"(casadi_int argc, char* argv[]) {\n";
2709 g <<
"casadi_int j;\n";
2710 g <<
"casadi_real* a;\n";
2711 g <<
"const casadi_real* r;\n";
2712 g <<
"casadi_int flag;\n";
2713 if (needs_mem) g <<
"int mem;\n";
2723 g <<
"const casadi_real* arg[" <<
sz_arg() <<
"];\n";
2726 g <<
"casadi_real* res[" <<
sz_res() <<
"];\n";
2729 for (casadi_int i=0; i<
n_in_; ++i) {
2730 g <<
"arg[" << i <<
"] = w+" << off <<
";\n";
2733 for (casadi_int i=0; i<
n_out_; ++i) {
2734 g <<
"res[" << i <<
"] = w+" << off <<
";\n";
2740 <<
"for (j=0; j<" <<
nnz_in() <<
"; ++j) "
2741 <<
"if (scanf(\"%lg\", a++)<=0) return 2;\n";
2744 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2748 g <<
"flag = " <<
name_ <<
"(arg, res, iw, w+" << off <<
", ";
2756 g <<
name_ <<
"_release(mem);\n";
2758 g <<
"if (flag) return flag;\n";
2761 g <<
"r = w+" <<
nnz_in() <<
";\n"
2762 <<
"for (j=0; j<" <<
nnz_out() <<
"; ++j) "
2763 << g.
printf(
"%g ",
"*r++") <<
"\n";
2766 g << g.
printf(
"\\n") <<
"\n";
2775 g << g.
declare(
"casadi_functions* " +
name_ +
"_functions(void)") <<
" {\n"
2776 <<
"static casadi_functions fun = {\n"
2777 <<
name_ <<
"_incref,\n"
2778 <<
name_ <<
"_decref,\n"
2779 <<
name_ <<
"_checkout,\n"
2780 <<
name_ <<
"_release,\n"
2781 <<
name_ <<
"_default_in,\n"
2785 <<
name_ <<
"_n_in,\n"
2786 <<
name_ <<
"_n_out,\n"
2787 <<
name_ <<
"_name_in,\n"
2788 <<
name_ <<
"_name_out,\n"
2789 <<
name_ <<
"_sparsity_in,\n"
2790 <<
name_ <<
"_sparsity_out,\n"
2791 <<
name_ <<
"_work,\n"
2805 if (e.f.get()==
this)
return e.codegen_name;
2810 if (e.f.get()==
this)
return "f" +
str(i);
2813 casadi_error(
"Function '" +
name_ +
"' not found");
2818 std::string mem_array = g.
shorthand(name +
"_mem");
2819 return mem_array+
"[" + index +
"]";
2827 casadi_warning(
"The function \"" +
name_ +
"\", which is of type \""
2828 +
class_name() +
"\" cannot be code generated. The generation "
2829 "will proceed, but compilation of the code will not be possible.");
2830 g <<
"#error Code generation not supported for " <<
class_name() <<
"\n";
2835 casadi_error(
"'generate_dependencies' not defined for " +
class_name());
2841 for (casadi_int oind=0; oind<
n_out_; ++oind) {
2843 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
2847 for (casadi_int iind=0; iind<
n_in_; ++iind) {
2849 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
2858 casadi_int* iw,
bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const {
2863 casadi_int d1 = sp.
size2();
2864 const casadi_int *colind = sp.
colind(), *row = sp.
row();
2865 for (casadi_int cc=0; cc<d1; ++cc) {
2866 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
2867 res[oind][row[el]] |= arg[iind][cc];
2876 for (casadi_int oind=0; oind<
n_out_; ++oind) {
2878 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
2881 for (casadi_int iind=0; iind<
n_in_; ++iind) {
2883 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
2890 casadi_int d1 = sp.
size2();
2891 const casadi_int *colind = sp.
colind(), *row = sp.
row();
2892 for (casadi_int cc=0; cc<d1; ++cc) {
2893 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
2894 arg[iind][cc] |= res[oind][row[el]];
2906 size_t& sz_iw,
size_t& sz_w)
const {
2909 sz_iw = this->
sz_iw();
2910 sz_w = this->
sz_w();
2930 sz_arg_tmp_ = std::max(sz_arg_tmp_,
sz_arg);
2938 sz_res_tmp_ = std::max(sz_res_tmp_,
sz_res);
2944 sz_iw_per_ +=
sz_iw;
2946 sz_iw_tmp_ = std::max(sz_iw_tmp_,
sz_iw);
2954 sz_w_tmp_ = std::max(sz_w_tmp_,
sz_w);
2972 for (
const auto& s : m->fstats) {
2973 stats[
"n_call_" +s.first] = s.second.n_call;
2974 stats[
"t_wall_" +s.first] = s.second.t_wall;
2975 stats[
"t_proc_" +s.first] = s.second.t_proc;
2983 casadi_assert(m->stats_available,
2984 "No stats available: Function '" +
name_ +
"' not set up. "
2985 "To get statistics, first evaluate it numerically.");
3030 call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3031 const std::vector<std::vector<MX> >& fseed,
3032 std::vector<std::vector<MX> >& fsens,
3033 bool always_inline,
bool never_inline)
const {
3034 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3035 casadi_assert(!always_inline,
"Class " +
class_name() +
3036 " cannot be inlined in an MX expression");
3040 "Derivatives cannot be calculated for " +
name_);
3043 casadi_int nfwd = fseed.size();
3047 if (nfwd==0)
return;
3050 casadi_int npar = 1;
3051 for (
auto&& r : fseed) {
3054 fsens, always_inline, never_inline);
3061 std::vector<MX> darg = arg;
3062 darg.insert(darg.end(), res.begin(), res.end());
3063 std::vector<MX> J =
jacobian()(darg);
3065 std::vector<MX> v(nfwd), all_fseed(
n_in_);
3066 for (
size_t i = 0; i <
n_in_; ++i) {
3067 for (
size_t d = 0; d < nfwd; ++d) v[d] = vec(fseed.at(d).at(i));
3068 all_fseed[i] = horzcat(v);
3071 std::vector<MX> all_fsens(
n_out_);
3072 std::vector<MX>::const_iterator J_it = J.begin();
3073 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3074 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3076 MX a = mtimes(*J_it++, all_fseed[iind]);
3077 all_fsens[oind] = all_fsens[oind].is_empty(
true) ? a : all_fsens[oind] + a;
3081 for (
size_t d = 0; d < nfwd; ++d) fsens[d].resize(
n_out_);
3082 for (
size_t i = 0; i <
n_out_; ++i) {
3083 v = horzsplit(all_fsens[i]);
3084 casadi_assert_dev(v.size() == nfwd);
3085 for (
size_t d = 0; d < nfwd; ++d) fsens[d][i] = reshape(v[d],
size_out(i));
3094 casadi_int offset = 0;
3095 while (offset<nfwd) {
3097 casadi_int nfwd_batch = std::min(nfwd-offset, max_nfwd);
3100 std::vector<MX> darg;
3102 darg.insert(darg.end(), arg.begin(), arg.end());
3103 darg.insert(darg.end(), res.begin(), res.end());
3104 std::vector<MX> v(nfwd_batch);
3105 for (casadi_int i=0; i<
n_in_; ++i) {
3106 for (casadi_int d=0; d<nfwd_batch; ++d) v[d] = fseed[offset+d][i];
3107 darg.push_back(horzcat(v));
3112 std::vector<MX> x = dfcn(darg);
3114 casadi_assert_dev(x.size()==
n_out_);
3117 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d].resize(
n_out_);
3118 for (casadi_int i=0; i<
n_out_; ++i) {
3121 casadi_assert_dev(v.size()==nfwd_batch);
3123 v = std::vector<MX>(nfwd_batch,
MX(
size_out(i)));
3125 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d][i] = v[d];
3129 offset += nfwd_batch;
3135 call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3136 const std::vector<std::vector<MX> >& aseed,
3137 std::vector<std::vector<MX> >& asens,
3138 bool always_inline,
bool never_inline)
const {
3139 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3140 casadi_assert(!always_inline,
"Class " +
class_name() +
3141 " cannot be inlined in an MX expression");
3145 "Derivatives cannot be calculated for " +
name_);
3148 casadi_int nadj = aseed.size();
3152 if (nadj==0)
return;
3155 casadi_int npar = 1;
3156 for (
auto&& r : aseed) {
3159 asens, always_inline, never_inline);
3166 std::vector<MX> darg = arg;
3167 darg.insert(darg.end(), res.begin(), res.end());
3168 std::vector<MX> J =
jacobian()(darg);
3170 std::vector<MX> v(nadj), all_aseed(
n_out_);
3171 for (
size_t i = 0; i <
n_out_; ++i) {
3172 for (
size_t d = 0; d < nadj; ++d) v[d] = vec(aseed.at(d).at(i));
3173 all_aseed[i] = horzcat(v);
3176 std::vector<MX> all_asens(
n_in_);
3177 std::vector<MX>::const_iterator J_it = J.begin();
3178 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3179 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3181 MX a = mtimes((*J_it++).
T(), all_aseed[oind]);
3182 all_asens[iind] = all_asens[iind].is_empty(
true) ? a : all_asens[iind] + a;
3186 for (
size_t d = 0; d < nadj; ++d) asens[d].resize(
n_in_);
3187 for (
size_t i = 0; i <
n_in_; ++i) {
3188 v = horzsplit(all_asens[i]);
3189 casadi_assert_dev(v.size() == nadj);
3190 for (
size_t d = 0; d < nadj; ++d) {
3191 if (asens[d][i].is_empty(
true)) {
3192 asens[d][i] = reshape(v[d],
size_in(i));
3194 asens[d][i] += reshape(v[d],
size_in(i));
3204 casadi_int offset = 0;
3205 while (offset<nadj) {
3207 casadi_int nadj_batch = std::min(nadj-offset, max_nadj);
3210 std::vector<MX> darg;
3212 darg.insert(darg.end(), arg.begin(), arg.end());
3213 darg.insert(darg.end(), res.begin(), res.end());
3214 std::vector<MX> v(nadj_batch);
3215 for (casadi_int i=0; i<
n_out_; ++i) {
3216 for (casadi_int d=0; d<nadj_batch; ++d) v[d] = aseed[offset+d][i];
3217 darg.push_back(horzcat(v));
3222 std::vector<MX> x = dfcn(darg);
3223 casadi_assert_dev(x.size()==
n_in_);
3226 for (casadi_int d=0; d<nadj_batch; ++d) asens[offset+d].resize(
n_in_);
3227 for (casadi_int i=0; i<
n_in_; ++i) {
3230 casadi_assert_dev(v.size()==nadj_batch);
3232 v = std::vector<MX>(nadj_batch,
MX(
size_in(i)));
3234 for (casadi_int d=0; d<nadj_batch; ++d) {
3235 if (asens[offset+d][i].is_empty(
true)) {
3236 asens[offset+d][i] = v[d];
3238 asens[offset+d][i] += v[d];
3243 offset += nadj_batch;
3249 call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3250 const std::vector<std::vector<SX> >& fseed,
3251 std::vector<std::vector<SX> >& fsens,
3252 bool always_inline,
bool never_inline)
const {
3253 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3254 if (fseed.empty()) {
3258 casadi_error(
"'forward' (SX) not defined for " +
class_name());
3262 call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3263 const std::vector<std::vector<SX> >& aseed,
3264 std::vector<std::vector<SX> >& asens,
3265 bool always_inline,
bool never_inline)
const {
3266 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3267 if (aseed.empty()) {
3271 casadi_error(
"'reverse' (SX) not defined for " +
class_name());
3313 std::vector<SX> ret(
n_in_);
3314 for (casadi_int i=0; i<ret.size(); ++i) {
3321 std::vector<SX> ret(
n_out_);
3322 for (casadi_int i=0; i<ret.size(); ++i) {
3329 std::vector<DM> ret(
n_in_);
3330 for (casadi_int i=0; i<ret.size(); ++i) {
3337 std::vector<DM> ret(
n_out_);
3338 for (casadi_int i=0; i<ret.size(); ++i) {
3353 std::vector<MX> ret(
n_in_);
3354 for (casadi_int i=0; i<ret.size(); ++i) {
3361 std::vector<MX> ret(
n_out_);
3362 for (casadi_int i=0; i<ret.size(); ++i) {
3369 return type ==
"FunctionInternal";
3373 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const {
3378 casadi_error(
"'free_mx' only defined for 'MXFunction'");
3382 casadi_error(
"'free_sx' only defined for 'SXFunction'");
3387 casadi_error(
"'generate_lifted' only defined for 'MXFunction'");
3391 casadi_error(
"'n_instructions' not defined for " +
class_name());
3395 casadi_error(
"'instruction_id' not defined for " +
class_name());
3399 casadi_error(
"'instruction_input' not defined for " +
class_name());
3403 casadi_error(
"'instruction_constant' not defined for " +
class_name());
3407 casadi_error(
"'instruction_output' not defined for " +
class_name());
3411 casadi_error(
"'instruction_MX' not defined for " +
class_name());
3415 casadi_error(
"'instructions_sx' not defined for " +
class_name());
3419 casadi_error(
"'n_nodes' not defined for " +
class_name());
3424 const std::string& parallelization) {
3425 if (x.empty())
return x;
3427 casadi_assert(x.size()==
n_in_,
"mapsum_mx: Wrong number_i of arguments");
3429 casadi_int npar = 1;
3431 std::vector<MX> x_mod(x.size());
3432 for (casadi_int i=0; i<
n_in_; ++i) {
3443 for (casadi_int i=0; i<x_mod.size(); ++i) {
3444 n = std::max(x_mod[i].size2() /
size2_in(i), n);
3447 std::vector<casadi_int> reduce_in;
3448 for (casadi_int i=0; i<x_mod.size(); ++i) {
3449 if (x_mod[i].size2()/
size2_in(i)!=n) {
3450 reduce_in.push_back(i);
3462 if (arg.
size()==inp.
size())
return true;
3472 if (npar==-1)
return false;
3484 casadi_assert(
nnz_in()==arg.size(),
3485 "Dimension mismatch. Expecting " +
str(
nnz_in()) +
3486 ", got " +
str(arg.size()) +
" instead.");
3488 std::vector<DM> ret =
dm_in();
3489 casadi_int offset = 0;
3490 for (casadi_int i=0;i<
n_in_;++i) {
3492 std::copy(arg.begin()+offset, arg.begin()+offset+
nnz_in(i), r.
ptr());
3499 casadi_assert(
nnz_out()==res.size(),
3500 "Dimension mismatch. Expecting " +
str(
nnz_out()) +
3501 ", got " +
str(res.size()) +
" instead.");
3503 std::vector<DM> ret =
dm_out();
3504 casadi_int offset = 0;
3505 for (casadi_int i=0;i<
n_out_;++i) {
3507 std::copy(res.begin()+offset, res.begin()+offset+
nnz_out(i), r.
ptr());
3515 casadi_int npar = -1;
3521 std::vector<double> ret(
nnz_in());
3522 casadi_int offset = 0;
3523 for (casadi_int i=0;i<
n_in_;++i) {
3524 const double* e = arg2.at(i).ptr();
3525 std::copy(e, e+
nnz_in(i), ret.begin()+offset);
3533 casadi_int npar = -1;
3539 std::vector<double> ret(
nnz_out());
3540 casadi_int offset = 0;
3541 for (casadi_int i=0;i<
n_out_;++i) {
3542 const double* e = res2.at(i).ptr();
3543 std::copy(e, e+
nnz_out(i), ret.begin()+offset);
3550 casadi_int* iw,
double* w)
const {
3558 for (
auto&& i : mem_) {
3567 if (
name_ ==
"jac_" + n) {
3569 }
else if (
name_ ==
"adj1_" + n) {
3580 if (
name_ ==
"jac_" + n) {
3582 }
else if (
name_ ==
"adj1_" + n) {
3593 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
3614 if (
name_ ==
"jac_" + n) {
3628 std::vector<casadi_int> row, colind;
3629 row.reserve(sp_out.
nnz() * sp_in.
nnz());
3630 colind.reserve(sp_in.
numel() + 1);
3632 for (casadi_int c1 = 0; c1 < sp_in.
size2(); ++c1) {
3633 for (casadi_int k1 = sp_in.
colind(c1); k1 < sp_in.
colind(c1 + 1); ++k1) {
3634 casadi_int e1 = sp_in.
row(k1) + sp_in.
size1() * c1;
3636 colind.resize(e1 + 1, row.size());
3638 for (casadi_int c2 = 0; c2 < sp_out.
size2(); ++c2) {
3639 for (casadi_int k2 = sp_out.
colind(c2); k2 < sp_out.
colind(c2 + 1); ++k2) {
3640 row.push_back(sp_out.
row(k2) + sp_out.
size1() * c2);
3646 colind.resize(sp_in.
numel() + 1, row.size());
3649 }
else if (
name_ ==
"adj1_" + n) {
3659 #ifdef CASADI_WITH_THREAD
3660 std::lock_guard<std::mutex> lock(mtx_);
3662 return mem_.at(ind);
3666 return ind<mem_.size();
3670 #ifdef CASADI_WITH_THREAD
3671 std::lock_guard<std::mutex> lock(mtx_);
3673 if (unused_.empty()) {
3679 casadi_error(
"Failed to create or initialize memory object");
3681 return static_cast<int>(mem_.size()) - 1;
3684 int m = unused_.top();
3691 #ifdef CASADI_WITH_THREAD
3692 std::lock_guard<std::mutex> lock(mtx_);
3698 factory(
const std::string& name,
3699 const std::vector<std::string>& s_in,
3700 const std::vector<std::string>& s_out,
3702 const Dict& opts)
const {
3703 return wrap().
factory(name, s_in, s_out, aux, opts);
3708 return std::vector<std::string>();
3712 casadi_error(
"'get_function' not defined for " +
class_name());
3718 const Function& dep, casadi_int max_depth)
const {
3720 if (!dep.
is_null() && all_fun.find(dep.
get()) == all_fun.end()) {
3722 all_fun[dep.
get()] = dep;
3724 if (max_depth > 0) dep->
find(all_fun, max_depth - 1);
3729 which_depends(
const std::string& s_in,
const std::vector<std::string>& s_out,
3730 casadi_int order,
bool tr)
const {
3731 Function f = shared_from_this<Function>();
3737 casadi_error(
"'oracle' not defined for " +
class_name());
3743 const std::vector<casadi_int>& order_in,
3744 const std::vector<casadi_int>& order_out,
const Dict& opts)
const {
3745 return wrap().
slice(name, order_in, order_out, opts);
3750 for (casadi_int i=0; i<
n_in_; ++i) {
3754 for (casadi_int i=0; i<
n_out_; ++i) {
3762 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3764 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
3766 casadi_int ind = iind + oind *
n_in_;
3774 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
3779 std::vector<DM> argv(
n_in_);
3780 for (casadi_int i=0; i<
n_in_; ++i) {
3782 casadi_copy(arg[i], argv[i].nnz(), argv[i].ptr());
3786 std::vector<DM> resv =
eval_dm(argv);
3789 casadi_assert(resv.size()==
n_out_,
3790 "Expected " +
str(
n_out_) +
" outputs, got " +
str(resv.size()) +
".");
3793 for (casadi_int i=0; i<
n_out_; ++i) {
3798 casadi_error(
"Shape mismatch for output " +
str(i) +
": got " + resv[i].dim() +
", "
3802 if (res[i])
casadi_copy(resv[i].ptr(), resv[i].nnz(), res[i]);
3806 }
catch(std::exception& e) {
3807 casadi_error(
"Failed to evaluate 'eval_dm' for " +
name_ +
":\n" + e.what());
3812 casadi_error(
"'eval' not defined for " +
class_name());
3821 for (
auto &&s : fstats) {
3822 name_len = std::max(s.first.size(), name_len);
3824 name_len = std::max(
name_.size(), name_len);
3828 sprint(namefmt,
sizeof(namefmt),
"%%%ds ",
static_cast<casadi_int
>(name_len));
3833 print(
" : %8s %10s %8s %10s %9s\n",
"t_proc",
"(avg)",
"t_wall",
"(avg)",
"n_eval");
3836 char buffer_proc[10];
3837 char buffer_wall[10];
3838 char buffer_proc_avg[10];
3839 char buffer_wall_avg[10];
3842 for (
const auto &s : fstats) {
3843 if (s.second.n_call!=0) {
3844 print(namefmt, s.first.c_str());
3847 format_time(buffer_proc_avg, s.second.t_proc/s.second.n_call);
3848 format_time(buffer_wall_avg, s.second.t_wall/s.second.n_call);
3849 print(
" | %s (%s) %s (%s) %9d\n",
3850 buffer_proc, buffer_proc_avg,
3851 buffer_wall, buffer_wall_avg, s.second.n_call);
3858 casadi_assert_dev(time>=0);
3859 double log_time = log10(time);
3860 int magn =
static_cast<int>(floor(log_time));
3861 int iprefix =
static_cast<int>(floor(log_time/3));
3863 sprint(buffer, 10,
" 0");
3867 sprint(buffer, 10,
" inf");
3870 char prefixes[] =
"TGMk munp";
3871 char prefix = prefixes[4-iprefix];
3873 int rem = magn-3*iprefix;
3874 double time_normalized = time/pow(10, 3*iprefix);
3877 sprint(buffer, 10,
" %1.2f%cs", time_normalized, prefix);
3878 }
else if (rem==1) {
3879 sprint(buffer, 10,
" %2.2f%cs", time_normalized, prefix);
3881 sprint(buffer, 10,
"%3.2f%cs", time_normalized, prefix);
3888 va_start(args, fmt);
3890 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
3894 casadi_assert(n>=0 && n<buf_sz,
"Print failure while processing '" + std::string(fmt) +
"'");
3900 va_start(args, fmt);
3903 size_t buf_sz =
sizeof(buf);
3904 char* buf_dyn =
nullptr;
3906 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
3908 if (n>
static_cast<casadi_int
>(buf_sz)) {
3909 buf_sz =
static_cast<size_t>(n+1);
3910 buf_dyn =
new char[buf_sz];
3911 n = vsnprintf(buf_dyn, buf_sz, fmt, args);
3914 if (n>=0)
uout() << (buf_dyn ? buf_dyn : buf) << std::flush;
3919 casadi_assert(n>=0,
"Print failure while processing '" + std::string(fmt) +
"'");
3924 bool always_inline,
bool never_inline)
const {
3926 eval_mx(arg, res, always_inline, never_inline);
3929 std::vector<std::vector<MX>> v(npar, arg);
3931 for (
int i=0; i<
n_in_; ++i) {
3933 t = horzsplit(arg[i],
size2_in(i));
3934 casadi_assert_dev(t.size()==npar);
3935 for (
int p=0; p<npar; ++p) v[p][i] = t[p];
3939 for (
int p=0; p<npar; ++p) {
3940 eval_mx(v[p], t, always_inline, never_inline);
3946 for (
int i=0; i<
n_out_; ++i) {
3947 for (
int p=0; p<npar; ++p) t[p] = v[p][i];
3948 res[i] = horzcat(t);
3958 default:
return "SOLVER_RET_UNKNOWN";
3963 s.
version(
"ProtoFunction", 2);
3973 int version = s.
version(
"ProtoFunction", 1, 2);
3988 s.
version(
"FunctionInternal", 7);
3996 s.
pack(
"FunctionInternal::jit",
jit_);
4004 casadi_assert(binary_ptr,
"Could not open library '" +
compiler_.
library() +
"'.");
4005 s.
pack(
"FunctionInternal::jit_binary", *binary_ptr);
4055 s.
pack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4056 s.
pack(
"FunctionInternal::sz_res_per", sz_res_per_);
4057 s.
pack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4058 s.
pack(
"FunctionInternal::sz_w_per", sz_w_per_);
4059 s.
pack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4060 s.
pack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4061 s.
pack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4062 s.
pack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4066 int version = s.
version(
"FunctionInternal", 1, 7);
4082 std::string library;
4083 s.
unpack(
"FunctionInternal::jit_library", library);
4089 std::stringstream ss;
4090 s.
unpack(
"FunctionInternal::jit_binary", ss);
4093 s.
unpack(
"FunctionInternal::jit_binary", *binary_ptr);
4164 s.
unpack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4165 s.
unpack(
"FunctionInternal::sz_res_per", sz_res_per_);
4166 s.
unpack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4167 s.
unpack(
"FunctionInternal::sz_w_per", sz_w_per_);
4168 s.
unpack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4169 s.
unpack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4170 s.
unpack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4171 s.
unpack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4187 std::string base_function;
4188 s.
unpack(
"FunctionInternal::base_function", base_function);
4191 "FunctionInternal::deserialize: not found '" + base_function +
"'");
4194 ret.
own(it->second(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.
Helper class for C code generation.
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.
static std::string array(const std::string &type, const std::string &name, casadi_int len, const std::string &def=std::string())
std::string generate(const std::string &prefix="")
Generate file(s)
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::vector< FunctionMeta > added_functions_
std::string shorthand(const std::string &name) const
Get a shorthand.
std::stringstream auxiliaries
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::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.
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.
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 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.
virtual void codegen_incref(CodeGenerator &g) const
Codegen incref for dependencies.
casadi_int numel_out() const
Number of input/output elements.
Function custom_jacobian_
std::string definition() const
Get function signature: name:(inputs)->(outputs)
virtual void find(std::map< FunctionInternal *, Function > &all_fun, casadi_int max_depth) const
const Sparsity & sparsity_in(casadi_int ind) const
Input/output sparsity.
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.
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.
eval_t eval_
Numerical evaluation redirected to a C function.
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 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 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.
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.
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
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.
Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind) const
Get the sparsity pattern via sparsity seed propagation.
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.
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.
virtual void codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
Dict cache_init_
Values to prepopulate the function cache with.
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.
void add_embedded(std::map< FunctionInternal *, Function > &all_fun, const Function &dep, casadi_int max_depth) const
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 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 wrap_as_needed(const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
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.
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 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.
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.
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.
std::string temporary_file(const std::string &prefix, const std::string &suffix)
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)
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.
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)