26 #include "mx_node.hpp"
28 #include "symbolic_mx.hpp"
29 #include "constant_mx.hpp"
30 #include "multiple_output.hpp"
31 #include "casadi_misc.hpp"
33 #include "calculus.hpp"
34 #include "mx_function.hpp"
37 #include "serializing_stream.hpp"
39 #include "bspline.hpp"
41 #include "casadi_call.hpp"
45 #define CASADI_THROW_ERROR(FNAME, WHAT) \
46 throw CasadiException("Error in MX::" FNAME " at " + CASADI_WHERE + ":\n"\
50 #define CASADI_THROW_ERROR_OBJ(FNAME, WHAT) \
51 throw CasadiException("Error in MX::" FNAME " for node of type " \
52 + this->class_name() + " at " + CASADI_WHERE + ":\n" + std::string(WHAT));
65 MX::MX(
MXNode* node,
bool dummy1,
bool dummy2,
bool dummy3,
bool dummy4) {
70 return MX(node,
false,
false,
false,
false);
81 MX::MX(
const std::vector<double>& x) {
94 *
this = val->
get_nzref(sp, std::vector<casadi_int>(sp.
nnz(), 0));
110 MX::MX(casadi_int nrow, casadi_int ncol) {
114 MX::MX(
const std::pair<casadi_int, casadi_int>& rc) {
131 casadi_assert_dev(
dynamic_cast<MultipleOutput*
>(node) !=
nullptr);
133 std::vector<MX> ret(x->
nout());
134 for (casadi_int i=0; i<ret.size(); ++i) {
138 }
else if (ret[i].
nnz()==0) {
139 ret[i] =
MX(ret[i].
size());
146 return (*this)->__nonzero__();
171 "Marix::get: First index must be a dense vector");
173 "Marix::get: Second index must be a dense vector");
176 std::vector<casadi_int>
mapping;
199 std::vector<casadi_int>
mapping;
209 "get(Sparsity sp): shape mismatch. This matrix has shape "
210 +
str(
size()) +
", but supplied sparsity index has shape "
216 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices."
217 "Got " +
dim(
true) +
" instead.");
222 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices. ");
227 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
232 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
254 set(m, ind1, rr.
T(), cc);
260 set(m, ind1, rr, cc.
T());
266 "MX::set: First index not dense vector");
268 "MX::set: Second index not dense vector");
279 set(m.
T(), ind1, rr, cc);
283 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size1()) +
"-by-"
292 casadi_assert_in_range(rr.
nonzeros(), -sz1+ind1, sz1+ind1);
293 casadi_assert_in_range(cc.
nonzeros(), -sz2+ind1, sz2+ind1);
302 for (casadi_int j=0; j<el.
size2(); ++j) {
303 casadi_int this_j = cc->at(j) - ind1;
304 if (this_j<0) this_j += sz2;
305 for (casadi_int k=el.
colind(j); k<el.
colind(j+1); ++k) {
306 casadi_int i = m.
row(k);
307 casadi_int this_i = rr->at(i) - ind1;
308 if (this_i<0) this_i += sz1;
309 el->at(k) = this_i + this_j*sz1;
344 set(m.
T(), ind1, rr);
348 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size())
349 +
", while rhs is " +
str(m.
size()));
360 casadi_assert_in_range(rr.
nonzeros(), -nel+ind1, nel+ind1);
371 new_row.reserve(sz+rrsz);
372 new_col.reserve(sz+rrsz);
374 for (std::vector<casadi_int>::iterator i=
nz.begin(); i!=
nz.end(); ++i) {
377 new_row.push_back(*i % sz1);
378 new_col.push_back(*i / sz1);
394 "set(Sparsity sp): shape mismatch. This matrix has shape "
395 +
str(
size()) +
", but supplied sparsity index has shape "
397 std::vector<casadi_int> ii = sp.
find();
421 casadi_int sz =
nnz();
422 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
425 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
427 for (
auto&& i : kk_mod.
nonzeros()) {
428 casadi_assert(!(ind1 && i<=0),
429 "Matlab is 1-based, but requested index " +
str(i) +
". "
430 "Note that negative slices are disabled in the Matlab interface. "
431 "Possibly you may want to use 'end'.");
450 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1.0: outer);
455 m = (*this)->
get_nz_ref(ind1 ? inner-1: inner, ind1 ? outer-1.0: outer);
460 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1: outer);
469 casadi_assert(kk.
nnz()==m.
nnz() || m.
nnz()==1,
470 "MX::set_nz: length of non-zero indices (" +
str(kk.
nnz()) +
") " +
471 "must match size of rhs (" +
str(m.
nnz()) +
").");
491 casadi_error(
"Dimension mismatch. lhs is " +
str(kk.
size())
492 +
", while rhs is " +
str(m.
size()));
504 casadi_int sz =
nnz();
505 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
508 if (kk.
nnz()==0)
return;
511 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
513 for (
auto&& i : kk_mod.
nonzeros()) {
514 casadi_assert(!(ind1 && i<=0),
515 "Matlab is 1-based, but requested index " +
str(i) +
". "
516 "Note that negative slices are disabled in the Matlab interface. "
517 "Possibly you may want to use 'end'.");
554 ", x is " + x.
dim() +
", while y is " + y.
dim());
580 MX MX::inf(
const std::pair<casadi_int, casadi_int> &rc) {
581 return inf(rc.first, rc.second);
592 MX MX::nan(
const std::pair<casadi_int, casadi_int>& rc) {
593 return nan(rc.first, rc.second);
605 if ((*this)->op()==
OP_NEG) {
606 return (*this)->
dep(0);
613 return (*this)->sparsity();
616 void MX::erase(
const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
bool ind1) {
621 std::vector<casadi_int>
mapping = sp.
erase(rr, cc, ind1);
633 for (
const MX& e : p) {
640 for (casadi_int i=0; i<
nz.
nnz(); ++i) {
641 ret.push_back(
nz(i));
648 void MX::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
663 const std::vector<casadi_int>& rr,
664 const std::vector<casadi_int>& cc,
bool ind1) {
666 sp.
enlarge(nrow, ncol, rr, cc, ind1);
678 return mac(x, y, z, blas);
683 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
684 const std::vector<casadi_int>& dim_c,
685 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
686 const std::vector<casadi_int>& c) {
687 return C->get_einstein(A,
B, dim_c, dim_a, dim_b, c, a, b);
691 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
692 const std::vector<casadi_int>& dim_c,
693 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
694 const std::vector<casadi_int>& c) {
699 if (axis==-1) axis = x.
is_row();
700 MX r = axis==0 ? x.
T() : x;
707 MX ret = f(std::vector<MX>{0, r})[0];
709 return axis==0 ? ret.
T() : ret;
720 "Matrix product with incompatible dimensions. Lhs is "
721 + x.
dim() +
" and rhs is " + y.
dim() +
".");
745 "Error in attachAssert: assertion expression y must be scalar, "
746 "but got " + y.
dim());
747 return(*this)->get_assert(y, fail_message);
755 return(*this)->
get_dump(base_filename, opts);
759 casadi_assert(
op()==
OP_DUMP,
"reset_dump_count: not a dump node");
769 Function f(
"f", std::vector<MX>{}, {m}, {{
"allow_free",
true}});
770 return f(std::vector<DM>{})[0];
784 return (*this)->
dep(ch);
788 return (*this)->n_dep();
792 return (*this)->name();
808 return (*this)->which_function();
812 return (*this)->is_output();
816 return (*this)->has_output();
820 return (*this)->which_output();
824 return (*this)->op()==
op;
832 return dynamic_cast<const Norm*
>(
get())!=
nullptr;
835 MX::operator double()
const {
839 MX::operator
DM()
const {
840 return (*this)->get_DM();
844 return (*this)->is_binary();
848 return (*this)->is_unary();
852 return (*this)->op();
856 return (*this)->info();
860 (*this)->serialize(s);
882 "MX::is_commutative: must be binary or unary operation");
883 return operation_checker<CommChecker>(
op());
887 return (*this)->mapping();
891 return (*this)->temp;
899 return (*this)->nout();
911 casadi_assert(sp.
size()==x.
size(),
"Cannot project " + x.
dim() +
" to " + sp.
dim());
918 }
catch (std::exception& e) {
919 CASADI_THROW_ERROR(
"project", e.what());
936 casadi_int MX::eq_depth_ = 1;
939 eq_depth_ = eq_depth;
955 return (*this)->is_valid_input();
959 return (*this)->n_primitives();
964 std::vector<MX>::iterator it=ret.begin();
965 (*this)->primitives(it);
966 casadi_assert_dev(it==ret.end());
972 std::vector<MX>::iterator it=ret.begin();
973 (*this)->split_primitives(x, it);
974 casadi_assert_dev(it==ret.end());
980 std::vector<SX>::iterator it=ret.begin();
981 (*this)->split_primitives(x, it);
982 casadi_assert_dev(it==ret.end());
988 std::vector<DM>::iterator it=ret.begin();
989 (*this)->split_primitives(x, it);
990 casadi_assert_dev(it==ret.end());
995 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
996 std::vector<MX>::const_iterator it=v.begin();
998 casadi_assert_dev(it==v.end());
1003 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
1004 std::vector<SX>::const_iterator it=v.begin();
1005 SX ret = (*this)->join_primitives(it);
1006 casadi_assert_dev(it==v.end());
1011 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
1012 std::vector<DM>::const_iterator it=v.begin();
1013 DM ret = (*this)->join_primitives(it);
1014 casadi_assert_dev(it==v.end());
1019 return (*this)->has_duplicates();
1023 (*this)->reset_input();
1027 return (*this)->is_eye();
1034 return (*this)->is_zero();
1039 return (*this)->is_one();
1043 return (*this)->is_value(-1);
1047 return (*this)->is_half();
1051 return (*this)->is_value(val);
1055 return (*this)->is_nonnegative();
1066 casadi_error(
"Cannot check regularity for symbolic MX");
1071 return (*this)->is_inf();
1075 return (*this)->is_minus_inf();
1079 return (*this)->is_integer();
1091 return (*this)->get_unary(
OP_INV);
1100 return dynamic_cast<const MXNode*
>(ptr)!=
nullptr;
1105 for (
auto&& i : x) {
1106 if (i.is_empty(both))
return true;
1111 std::vector<MX>
trim_empty(
const std::vector<MX>& x,
bool both=
false) {
1112 std::vector<MX> ret;
1113 for (
auto&& i : x) {
1114 if (!i.is_empty(both)) ret.push_back(i);
1123 for (casadi_int i=0;i<
ne.
size();i++) {
1125 "horzcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1126 " and x[0]: " +
ne[0].
dim() +
".");
1132 }
else if (x.size()==1) {
1140 casadi_int nrow = 0;
1141 for (casadi_int i=0;i<ret.size();++i) {
1143 casadi_assert_dev(nrow==0 || nrow==ret[i].
size1());
1144 nrow = ret[i].size1();
1151 return x.front()->get_horzcat(x);
1157 if (x.empty())
return MX();
1158 if (x.size()==1)
return x.front();
1162 return x.front()->get_diagcat(x);
1169 for (casadi_int i=0;i<
ne.
size();i++) {
1171 "vertcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1172 " and x[0]: " +
ne[0].
dim() +
".");
1178 }
else if (x.size()==1) {
1186 casadi_int ncol = 0;
1187 for (casadi_int i=0;i<ret.size();++i) {
1189 casadi_assert_dev(ncol==0 || ret[i].
size2()==ncol);
1190 ncol = ret[i].size2();
1196 }
else if (!x.front().is_column()) {
1198 std::vector<MX> xT = x;
1199 for (std::vector<MX>::iterator i=xT.begin(); i!=xT.end(); ++i) *i = i->T();
1208 casadi_assert_dev(!
offset.empty());
1209 casadi_assert_dev(
offset.front()==0);
1215 return std::vector<MX>(0);
1216 }
else if (
offset.size()==2) {
1217 return std::vector<MX>(1, x);
1224 const std::vector<casadi_int>& offset2) {
1226 casadi_assert_dev(!offset1.empty());
1227 casadi_assert_dev(offset1.front()==0);
1228 casadi_assert_dev(offset1.back()==x.
size1());
1232 casadi_assert_dev(!offset2.empty());
1233 casadi_assert_dev(offset2.front()==0);
1234 casadi_assert_dev(offset2.back()==x.
size2());
1243 casadi_assert_dev(!
offset.empty());
1244 casadi_assert_dev(
offset.front()==0);
1250 return std::vector<MX>();
1251 }
else if (
offset.size()==2) {
1252 return std::vector<MX>(1, x);
1258 for (
auto&& e : ret) e = e.T();
1265 if (v.empty())
return MX(0, 0);
1268 casadi_int ncols = v.front().size();
1269 for (
auto&& e : v) {
1270 casadi_assert(e.size()==ncols,
"blockcat: Inconsistent number of block columns");
1274 if (v.front().empty())
return MX(0, 0);
1277 std::vector<MX>
rows;
1278 for (
auto&& e : v) {
1305 std::vector<MX>& res,
1316 return transform(std::vector<MX>{x}, opts).at(0);
1320 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
1321 return transform(std::vector<MX>{x}, passes, opts).at(0);
1328 {{
"allow_free",
true}, {
"allow_duplicate_io_names",
true}});
1334 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
1338 {{
"allow_free",
true}, {
"allow_duplicate_io_names",
true}});
1345 if (nrow==x.
size1() && ncol==x.
size2())
return x;
1362 casadi_assert(x.
nnz()==sp.
nnz(),
1363 "Mismatching nonzero count: " +
str(x.
nnz()) +
" versus " +
1374 if (short_circuit) {
1376 std::vector<MX> arg =
symvar(
veccat(std::vector<MX>{x_true, x_false}));
1379 Function f_true(
"f_true", arg, {x_true});
1380 Function f_false(
"f_false", arg, {x_false});
1386 std::vector<MX> sw_arg;
1387 sw_arg.push_back(cond);
1388 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1389 return sw(sw_arg).at(0);
1396 const MX& x_default,
bool short_circuit) {
1397 if (short_circuit) {
1399 std::vector<MX> arg = x;
1400 arg.push_back(x_default);
1404 std::vector<Function> f(x.size());
1405 for (casadi_int k=0; k<x.size(); ++k) {
1406 std::stringstream ss;
1407 ss <<
"f_case" << k;
1408 f[k] =
Function(ss.str(), arg, {x[k]});
1410 Function f_default(
"f_default", arg, {x_default});
1416 std::vector<MX> sw_arg;
1417 sw_arg.push_back(ind);
1418 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1419 return sw(sw_arg).at(0);
1422 for (casadi_int k=0; k<x.size(); ++k) {
1423 ret =
if_else(ind==
static_cast<double>(k), x[k], ret);
1431 std::vector<unsigned char>
mapping;
1435 std::vector<casadi_int> nzA, nzB;
1451 ret =
B->get_nzassign(ret, nzB);
1456 casadi_assert(x.
is_square(),
"trace: must be square");
1458 for (casadi_int i=0; i < x.
size2(); i ++) {
1466 std::vector<casadi_int>
mapping;
1476 Dict opts{{
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}};
1477 Function f(
"tmp_n_nodes", std::vector<MX>{}, {x}, opts);
1490 casadi_assert(p.
is_dense(),
"polynomial coefficients vector must be a vector");
1491 casadi_assert(p.
is_column() && p.
nnz()>0,
"polynomial coefficients must be a vector");
1493 for (casadi_int i=1; i<p.
nnz(); ++i) {
1494 ret = ret*x + p.
nz(i);
1500 return x->
disp(args);
1504 std::vector<MX>& ex,
bool reverse) {
1505 casadi_assert(v.size()==vdef.size(),
1506 "Mismatch in the number of expression to substitute.");
1507 for (casadi_int k=0; k<v.size(); ++k) {
1509 "Variable " +
str(k) +
" is not symbolic");
1510 casadi_assert(v[k].
size() == vdef[k].
size(),
1511 "Inconsistent shape for variable " +
str(k) +
".");
1513 casadi_assert(
reverse==
false,
"Not implemented");
1516 if (v.empty())
return;
1519 std::vector<MX> f_out = vdef;
1520 f_out.insert(f_out.end(), ex.begin(), ex.end());
1521 Function temp(
"tmp_substitute_inplace", {v}, f_out,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1526 return substitute(std::vector<MX>{ex}, std::vector<MX>{v}, std::vector<MX>{vdef}).front();
1530 const std::vector<MX> &vdef) {
1532 casadi_assert_dev(v.size()==vdef.size());
1535 bool all_equal =
true;
1536 for (casadi_int k=0; k<v.size(); ++k) {
1542 if (all_equal)
return ex;
1545 Function F(
"tmp_substitute", v, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1546 std::vector<MX> ret;
1547 F.
call(vdef, ret,
true);
1552 const std::vector<MX> &vdef) {
1557 const std::vector<MX> &vdef,
bool& updated) {
1562 const std::vector<MX>& v,
1563 const std::vector<MX>& vdef) {
1568 const std::vector<MX>& v,
1569 const std::vector<MX>& vdef,
1571 casadi_assert(v.size()==vdef.size(),
1572 "Mismatch in the number of expression to substitute: "
1573 +
str(v.size()) +
" <-> " +
str(vdef.size()) +
".");
1578 bool all_equal =
true;
1579 for (casadi_int k=0; k<v.size(); ++k) {
1585 if (all_equal)
return ex;
1588 for (casadi_int i=0;i<v.size();++i) {
1589 casadi_assert(v[i].
size()==vdef[i].
size(),
1590 "Inconsistent shapes for i = " +
str(i) +
": v[i] " + v[i].
dim() +
1591 " <-> vdef[i] " + vdef[i].
dim());
1595 Dict opts({{
"max_io", 0}, {
"allow_free",
true}});
1596 Function f(
"tmp_graph_substitute", std::vector<MX>{}, ex, opts);
1600 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1601 std::vector<MX> swork(ff->workloc_.size()-1);
1604 std::vector<bool> tainted(swork.size());
1608 std::map<const MXNode*, casadi_int> expr_lookup;
1609 for (casadi_int i=0;i<v.size();++i) {
1610 auto it = expr_lookup.find(v[i].operator->());
1611 if (it==expr_lookup.end()) expr_lookup[v[i].operator->()] = i;
1615 std::vector<bool> expr_found(v.size(),
false);
1618 std::vector<MX> f_out(f.n_out());
1619 std::vector<MX> oarg, ores;
1622 std::map<const MXNode*, casadi_int>::const_iterator it_lookup;
1625 std::vector<std::vector<MX>> out_split(ex.size());
1626 for (casadi_int i = 0; i < out_split.size(); ++i) out_split[i].resize(ex[i].
n_primitives());
1628 for (
auto it=algorithm.begin(); it!=algorithm.end(); ++it) {
1632 it_lookup = expr_lookup.find((it->data).operator->());
1634 if (it_lookup!=expr_lookup.end()) {
1636 MX e = vdef[it_lookup->second];
1640 for (casadi_int i=0;i<it->res.size();++i) {
1641 casadi_int k = it->res[i];
1648 swork[it->res.front()] = e;
1649 tainted[it->res.front()] =
true;
1651 expr_found[it_lookup->second] =
true;
1653 }
else if (it->data->has_output()) {
1654 bool any_tainted =
false;
1656 for (casadi_int i=0;i<it->res.size();++i) {
1658 casadi_int k = it->res[i];
1662 it_lookup = expr_lookup.
find(out.operator->());
1663 if (it_lookup!=expr_lookup.end()) {
1665 MX e = vdef[it_lookup->second];
1669 expr_found[it_lookup->second] =
true;
1673 if (any_tainted)
continue;
1679 tainted[it->res.front()] =
false;
1682 swork[it->res.front()] = it->data;
1683 tainted[it->res.front()] =
false;
1686 out_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
1690 bool node_tainted =
false;
1693 oarg.resize(it->arg.size());
1694 for (casadi_int i=0; i<oarg.size(); ++i) {
1695 casadi_int el = it->arg[i];
1696 if (el>=0) node_tainted = node_tainted || tainted[el];
1697 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : swork.at(el);
1701 ores.resize(it->res.size());
1702 if (!node_tainted) {
1703 if (it->data.has_output()) {
1704 for (casadi_int i=0;i<it->res.size();++i) {
1705 ores.at(i) = it->data.get_output(i);
1708 ores.at(0) = it->data;
1711 it->data->eval_mx(oarg, ores);
1715 for (casadi_int i=0; i<ores.size(); ++i) {
1716 casadi_int el = it->res[i];
1717 if (el>=0) swork.at(el) = ores[i];
1718 if (el>=0) tainted[el] = node_tainted;
1725 for (
size_t k = 0; k < out_split.size(); ++k) {
1726 f_out[k] = ex[k].join_primitives(out_split.at(k));
1729 bool all_found=
true;
1730 for (casadi_int i=0;i<v.size();++i) {
1731 all_found = all_found && expr_found[i];
1734 updated =
any(expr_found);
1741 std::vector<MX>& vdef,
const Dict& opts) {
1744 std::string v_prefix =
"v_", v_suffix =
"";
1745 bool lift_shared =
true, lift_calls =
false;
1746 casadi_int v_ind = 0;
1747 for (
auto&&
op : opts) {
1748 if (
op.first ==
"prefix") {
1749 v_prefix = std::string(
op.second);
1750 }
else if (
op.first ==
"suffix") {
1751 v_suffix = std::string(
op.second);
1752 }
else if (
op.first ==
"lift_shared") {
1753 lift_shared =
op.second;
1754 }
else if (
op.first ==
"lift_calls") {
1755 lift_calls =
op.second;
1756 }
else if (
op.first ==
"offset") {
1759 casadi_error(
"No such option: " + std::string(
op.first));
1763 Function f(
"tmp_extract", std::vector<MX>{}, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1766 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1767 std::vector<MX> work(ff->workloc_.size()-1);
1769 std::vector<casadi_int> usecount(work.size(), 0);
1771 std::vector<std::pair<casadi_int, casadi_int> > origin(work.size(), std::make_pair(-1, -1));
1773 std::vector<std::pair<casadi_int, casadi_int> >
replace;
1776 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1783 for (casadi_int c=0; c<it->arg.size(); ++c) {
1785 if (lift_calls && it->op ==
OP_CALL) {
1787 if (usecount.at(it->arg[c]) >= 0) {
1788 replace.push_back(origin.at(it->arg[c]));
1789 usecount.at(it->arg[c]) = -1;
1791 }
else if (lift_shared && work[it->arg[c]].op() !=
OP_PARAMETER
1792 && work[it->arg[c]].op() !=
OP_CONST) {
1793 if (usecount.at(it->arg[c]) == 0) {
1795 usecount.at(it->arg[c]) = 1;
1796 }
else if (usecount.at(it->arg[c]) == 1) {
1798 replace.push_back(origin.at(it->arg[c]));
1799 usecount.at(it->arg[c]) = -1;
1809 usecount[it->res.front()] = -1;
1812 for (casadi_int c=0; c<it->res.size(); ++c) {
1813 if (it->res[c]>=0) {
1814 work[it->res[c]] = it->data.get_output(c);
1815 origin[it->res[c]] = std::make_pair(k, c);
1816 if (lift_calls && it->op ==
OP_CALL) {
1818 replace.push_back(origin.at(it->res[c]));
1819 usecount.at(it->res[c]) = -1;
1821 usecount.at(it->res[c]) = 0;
1837 std::vector<std::pair<casadi_int, casadi_int> >::const_iterator replace_it=
replace.begin();
1839 std::vector<MX> oarg, ores;
1842 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1845 casadi_assert(it->data->segment()==0,
"Not implemented");
1846 ex[it->data->ind()] = work[it->arg.front()];
1849 work[it->res.front()] = it->data;
1855 work[it->res.front()] = it->data;
1858 oarg.resize(it->arg.size());
1859 for (casadi_int i=0; i<oarg.size(); ++i) {
1860 casadi_int el = it->arg[i];
1861 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : work.at(el);
1864 ores.resize(it->res.size());
1865 it->data->eval_mx(oarg, ores);
1867 for (casadi_int i=0; i<ores.size(); ++i) {
1868 casadi_int el = it->res[i];
1869 if (el>=0) work.at(el) = ores[i];
1873 for (casadi_int c=0; c<it->res.size(); ++c) {
1875 casadi_int ind = it->res[c];
1877 bool replace_node = replace_it !=
replace.end()
1878 && replace_it->first==k && replace_it->second==c;
1880 bool output_node = lift_calls && it->op ==
OP_CALL;
1882 if (!replace_node && !output_node)
continue;
1885 v.push_back(
MX::sym(v_prefix + std::to_string(v_ind++) + v_suffix, v_sp));
1889 casadi_assert(replace_node,
"Consistency check");
1891 vdef.push_back(work[ind]);
1893 work[ind] = v.back();
1898 casadi_assert(output_node,
"Consistency check");
1900 vdef.push_back(ores.at(c));
1907 casadi_assert(replace_it ==
replace.end(),
"Consistency check failed");
1908 }
catch (std::exception& e) {
1909 CASADI_THROW_ERROR(
"extract", e.what());
1913 void MX::shared(std::vector<MX>& ex, std::vector<MX>& v, std::vector<MX>& vdef,
1914 const std::string& v_prefix,
const std::string& v_suffix) {
1916 extract(ex, v, vdef,
Dict{{
"lift_shared",
true}, {
"lift_calls",
false},
1917 {
"prefix", v_prefix}, {
"suffix", v_suffix}});
1924 h_opts[
"allow_free"] =
true;
1925 Function h(
"helper_jacobian_MX", {x}, {f}, h_opts);
1927 }
catch (std::exception& e) {
1928 CASADI_THROW_ERROR(
"jacobian", e.what());
1934 return hessian(f, x, g, opts);
1939 Dict all_opts = opts;
1941 if (!opts.count(
"symmetric")) all_opts[
"symmetric"] =
true;
1943 }
catch (std::exception& e) {
1944 CASADI_THROW_ERROR(
"hessian", e.what());
1948 std::vector<std::vector<MX> >
1950 const std::vector<MX> &arg,
1951 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1954 bool always_inline =
true;
1955 bool never_inline =
false;
1959 h_opts[
"allow_free"] =
true;
1960 for (
auto&&
op : opts_remainder) {
1961 if (
op.first==
"always_inline") {
1962 always_inline =
op.second;
1963 }
else if (
op.first==
"never_inline") {
1964 never_inline =
op.second;
1966 casadi_error(
"No such option: " + std::string(
op.first));
1970 Function temp(
"forward_temp", arg, ex, h_opts);
1971 std::vector<std::vector<MX> > ret;
1972 temp->
call_forward(arg, ex, v, ret, always_inline, never_inline);
1974 }
catch (std::exception& e) {
1975 CASADI_THROW_ERROR(
"forward", e.what());
1979 std::vector<std::vector<MX> >
1981 const std::vector<MX> &arg,
1982 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1985 bool always_inline =
true;
1986 bool never_inline =
false;
1991 h_opts[
"allow_free"] =
true;
1993 for (
auto&&
op : opts_remainder) {
1994 if (
op.first==
"always_inline") {
1995 always_inline =
op.second;
1996 }
else if (
op.first==
"never_inline") {
1997 never_inline =
op.second;
1999 casadi_error(
"No such option: " + std::string(
op.first));
2003 Function temp(
"reverse_temp", arg, ex, h_opts);
2004 std::vector<std::vector<MX> > ret;
2005 temp->
call_reverse(arg, ex, v, ret, always_inline, never_inline);
2007 }
catch (std::exception& e) {
2008 CASADI_THROW_ERROR(
"reverse", e.what());
2021 return det(x,
"qr");
2026 return mysolver.
det(x);
2034 casadi_error(
"Not implemented");
2042 Function f(
"f", std::vector<MX>{}, {x}, {{
"allow_free",
true}});
2047 return matrix_expand(std::vector<MX>{e}, boundary, options).at(0);
2051 const std::vector<MX> &boundary,
2052 const Dict &options) {
2055 std::vector<MX> syms(boundary.size());
2057 for (casadi_int i=0;i<syms.size();++i) {
2068 Function f(
"tmp_matrix_expand", v, ret,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
2092 }
else if (n==1 && m==1) {
2108 if (nsteps < 2)
return b;
2109 MX step = (b - a) /
static_cast<double>(nsteps - 1);
2110 std::vector<double> idx(nsteps - 1);
2111 for (casadi_int i = 0; i < nsteps - 1; ++i) idx[i] =
static_cast<double>(i);
2112 return vertcat(std::vector<MX>{a +
DM(idx) * step, b});
2129 return solve(a, b,
"qr");
2136 return mysolver.
solve(a, b,
false);
2149 opts[
"const_A"] =
true;
2151 return ret(std::vector<MX>{A, t})[0];
2156 return ret(std::vector<MX>{A, 1})[0];
2166 if (x.
nnz()==0)
return false;
2169 Function temp(
"tmp_depends_on", {arg}, {x},
Dict{{
"max_io", 0}, {
"allow_free",
true}});
2172 std::vector<bvec_t> t_in(arg.
nnz(), 1), t_out(x.
nnz());
2176 for (casadi_int i=0; i<t_out.size(); ++i) {
2177 if (t_out[i])
return true;
2185 if (n.empty())
return true;
2188 std::set<MXNode*> l;
2189 for (
const MX& e : v) l.insert(e.get());
2191 size_t l_unique = l.size();
2193 for (
const MX& e : n) l.insert(e.get());
2195 return l.size()==l_unique;
2199 if (n.empty())
return true;
2202 std::set<MXNode*> l;
2203 for (
const MX& e : v) l.insert(e.get());
2205 size_t l_unique = l.size();
2207 std::set<MXNode*> r;
2208 for (
const MX& e : n) r.insert(e.get());
2210 size_t r_unique = r.size();
2211 for (
const MX& e : n) l.insert(e.get());
2213 return l.size()<l_unique+r_unique;
2221 return p->
get_low(v, options);
2226 const std::vector< std::vector<double> >& knots,
2227 const std::vector<casadi_int>& degree,
2234 const std::vector< std::vector<double> >& knots,
2235 const std::vector<casadi_int>& degree,
2242 const std::vector<MX>& knots,
2243 const std::vector<casadi_int>& degree,
2250 const std::vector< std::vector<double> >& knots,
2251 const std::vector<casadi_int>& degree,
2262 std::vector<MX>& res,
2264 Dict temp_opts = {{
"live_variables",
false},
2267 {
"allow_free",
true}};
2268 Function f(
"temp", arg, res, temp_opts);
2270 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2274 std::vector<bool> is_numeric(workloc_.size()-1);
2276 std::vector<MX> swork(workloc_.size()-1);
2279 std::vector<std::vector<MX> > arg_split(arg.size());
2280 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].split_primitives(arg[i]);
2283 std::vector<std::vector<MX> > res_split(res.size());
2284 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].n_primitives());
2286 std::vector<MX> arg1, res1;
2288 std::unordered_map<const MXNode*, bool> numeric_node;
2290 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2292 swork[it->res.front()] = project(arg_split.at(it->data->ind()).at(it->data->segment()),
2293 it->data.sparsity(),
true);
2294 is_numeric[it->res.front()] =
false;
2297 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2300 swork[it->res.front()] = it->data;
2301 is_numeric[it->res.front()] =
false;
2304 arg1.resize(it->arg.size());
2307 bool numeric =
true;
2309 for (casadi_int i=0; i<arg1.size(); ++i) {
2310 casadi_int el = it->arg[i];
2312 arg1[i] =
MX(it->data->dep(i).size());
2314 arg1[i] = swork[el];
2315 numeric = numeric && is_numeric[el];
2319 numeric_node[it->data.get()] = numeric;
2322 res1.resize(it->res.size());
2324 bool matched =
false;
2327 if (it->op ==
OP_MUL && is_numeric[it->arg[0]] &&
2328 !is_numeric[it->arg[1]] && arg1[1].is_op(
OP_MUL)) {
2329 if (numeric_node[arg1[1].dep(0).get()]) {
2331 res1[0] = (arg1[0]*arg1[1].dep(0))*arg1[1].dep(1);
2335 if (!matched) it->data->eval_mx(arg1, res1);
2337 for (casadi_int i=0; i<res1.size(); ++i) {
2338 casadi_int el = it->res[i];
2340 is_numeric[el] = numeric;
2345 for (casadi_int i=0; i<res1.size(); ++i) {
2346 casadi_int el = it->res[i];
2348 swork[el] = res1[i];
2355 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].join_primitives(res_split[i]);
2361 std::unordered_multimap< std::size_t, std::pair<MX, DM> >& cache) {
2363 std::size_t h = sp.
hash();
2367 auto r = cache.equal_range(h);
2368 for (
auto it = r.first; it != r.second; ++it) {
2369 const DM& d = it->second.second;
2372 return it->second.first;
2379 std::vector<double> vec(v, v+sp.
nnz());
2382 cache.emplace(h, std::make_pair(ret, m));
2389 std::vector<MX>& res,
2392 Dict temp_opts = {{
"live_variables",
false},
2395 {
"allow_free",
true}};
2396 Function f(
"temp", arg, res, temp_opts);
2398 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2402 std::vector<double> w_vec(f.
sz_w());
2404 std::vector<casadi_int> iw_vec(f.
sz_iw());
2405 casadi_int* iw =
get_ptr(iw_vec);
2406 std::vector<const double*> arg_num_vec(f.
sz_arg());
2407 const double** arg_num =
get_ptr(arg_num_vec);
2408 std::vector<double*> res_num_vec(f.
sz_res());
2409 double** res_num =
get_ptr(res_num_vec);
2412 std::vector<bool> is_numeric(workloc_.size()-1);
2417 std::vector<MX> swork(workloc_.size()-1);
2420 std::vector<std::vector<MX> > arg_split(arg.size());
2421 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].
split_primitives(arg[i]);
2424 std::vector<std::vector<MX> > res_split(res.size());
2425 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].
n_primitives());
2427 std::vector<MX> arg1, res1;
2429 std::unordered_multimap< std::size_t, std::pair<MX, DM> > cache;
2431 bool performed_folding =
false;
2434 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2436 swork[it->res.front()] =
project(arg_split.at(it->data->ind()).at(it->data->segment()),
2437 it->data.sparsity(),
true);
2438 is_numeric[it->res.front()] =
false;
2441 MX& target = res_split.at(it->data->ind()).at(it->data->segment());
2442 casadi_int el = it->arg.front();
2443 if (is_numeric[el] && !it->data->dep().is_constant()) {
2444 target =
get_const(it->data->dep().sparsity(), w + workloc_[el], cache);
2450 swork[it->res.front()] = it->data;
2451 is_numeric[it->res.front()] =
false;
2454 arg1.resize(it->arg.size());
2457 bool numeric =
true;
2460 for (casadi_int i=0; i<arg1.size(); ++i) {
2461 casadi_int el = it->arg[i];
2464 arg1[i] =
MX(it->data->dep(i).size());
2467 arg1[i] = swork[el];
2469 numeric = numeric && is_numeric[el];
2475 for (casadi_int i=0; i<it->arg.size(); ++i)
2476 arg_num[i] = it->arg[i]>=0 ? w+workloc_[it->arg[i]] :
nullptr;
2477 for (casadi_int i=0; i<it->res.size(); ++i)
2478 res_num[i] = it->res[i]>=0 ? w+workloc_[it->res[i]] :
nullptr;
2480 if (it->data->eval(arg_num, res_num, iw, w)) casadi_error(
"Evaluation error");
2481 performed_folding =
true;
2484 for (casadi_int i=0; i<arg1.size(); ++i) {
2485 casadi_int el = it->arg[i];
2487 MX& target = arg1[i];
2488 if (is_numeric[el] && !it->data->dep(i).is_constant()) {
2489 target =
get_const(it->data->dep(i).sparsity(), w + workloc_[el], cache);
2498 res1.resize(it->res.size());
2499 it->data->
eval_mx(arg1, res1);
2502 for (casadi_int i=0; i<res1.size(); ++i) {
2503 casadi_int el = it->res[i];
2505 swork[el] = res1[i];
2506 is_numeric[el] = numeric;
2513 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].
join_primitives(res_split[i]);
2515 return performed_folding;
2519 std::vector<MX>& res,
2521 Dict temp_opts = {{
"live_variables",
false},
2524 {
"allow_free",
true}};
2525 Function f(
"temp", arg, res, temp_opts);
2527 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2530 std::vector<casadi_int> rwork(workloc_.size()-1);
2531 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2534 rwork[it->arg.front()]++;
2536 rwork[it->res.front()]++;
2538 for (casadi_int i=0; i<it->arg.size(); ++i) {
2539 casadi_int el = it->arg[i];
2551 std::vector<MX> swork(workloc_.size()-1);
2554 std::vector<std::vector<MX> > arg_split(arg.size());
2555 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].
split_primitives(arg[i]);
2558 std::vector<std::vector<MX> > res_split(res.size());
2559 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].
n_primitives());
2561 std::vector<MX> arg1, res1;
2564 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2566 swork[it->res.front()] =
project(arg_split.at(it->data->ind()).at(it->data->segment()),
2567 it->data.sparsity(),
true);
2570 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2573 swork[it->res.front()] = it->data;
2576 arg1.resize(it->arg.size());
2578 std::vector<bool> unique(it->arg.size(),
true);
2579 for (casadi_int i=0; i<arg1.size(); ++i) {
2580 casadi_int el = it->arg[i];
2582 arg1[i] =
MX(it->data->dep(i).size());
2584 arg1[i] = swork[el];
2585 if (rwork[el]>1) unique[i] =
false;
2590 res1.resize(it->res.size());
2591 it->data->eval_mx(arg1, res1, unique);
2594 for (casadi_int i=0; i<res1.size(); ++i) {
2595 casadi_int el = it->res[i];
2597 swork[el] = res1[i];
2604 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].
join_primitives(res_split[i]);
2609 class IncrementalSerializerMX {
2612 IncrementalSerializerMX() : serializer(ss) {
2615 std::string pack(
const MX& a) {
2618 if (a.is_empty())
return "";
2624 a.serialize(serializer);
2627 a.serialize(serializer);
2628 std::string ret = ss.str();
2635 std::stringstream ss;
2637 std::vector<MX> ref;
2638 SerializingStream serializer;
2642 std::vector<MX>
MX::cse(
const std::vector<MX>& e) {
2643 std::vector<MX> orig = e;
2644 bool updated =
true;
2646 Function f(
"f", std::vector<MX>{}, orig,
2647 {{
"live_variables",
false}, {
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}});
2651 std::vector<MX> swork(ff->workloc_.size()-1);
2654 std::vector<std::vector<MX> > res_split(orig.size());
2655 for (casadi_int i=0; i<orig.size(); ++i) res_split[i].resize(orig[i].
n_primitives());
2657 std::vector<MX> arg1, res1;
2658 std::vector<MX> res(orig.size());
2660 std::unordered_map<std::string, MX > cache;
2661 IncrementalSerializerMX s;
2668 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it) {
2671 std::string key = s.pack(it->data);
2673 auto itk = cache.find(key);
2674 if (itk==cache.end()) {
2675 cache[key] = it->data;
2680 casadi_int alg_counter = 0;
2681 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2686 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2689 MX& target = swork[it->res.front()];
2691 cache[s.pack(target)] = target;
2695 arg1.resize(it->arg.size());
2696 for (casadi_int i=0; i<arg1.size(); ++i) {
2697 casadi_int el = it->arg[i];
2698 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : swork[el];
2702 res1.resize(it->res.size());
2703 it->data->eval_mx(arg1, res1);
2706 for (casadi_int i=0; i<res1.size(); ++i) {
2707 casadi_int el = it->res[i];
2709 MX& out_i = res1[i];
2712 casadi_int output_node = -1;
2717 out_i = out_i.
dep(0);
2725 if (!function_serialize_cache.
incache(fptr, key_s)) {
2727 function_serialize_cache.
tocache(fptr, key_s);
2732 if (!function_cache.
incache(key_s, canonical)) {
2742 std::string key = s.pack(out_i);
2744 auto itk = cache.find(key);
2745 if (itk==cache.end()) {
2748 out_i = itk->second;
2751 if (output_node==-1) {
2761 if (el>=0) swork[el] = out_i;
2767 for (casadi_int i=0; i<res.size(); ++i) res[i] = orig[i].
join_primitives(res_split[i]);
2769 std::vector<MX> subs_from;
2770 std::vector<MX> subs_to;
2771 for (
const auto& e : function_cache.
cache_map()) {
2772 e.second->merge(res, subs_from, subs_to);
2781 std::vector<MX>& symbol_v, std::vector<MX>& parametric_v,
2782 bool extract_trivial, casadi_int v_offset,
2783 const std::string& v_prefix,
const std::string& v_suffix) {
2785 auto it = symbol_map.
find(node.
get());
2789 if (is_trivial && !extract_trivial) {
2793 if (it==symbol_map.end()) {
2796 symbol_map[node.
get()] = sym;
2799 symbol_v.push_back(sym);
2800 parametric_v.push_back(node);
2811 MX& expr_ret, std::vector<MX>& symbols, std::vector<MX>& parametric,
2813 std::string v_prefix =
"e_";
2814 std::string v_suffix =
"";
2815 bool extract_trivial =
false;
2816 casadi_int v_offset = 0;
2817 for (
auto&&
op : opts) {
2818 if (
op.first ==
"prefix") {
2819 v_prefix = std::string(
op.second);
2820 }
else if (
op.first ==
"suffix") {
2821 v_suffix = std::string(
op.second);
2822 }
else if (
op.first ==
"offset") {
2823 v_offset =
op.second;
2824 }
else if (
op.first ==
"extract_trivial") {
2825 extract_trivial =
op.second;
2827 casadi_error(
"No such option: " + std::string(
op.first));
2830 Function f(
"f", {par}, {expr}, {{
"live_variables",
false},
2831 {
"max_io", 0}, {
"allow_free",
true}});
2835 std::vector< MX > w(ff->workloc_.size()-1);
2841 std::vector< char > expr_status(ff->workloc_.size()-1, 0);
2847 std::vector<MX> res_split;
2851 std::vector<MX > arg1, res1;
2854 std::map<MXNode*, MX> symbol_map;
2857 std::vector<MX> symbol_v, parametric_v;
2860 casadi_int alg_counter = 0;
2861 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2863 w[it->res.front()] = arg_split.at(it->data->segment());
2864 expr_status[it->res.front()] = 1;
2866 MX arg = w[it->arg.front()];
2867 if (expr_status[it->arg.front()]==1) {
2869 extract_trivial, v_offset, v_prefix, v_suffix);
2872 res_split.at(it->data->segment()) = arg;
2875 w[it->res.front()] = it->data;
2876 expr_status[it->res.front()] = 0;
2879 w[it->res.front()] = it->data;
2880 expr_status[it->res.front()] = 2;
2883 arg1.resize(it->arg.size());
2884 for (casadi_int i=0; i<arg1.size(); ++i) {
2885 casadi_int el = it->arg[i];
2886 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : w[el];
2890 char max_status = 0;
2891 for (casadi_int i=0; i<arg1.size(); ++i) {
2892 casadi_int el = it->arg[i];
2894 max_status = std::max(max_status, expr_status[it->arg[i]]);
2897 bool any_tainted = max_status==2;
2901 for (casadi_int i=0; i<arg1.size(); ++i) {
2902 casadi_int el = it->arg[i];
2905 if (el>=0 && expr_status[el]==1) {
2908 extract_trivial, v_offset, v_prefix, v_suffix);
2914 res1.resize(it->res.size());
2915 it->data->eval_mx(arg1, res1);
2918 for (casadi_int i=0; i<res1.size(); ++i) {
2919 casadi_int el = it->res[i];
2923 expr_status[el] = max_status;
2933 parametric = parametric_v;
2937 const MX &sym_lin,
const MX &sym_const,
2938 MX& expr_const,
MX& expr_lin,
MX& expr_nonlin) {
2940 std::vector<MX> in = {sym_const, sym_lin};
2941 std::vector<MX> out = {expr};
2943 Function f(
"f", in, out, {{
"live_variables",
false},
2944 {
"max_io", 0}, {
"allow_free",
true}});
2948 std::vector< std::array<MX, 3> > w(ff->workloc_.size()-1);
2951 std::vector<std::vector<MX> > arg_split(in.size());
2952 for (casadi_int i=0; i<in.size(); ++i) arg_split[i] = in[i].
split_primitives(in[i]);
2955 std::array<std::vector<MX>, 3> res_split;
2956 for (
int k=0;k<3;++k) {
2960 std::vector<std::array<MX, 3> > arg1, res1;
2962 std::array<MX, 3> res;
2965 casadi_int alg_counter = 0;
2966 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2968 MX null =
MX::zeros(arg_split.at(it->data->ind()).at(it->data->segment()).sparsity());
2969 w[it->res.front()][0] =
null;
2970 w[it->res.front()][1] =
null;
2971 w[it->res.front()][2] =
null;
2972 w[it->res.front()][it->data->ind()] = arg_split.at(it->data->ind()).at(it->data->segment());
2975 for (
int i=0;i<3;++i) {
2976 res_split.at(i).at(it->data->segment()) = w[it->arg.front()][i];
2980 w[it->res.front()][0] = it->data;
2981 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2982 w[it->res.front()][2] =
MX::zeros(it->data->sparsity());
2985 w[it->res.front()][0] =
MX::zeros(it->data->sparsity());
2986 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2987 w[it->res.front()][2] = it->data;
2990 arg1.resize(it->arg.size());
2991 for (casadi_int i=0; i<arg1.size(); ++i) {
2992 casadi_int el = it->arg[i];
2993 for (
int k=0;k<3;++k) {
2994 arg1[i][k] = el<0 ?
MX(it->data->dep(i).size()) : w[el][k];
3000 res1.resize(it->res.size());
3001 for (casadi_int i=0;i<it->res.size();++i) {
3002 for (
int k=0;k<3;++k) {
3003 res1[i][k] =
MX::zeros(it->data->sparsity());
3006 it->data->eval_linear(arg1, res1);
3009 for (casadi_int i=0; i<res1.size(); ++i) {
3010 casadi_int el = it->res[i];
3011 for (
int k=0;k<3;++k) {
3012 if (el>=0) w[el][k] = res1[i][k];
3019 for (
int k=0;k<3;++k) {
3022 expr_const = res[0];
3024 expr_nonlin = res[2];
3028 std::vector<MX> s =
symvar(expr);
3031 options[
"never_inline"] =
true;
3033 Dict inline_options;
3034 inline_options[
"never_inline"] =
false;
3035 inline_options[
"always_inline"] =
true;
3036 Dict der_options =
Dict{{
"forward_options", inline_options},
3037 {
"reverse_options", inline_options},
3038 {
"jacobian_options", inline_options}};
3040 options[
"is_diff_in"] = std::vector<bool>{
false};
3041 options[
"is_diff_out"] = std::vector<bool>{
true};
3042 options =
combine(options, der_options);
3043 }
else if (order==2) {
3044 options[
"der_options"] = der_options;
3045 options[
"forward_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
3046 {
"is_diff_out", std::vector<bool>{
true}}};
3047 options[
"reverse_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
3048 {
"is_diff_out", std::vector<bool>{
true}}};
3049 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true} },
3050 {
"is_diff_out", std::vector<bool>{
false}}};
3052 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
3055 Function FS(
"FS", {x}, {expr}, {
"x"}, {
"z"}, options);
3056 return FS(std::vector<MX>{x})[0];
3060 casadi_warning(
"stop_diff(expr, var, order) is not well tested.");
3061 std::vector<MX> xv =
symvar(var);
3062 std::vector<MX> s =
symvar(expr);
3069 options[
"never_inline"] =
true;
3071 Dict inline_options;
3072 inline_options[
"never_inline"] =
false;
3073 inline_options[
"always_inline"] =
true;
3074 Dict der_options =
Dict{{
"forward_options", inline_options},
3075 {
"reverse_options", inline_options},
3076 {
"jacobian_options", inline_options}};
3078 options[
"is_diff_in"] = std::vector<bool>{
false,
true};
3079 options[
"is_diff_out"] = std::vector<bool>{
true};
3080 options =
combine(options, der_options);
3081 }
else if (order==2) {
3082 options[
"der_options"] = der_options;
3083 options[
"forward_options"] =
Dict{{
"is_diff_in",
3084 std::vector<bool>{
false,
true,
false,
true,
true} },
3085 {
"is_diff_out", std::vector<bool>{
true}}};
3086 options[
"reverse_options"] =
Dict{{
"is_diff_in",
3087 std::vector<bool>{
false,
true,
false,
true}},
3088 {
"is_diff_out", std::vector<bool>{
false,
true}}};
3089 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true}},
3090 {
"is_diff_out", std::vector<bool>{
true}}};
3092 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
3095 Function FS(
"FS", {x, y}, {expr}, {
"x",
"y"}, {
"z"}, options);
3096 return FS(std::vector<MX>{x, y})[0];
3101 std::set<MXNode*> bs;
3102 for (
const auto& e : b) {
3103 if (!e.is_null()) bs.insert(e.get());
3105 std::vector<MX> ret;
3106 for (
auto&& e : a) {
3108 if (bs.find(e.get())==bs.end()) {
3117 const std::vector<MX>& xis,
3118 const std::vector<MX>& L,
const std::vector<MX>& Lp,
3119 const std::vector<casadi_int>& strides,
3125 v.
get_nz(ret,
false, offset, I);
3128 casadi_int j = xis.
size()-i;
3129 MX offsetL, offsetR;
3130 if (strides[j]==1) {
3131 offsetL = offset+L[j];
3132 offsetR = offset+Lp[j];
3134 offsetL = offset+L[j]*strides[j];
3135 offsetR = offsetL+strides[j];
3137 MX vl =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetL);
3138 MX vu =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetR);
3141 return vl + xis[j]*(vu-vl);
3148 casadi_int n_dim = x.
size();
3149 std::vector<std::string> lookup_mode(n_dim,
"auto");
3150 for (
auto&&
op : opts) {
3151 if (
op.first==
"lookup_mode") {
3152 lookup_mode =
op.second;
3154 casadi_error(
"Unknown option '" +
op.first +
"'.");
3158 casadi_assert_dev(xq.size()==n_dim);
3162 std::vector<casadi_int> x_dims;
3163 for (
auto e : x) x_dims.push_back(e.numel());
3168 "Dimension mismatch: coefficients (" +
str(v.
numel()) +
") should be "
3169 "an integer multiple of product-of-dimensions (" +
str(
product(x_dims)) +
").");
3172 casadi_int nq = xq[0].numel();
3174 casadi_assert_dev(e.is_vector() && e.numel()==nq);
3178 std::vector<casadi_int> strides;
3179 strides.push_back(
n_out);
3180 for (
auto d : x_dims) strides.push_back(strides.back()*d);
3184 std::vector<MX> xis, Ls, Lps;
3185 for (casadi_int i=0;i<n_dim;++i) {
3186 MX L =
low(x[i], xq[i], {{
"lookup_mode", lookup_mode[i]}});
3189 x[i].
get_nz(xl,
false, L);
3190 x[i].get_nz(xu,
false, Lp);
3191 xis.push_back((xq[i]-xl)/(xu-xl));
3198 return interpn_G(n_dim, v, xis, Ls, Lps, strides, I);
3223 const std::vector<bool>& unique)
const {
3225 res.resize((*this)->nout());
3226 (*this)->eval_mx(arg, res, unique);
3227 }
catch (std::exception& e) {
3228 CASADI_THROW_ERROR_OBJ(
"eval_mx", e.what());
3233 std::vector<std::vector<MX> >& fsens)
const {
3235 (*this)->ad_forward(fseed, fsens);
3236 }
catch (std::exception& e) {
3237 CASADI_THROW_ERROR_OBJ(
"ad_forward", e.what());
3242 std::vector<std::vector<MX> >& asens)
const {
3244 (*this)->ad_reverse(aseed, asens);
3245 }
catch (std::exception& e) {
3246 CASADI_THROW_ERROR_OBJ(
"ad_reverse", e.what());
3250 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3251 std::mutex MX::mutex_temp;
3254 #undef CASADI_THROW_ERROR
static MX create(const MX &x, const MX &coeffs, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > °ree, casadi_int m, const Dict &opts)
static MX create(const MX &x, const std::vector< std::vector< double > > &knots, const std::vector< double > &coeffs, const std::vector< casadi_int > °ree, casadi_int m, const Dict &opts)
static DM dual(const std::vector< double > &x, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > °ree, const Dict &opts)
static MX create_call(const Function &fcn, const std::vector< MX > &arg)
Create function call node.
static ConstantMX * create(const Sparsity &sp, casadi_int val)
Helper class for Serialization.
Internal class for Function.
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.
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.
static Function if_else(const std::string &name, const Function &f_true, const Function &f_false, const Dict &opts=Dict())
Constructor (if-else)
size_t sz_res() const
Get required length of res field.
static Function conditional(const std::string &name, const std::vector< Function > &f, const Function &f_def, const Dict &opts=Dict())
Constuct a switch function.
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
FunctionInternal * get() const
Function mapaccum(const std::string &name, casadi_int N, const Dict &opts=Dict()) const
Create a mapaccumulated version of this function.
Function expand() const
Expand a function to SX.
std::vector< MX > free_mx() const
Get all the free variables of the function.
casadi_int n_nodes() const
Number of nodes in the algorithm.
size_t sz_iw() const
Get required length of iw field.
size_t sz_w() const
Get required length of w field.
size_t sz_arg() const
Get required length of arg field.
Function transform(const Dict &opts=Dict()) const
Apply transformation passes.
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.
void serialize(std::ostream &stream, const Dict &opts=Dict()) const
Serialize.
Sparsity sparsity() const
Get the sparsity pattern.
casadi_int numel() const
Get the number of elements.
bool is_dense() const
Check if the matrix expression is dense.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
casadi_int rows() const
Get the number of rows, Octave-style syntax.
const MX nz(const K &k) const
Get vector nonzero or slice of nonzeros.
bool is_tril() const
Check if the matrix is lower triangular.
bool is_row() const
Check if the matrix is a row vector (i.e. size1()==1)
bool is_triu() const
Check if the matrix is upper triangular.
casadi_int size1() const
Get the first dimension (i.e. number of rows)
std::string dim(bool with_nz=false) const
Get string representation of dimensions.
static MX ones(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries one.
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
const casadi_int * colind() const
Get the sparsity pattern. See the Sparsity class for details.
const casadi_int * row() const
Get the sparsity pattern. See the Sparsity class for details.
bool is_square() const
Check if the matrix expression is square.
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_scalar(bool scalar_and_dense=false) const
Check if the matrix expression is scalar.
SharedObjectInternal * get() const
Get a const pointer to the node.
void own(SharedObjectInternal *node)
SharedObjectInternal * operator->() const
Access a member function or object.
double det(const DM &A) const
Matrix determinant.
DM solve(const DM &A, const DM &B, bool tr=false) const
Internal node class for MXFunction.
std::vector< casadi_int > workloc_
Offsets for elements in the w_ vector.
std::vector< AlgEl > algorithm_
All the runtime elements in the order of evaluation.
Node class for MX objects.
virtual MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz, bool unique=false) const
Get the nonzeros of matrix.
virtual void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const
Evaluate symbolically (MX)
virtual MX get_logsumexp() const
Logsumexp.
virtual bool has_output() const
Check if a multiple output node.
virtual MX get_nzassign(const MX &y, const std::vector< casadi_int > &nz) const
Assign the nonzeros of a matrix to another matrix.
virtual MX get_norm_2() const
Spectral norm.
virtual MX get_output(casadi_int oind) const
Get an output.
virtual bool is_zero() const
Check if identically zero.
virtual MX get_sparsity_cast(const Sparsity &sp) const
Sparsity cast.
virtual MX get_mmax() const
Max.
static bool is_equal(const MXNode *x, const MXNode *y, casadi_int depth)
Check if two nodes are equivalent up to a given depth.
virtual MX get_unary(casadi_int op, bool unique=false) const
Get a unary operation.
virtual MX get_einstein(const MX &A, const MX &B, const std::vector< casadi_int > &dim_c, const std::vector< casadi_int > &dim_a, const std::vector< casadi_int > &dim_b, const std::vector< casadi_int > &c, const std::vector< casadi_int > &a, const std::vector< casadi_int > &b) const
Einstein product and addition.
virtual MX get_solve_triu(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A.
virtual MX get_kron(const MX &b) const
Create a Kronecker-product node.
virtual MX join_primitives(std::vector< MX >::const_iterator &it) const
Join an expression along symbolic primitives.
virtual MX get_dot(const MX &y) const
Inner product.
virtual MX get_repmat(casadi_int m, casadi_int n) const
Create a repeated matrix node.
virtual MX _get_binary(casadi_int op, const MX &y, bool scX, bool scY, bool unique_x=false, bool unique_y=false) const
Get a binary operation operation (matrix-matrix)
virtual MX get_solve_tril(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
virtual casadi_int nout() const
Number of outputs.
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
std::vector< MX > dep_
dependencies - functions that have to be evaluated before this one
MX get_binary(casadi_int op, const MX &y, bool unique_x=false, bool unique_y=false) const
Get a binary operation operation.
MX get_dump(const std::string &base_filename, const Dict &opts) const
Dump.
virtual MX get_norm_1() const
1-norm
virtual MX get_nz_ref(const MX &nz) const
Get the nonzeros of matrix, parametrically.
MX get_monitor(const std::string &comment) const
Monitor.
virtual MX get_reshape(const Sparsity &sp) const
Reshape.
MX get_convexify(const Dict &opts) const
Convexify.
virtual MX get_project(const Sparsity &sp, bool unique=false) const
Create set sparse.
virtual MX get_mac(const MX &y, const MX &z, const std::string &blas="reference") const
Matrix multiplication and addition.
virtual MX get_transpose() const
Transpose.
virtual MX get_norm_fro() const
Frobenius norm.
virtual std::vector< MX > get_diagsplit(const std::vector< casadi_int > &offset1, const std::vector< casadi_int > &offset2) const
Create a diagonal split node.
virtual std::vector< MX > get_horzsplit(const std::vector< casadi_int > &output_offset) const
Create a horizontal split node.
virtual MX get_vertcat(const std::vector< MX > &x) const
Create a vertical concatenation node (vectors only)
virtual MX get_repsum(casadi_int m, casadi_int n) const
Create a repeated sum node.
virtual MX get_mmin() const
Min.
virtual MX get_norm_inf() const
Infinity norm.
MX get_low(const MX &v, const Dict &options) const
Find.
virtual MX get_inv() const
Inverse.
virtual std::vector< MX > get_vertsplit(const std::vector< casadi_int > &output_offset) const
Create a vertical split node (vectors only)
virtual MX get_bilin(const MX &x, const MX &y) const
Bilinear form.
virtual MX get_kron_contract(const MX &x, bool inner) const
Create a Kronecker-contraction node.
virtual std::string disp(const std::vector< std::string > &arg) const =0
Print expression.
virtual MX get_rank1(const MX &alpha, const MX &x, const MX &y) const
Bilinear form.
virtual double to_double() const
Get the value (only for scalar constant nodes)
static MX linspace(const MX &a, const MX &b, casadi_int nsteps)
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const
Called from MXFunction.
void erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Erase a submatrix (leaving structural zeros in its place)
static MX nullspace(const MX &A)
static MX create(MXNode *node)
Create from node.
bool is_multiplication() const
Check if multiplication.
static MX unary(casadi_int op, const MX &x, bool unique=false)
Create nodes by their ID.
void reset_input() const
Reset the marker for an input expression.
static MX _rank1(const MX &A, const MX &alpha, const MX &x, const MX &y)
static MX kron(const MX &x, const MX &b)
bool is_minus_one() const
check if minus one (note that false negative answers are possible)
static MX mmax(const MX &x)
bool is_valid_input() const
Check if matrix can be used to define function inputs.
static MX cumsum(const MX &x, casadi_int axis=-1)
static MX substitute(const MX &ex, const MX &v, const MX &vdef)
static MX lift(const MX &x, const MX &x_guess)
bool is_eye() const
check if identity
bool is_value(double val) const
check if a certain value (note that false negative answers are possible)
static MX horzcat(const std::vector< MX > &x)
const Sparsity & sparsity() const
Get the sparsity pattern.
static std::vector< MX > difference(const std::vector< MX > &a, const std::vector< MX > &b)
static void separate_linear(const MX &expr, const MX &sym_lin, const MX &sym_const, MX &expr_const, MX &expr_lin, MX &expr_nonlin)
bool is_output() const
Check if evaluation output.
casadi_int n_out() const
Number of outputs.
static MX expm_const(const MX &A, const MX &t)
static MX norm_fro(const MX &x)
static MX einstein(const MX &A, const MX &B, const MX &C, const std::vector< casadi_int > &dim_a, const std::vector< casadi_int > &dim_b, const std::vector< casadi_int > &dim_c, const std::vector< casadi_int > &a, const std::vector< casadi_int > &b, const std::vector< casadi_int > &c)
Computes an einstein dense tensor contraction.
casadi_int n_dep() const
Get the number of dependencies of a binary SXElem.
casadi_int n_primitives() const
Get the number of primitives for MXFunction inputs/outputs.
static MX norm_inf(const MX &x)
bool __nonzero__() const
Returns the truth value of an MX expression.
bool is_half() const
check if 0.5 (note that false negative answers are possible)
static std::vector< MX > vertsplit(const MX &x, const std::vector< casadi_int > &offset)
bool is_call() const
Check if evaluation.
std::string name() const
Get the name.
bool has_output() const
Check if a multiple output node.
bool is_integer() const
Check if integer.
static MX jacobian(const MX &f, const MX &x, const Dict &opts=Dict())
Matrix< casadi_int > mapping() const
Get an IM representation of a GetNonzeros or SetNonzeros node.
static std::vector< MX > symvar(const MX &x)
static MX reshape(const MX &x, casadi_int nrow, casadi_int ncol)
static MX find(const MX &x)
static MX norm_2(const MX &x)
bool is_inf() const
check if inf (note that false negative answers are possible)
static bool simplify_const_folding(std::vector< MX > &arg, std::vector< MX > &res, const Dict &opts=Dict())
static MX stop_diff(const MX &expr, casadi_int order)
bool is_constant() const
Check if constant.
static MX eye(casadi_int n)
Identity matrix.
static MX mac(const MX &x, const MX &y, const MX &z, const std::string &blas="reference")
static MX sum1(const MX &x)
static casadi_int get_max_depth()
Get the depth to which equalities are being checked for simplifications.
MXNode * get() const
Get a const pointer to the node.
static void shared(std::vector< MX > &ex, std::vector< MX > &v, std::vector< MX > &vdef, const std::string &v_prefix, const std::string &v_suffix)
static bool contains_any(const std::vector< MX > &v, const std::vector< MX > &n)
static MX inf(const Sparsity &sp)
create a matrix with all inf
MX dump(const std::string &base_filename, const Dict &opts=Dict()) const
Dump an expression.
void reset_dump_count()
Reset the dump counter.
bool is_commutative() const
Check if commutative operation.
static MX project(const MX &x, const Sparsity &sp, bool intersect=false)
static MX pinv(const MX &A, const std::string &lsolver="qr", const Dict &dict=Dict())
std::vector< MX > split_primitives(const MX &x) const
Split up an expression along symbolic primitives.
static MX matrix_expand(const MX &e, const std::vector< MX > &boundary, const Dict &options)
static MX norm_1(const MX &x)
static MX mrdivide(const MX &a, const MX &b)
static MX inv_minor(const MX &A)
static bool is_equal(const MX &x, const MX &y, casadi_int depth=0)
static bool contains_all(const std::vector< MX > &v, const std::vector< MX > &n)
static void extract(std::vector< MX > &ex, std::vector< MX > &v, std::vector< MX > &vdef, const Dict &opts=Dict())
bool has_duplicates() const
Detect duplicate symbolic expressions.
static MX blockcat(const std::vector< std::vector< MX > > &v)
static MX hessian(const MX &f, const MX &x, const Dict &opts=Dict())
static DM evalf(const MX &m)
MX T() const
Transpose the matrix.
void set_temp(casadi_int t) const
Set the temporary variable.
std::vector< MX > get_nonzeros() const
Get nonzeros as list of scalar MXes.
static std::vector< MX > createMultipleOutput(MXNode *node)
Create from node (multiple-outputs)
casadi_int get_temp() const
static MX _bilin(const MX &A, const MX &x, const MX &y)
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const
Called from MXFunction.
static std::vector< MX > cse(const std::vector< MX > &e)
static MX mmin(const MX &x)
static MX solve(const MX &a, const MX &b)
static MX bspline(const MX &x, const DM &coeffs, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > °ree, casadi_int m, const Dict &opts=Dict())
static bool simplify_ref_count(std::vector< MX > &arg, std::vector< MX > &res, const Dict &opts=Dict())
static MX simplify(const MX &x)
static std::vector< bool > which_depends(const MX &expr, const MX &var, casadi_int order=1, bool tr=false)
static void substitute_inplace(const std::vector< MX > &v, std::vector< MX > &vdef, std::vector< MX > &ex, bool reverse)
static std::vector< MX > diagsplit(const MX &x, const std::vector< casadi_int > &offset1, const std::vector< casadi_int > &offset2)
static MX repmat(const MX &x, casadi_int n, casadi_int m=1)
Function which_function() const
Get function - only valid when is_call() is true.
static MX sparsity_cast(const MX &x, const Sparsity &sp)
static MX diag(const MX &x)
static void extract_parametric(const MX &expr, const MX &par, MX &expr_ret, std::vector< MX > &symbols, std::vector< MX > ¶metric, const Dict &opts)
static MX det(const MX &x)
static MX inv_node(const MX &A)
bool is_op(casadi_int op) const
Is it a certain operation.
bool is_minus_inf() const
check if -inf (note that false negative answers are possible)
bool is_norm() const
Check if norm.
std::vector< MX > primitives() const
Get primitives.
static casadi_int n_nodes(const MX &x)
void set_nz(const MX &m, bool ind1, const Slice &kk)
static MX polyval(const MX &p, const MX &x)
static MX graph_substitute(const MX &x, const std::vector< MX > &v, const std::vector< MX > &vdef)
bool is_regular() const
Checks if expression does not contain NaN or Inf.
static MX kron_contract(const MX &m, const MX &x, bool inner)
casadi_int which_output() const
Get the index of evaluation output - only valid when is_output() is true.
static MX repsum(const MX &x, casadi_int n, casadi_int m=1)
MX nzref(const Sparsity &sp, const std::vector< casadi_int > &nz) const
Low-level access to get_nzref.
void serialize(SerializingStream &s) const
Serialize an object.
static MX densify(const MX &x, const MX &val=0)
static std::vector< MX > get_free(const Function &f)
Get free variables.
static bool depends_on(const MX &x, const MX &arg)
MX inv() const
Element-wise inverse.
static MX mtimes(const MX &x, const MX &y, const std::string &blas="reference")
static MX deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static void set_max_depth(casadi_int eq_depth=1)
Set or reset the depth to which equalities are being checked for simplifications.
static MX mldivide(const MX &a, const MX &b)
static Sparsity jacobian_sparsity(const MX &f, const MX &x)
static MX expm(const MX &A)
MX attachAssert(const MX &y, const std::string &fail_message="") const
returns itself, but with an assertion attached
static MX nan(const Sparsity &sp)
create a matrix with all nan
static MX _sym(const std::string &name, const Sparsity &sp)
void set(const MX &m, bool ind1, const Slice &rr)
static DM bspline_dual(const std::vector< double > &x, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > °ree, const Dict &opts=Dict())
static MX trace(const MX &x)
bool is_one() const
check if one (note that false negative answers are possible)
static MX dot(const MX &x, const MX &y)
static MX interpn_linear(const std::vector< MX > &x, const MX &v, const std::vector< MX > &xq, const Dict &opts=Dict())
Low-level access to inlined linear interpolation.
static MX vertcat(const std::vector< MX > &x)
static MX convexify(const MX &H, const Dict &opts=Dict())
static MX _logsumexp(const MX &x)
static MX if_else(const MX &cond, const MX &if_true, const MX &if_false, bool short_circuit=false)
MX join_primitives(const std::vector< MX > &v) const
Join an expression along symbolic primitives.
MX dep(casadi_int ch=0) const
Get the nth dependency as MX.
MX monitor(const std::string &comment) const
Monitor an expression.
static std::vector< MX > horzsplit(const MX &x, const std::vector< casadi_int > &offset)
static MX conditional(const MX &ind, const std::vector< MX > &x, const MX &x_default, bool short_circuit=false)
static MX binary(casadi_int op, const MX &x, const MX &y, bool unique_x=false, bool unique_y=false)
Create nodes by their ID.
bool is_binary() const
Is binary operation.
static std::vector< MX > get_input(const Function &f)
Get function inputs.
bool is_unary() const
Is unary operation.
bool is_zero() const
check if zero (note that false negative answers are possible)
bool is_transpose() const
Is the expression a transpose?
MXNode * operator->()
Access a member of the node.
static bool test_cast(const SharedObjectInternal *ptr)
Check if a particular cast is allowed.
void get_nz(MX &m, bool ind1, const Slice &kk) const
bool is_doubled() const
Check if the node is the sum of two equal expressions.
static MX transform(const MX &x, const Dict &opts=Dict())
static std::string print_operator(const MX &x, const std::vector< std::string > &args)
static std::vector< std::vector< MX > > reverse(const std::vector< MX > &ex, const std::vector< MX > &arg, const std::vector< std::vector< MX > > &v, const Dict &opts=Dict())
bool is_symbolic() const
Check if symbolic.
void enlarge(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge matrix.
MX printme(const MX &b) const
static bool simplify_combine_terms(std::vector< MX > &arg, std::vector< MX > &res, const Dict &opts=Dict())
MX get_output(casadi_int oind) const
Get an output.
static MX diagcat(const std::vector< MX > &x)
static MX low(const MX &v, const MX &p, const Dict &options=Dict())
casadi_int op() const
Get operation type.
static std::vector< std::vector< MX > > forward(const std::vector< MX > &ex, const std::vector< MX > &arg, const std::vector< std::vector< MX > > &v, const Dict &opts=Dict())
static MX sum2(const MX &x)
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique=std::vector< bool >()) const
Evaluate the MX node with new symbolic dependencies.
bool is_nonnegative() const
Check if a value is always nonnegative (false negatives are allowed)
static MX unite(const MX &A, const MX &B)
std::vector< Scalar > & nonzeros()
Matrix< Scalar > T() const
Transpose the matrix.
const Sparsity & sparsity() const
Const access the sparsity - reference to data member.
bool is_regular() const
Checks if expression does not contain NaN or Inf.
static Matrix< Scalar > nullspace(const Matrix< Scalar > &x)
static Matrix< double > eye(casadi_int n)
create an n-by-n identity matrix
Helper class for Serialization.
void tocache(const K &key, const T &value)
const std::unordered_map< K, T > & cache_map() const
bool incache(const K &key, T &value) const
Class representing a Slice.
Slice apply(casadi_int len, bool ind1=false) const
Apply concrete length.
std::vector< casadi_int > all() const
Get a vector of indices.
static MatType veccat(const std::vector< MatType > &x)
static std::vector< casadi_int > offset(const std::vector< MatType > &v, bool vert=true)
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Get the index of an existing non-zero element.
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns.
std::vector< casadi_int > erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Erase rows and/or columns of a matrix.
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.
void enlarge(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge matrix.
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Get the location of all non-zero elements as they would appear in a Dense matrix.
bool is_orthonormal(bool allow_empty=false) const
Are both rows and columns orthonormal ?
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.
Sparsity unite(const Sparsity &y, std::vector< unsigned char > &mapping) const
Union of two sparsity patterns.
bool is_reshape(const Sparsity &y) const
Check if the sparsity is a reshape of another.
Sparsity get_diag(std::vector< casadi_int > &mapping) const
std::vector< casadi_int > get_col() const
Get the column for each non-zero entry.
static Sparsity reshape(const Sparsity &x, casadi_int nrow, casadi_int ncol)
Enlarge matrix.
casadi_int nnz() const
Get the number of (structural) non-zeros.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
std::size_t hash() const
Enlarge matrix.
std::vector< casadi_int > get_row() const
Get the row for each non-zero entry.
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 *.
static Sparsity mtimes(const Sparsity &x, const Sparsity &y, const std::string &blas="reference")
Enlarge matrix.
Represents a symbolic MX.
static ZeroByZero * getInstance()
Get a pointer to the singleton.
Function expmsol(const std::string &name, const std::string &solver, const Sparsity &A, const Dict &opts)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
T product(const std::vector< T > &values)
product
Dict combine(const Dict &first, const Dict &second, bool recurse)
Combine two dicts. First has priority.
std::vector< bool > _which_depends(const MatType &expr, const MatType &var, casadi_int order, bool tr)
Sparsity _jacobian_sparsity(const MatType &expr, const MatType &var)
CASADI_EXPORT std::string replace(const std::string &s, const std::string &p, const std::string &r)
Replace all occurences of p with r in s.
void sort(const std::vector< T > &values, std::vector< T > &sorted_values, std::vector< casadi_int > &indices, bool invert_indices=false)
Sort the data in a vector.
std::vector< MX > trim_empty(const std::vector< MX > &x, bool both=false)
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
MX register_symbol(const MX &node, std::map< MXNode *, MX > &symbol_map, std::vector< MX > &symbol_v, std::vector< MX > ¶metric_v, bool extract_trivial, casadi_int v_offset, const std::string &v_prefix, const std::string &v_suffix)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void hash_combine(std::size_t &seed, T v)
Generate a hash value incrementally (function taken from boost)
bool any(const std::vector< bool > &v)
Check if any arguments are true.
MX get_const(const Sparsity &sp, const double *v, std::unordered_multimap< std::size_t, std::pair< MX, DM > > &cache)
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
MX interpn_G(casadi_int i, const MX &v, const std::vector< MX > &xis, const std::vector< MX > &L, const std::vector< MX > &Lp, const std::vector< casadi_int > &strides, const Slice &I, const MX &offset=0)
std::vector< T > reverse(const std::vector< T > &v)
Reverse a list.
bool simplify_const_folding_order(std::vector< MX > &arg, std::vector< MX > &res, const Dict &opts)
Dict extract_from_dict(const Dict &d, const std::string &key, T &value)
bool has_empty(const std::vector< MX > &x, bool both=false)
Operation
Enum for quick access to any node.
Easy access to all the functions for a particular type.