26 #include "mx_node.hpp"
27 #include "symbolic_mx.hpp"
28 #include "constant_mx.hpp"
29 #include "multiple_output.hpp"
30 #include "casadi_misc.hpp"
32 #include "calculus.hpp"
33 #include "mx_function.hpp"
36 #include "serializing_stream.hpp"
38 #include "bspline.hpp"
39 #include "casadi_call.hpp"
43 #define CASADI_THROW_ERROR(FNAME, WHAT) \
44 throw CasadiException("Error in MX::" FNAME " at " + CASADI_WHERE + ":\n"\
48 #define CASADI_THROW_ERROR_OBJ(FNAME, WHAT) \
49 throw CasadiException("Error in MX::" FNAME " for node of type " \
50 + this->class_name() + " at " + CASADI_WHERE + ":\n" + std::string(WHAT));
63 MX::MX(
MXNode* node,
bool dummy1,
bool dummy2,
bool dummy3,
bool dummy4) {
68 return MX(node,
false,
false,
false,
false);
79 MX::MX(
const std::vector<double>& x) {
92 *
this = val->
get_nzref(sp, std::vector<casadi_int>(sp.
nnz(), 0));
108 MX::MX(casadi_int nrow, casadi_int ncol) {
112 MX::MX(
const std::pair<casadi_int, casadi_int>& rc) {
129 casadi_assert_dev(
dynamic_cast<MultipleOutput*
>(node) !=
nullptr);
131 std::vector<MX> ret(x->
nout());
132 for (casadi_int i=0; i<ret.size(); ++i) {
136 }
else if (ret[i].
nnz()==0) {
137 ret[i] =
MX(ret[i].
size());
144 return (*this)->__nonzero__();
165 "Marix::get: First index must be a dense vector");
167 "Marix::get: Second index must be a dense vector");
170 std::vector<casadi_int>
mapping;
185 return get_nz(m, ind1, rr);
192 std::vector<casadi_int>
mapping;
202 "get(Sparsity sp): shape mismatch. This matrix has shape "
203 +
str(
size()) +
", but supplied sparsity index has shape "
209 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices."
210 "Got " +
dim(
true) +
" instead.");
215 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices. ");
220 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
225 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
247 return set(m, ind1, rr.
T(), cc);
252 return set(m, ind1, rr, cc.
T());
257 "MX::set: First index not dense vector");
259 "MX::set: Second index not dense vector");
269 return set(m.
T(), ind1, rr, cc);
272 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size1()) +
"-by-"
281 casadi_assert_in_range(rr.
nonzeros(), -sz1+ind1, sz1+ind1);
282 casadi_assert_in_range(cc.
nonzeros(), -sz2+ind1, sz2+ind1);
291 for (casadi_int j=0; j<el.
size2(); ++j) {
292 casadi_int this_j = cc->at(j) - ind1;
293 if (this_j<0) this_j += sz2;
294 for (casadi_int k=el.
colind(j); k<el.
colind(j+1); ++k) {
295 casadi_int i = m.
row(k);
296 casadi_int this_i = rr->at(i) - ind1;
297 if (this_i<0) this_i += sz1;
298 el->at(k) = this_i + this_j*sz1;
301 return set(m,
false, el);
331 return set(m.
T(), ind1, rr);
334 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size())
335 +
", while rhs is " +
str(m.
size()));
346 casadi_assert_in_range(rr.
nonzeros(), -nel+ind1, nel+ind1);
350 return set_nz(m, ind1, rr);
356 new_row.reserve(sz+rrsz);
357 new_col.reserve(sz+rrsz);
359 for (std::vector<casadi_int>::iterator i=
nz.begin(); i!=
nz.end(); ++i) {
362 new_row.push_back(*i % sz1);
363 new_col.push_back(*i / sz1);
379 "set(Sparsity sp): shape mismatch. This matrix has shape "
380 +
str(
size()) +
", but supplied sparsity index has shape "
382 std::vector<casadi_int> ii = sp.
find();
406 casadi_int sz =
nnz();
407 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
410 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
412 for (
auto&& i : kk_mod.
nonzeros()) {
413 casadi_assert(!(ind1 && i<=0),
414 "Matlab is 1-based, but requested index " +
str(i) +
". "
415 "Note that negative slices are disabled in the Matlab interface. "
416 "Possibly you may want to use 'end'.");
435 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1.0: outer);
440 m = (*this)->
get_nz_ref(ind1 ? inner-1: inner, ind1 ? outer-1.0: outer);
445 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1: outer);
454 casadi_assert(kk.
nnz()==m.
nnz() || m.
nnz()==1,
455 "MX::set_nz: length of non-zero indices (" +
str(kk.
nnz()) +
") " +
456 "must match size of rhs (" +
str(m.
nnz()) +
").");
470 return set_nz(m.
T(), ind1, kk);
473 casadi_error(
"Dimension mismatch. lhs is " +
str(kk.
size())
474 +
", while rhs is " +
str(m.
size()));
481 return set_nz(m_copy, ind1, kk);
485 casadi_int sz =
nnz();
486 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
489 if (kk.
nnz()==0)
return;
492 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
494 for (
auto&& i : kk_mod.
nonzeros()) {
495 casadi_assert(!(ind1 && i<=0),
496 "Matlab is 1-based, but requested index " +
str(i) +
". "
497 "Note that negative slices are disabled in the Matlab interface. "
498 "Possibly you may want to use 'end'.");
502 return set_nz(m,
false, kk_mod);
534 ", x is " + x.
dim() +
", while y is " + y.
dim());
560 MX MX::inf(
const std::pair<casadi_int, casadi_int> &rc) {
561 return inf(rc.first, rc.second);
572 MX MX::nan(
const std::pair<casadi_int, casadi_int>& rc) {
573 return nan(rc.first, rc.second);
585 if ((*this)->op()==
OP_NEG) {
586 return (*this)->
dep(0);
593 return (*this)->sparsity();
596 void MX::erase(
const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
bool ind1) {
601 std::vector<casadi_int>
mapping = sp.
erase(rr, cc, ind1);
613 for (
const MX& e : p) {
620 for (casadi_int i=0; i<
nz.
nnz(); ++i) {
621 ret.push_back(
nz(i));
628 void MX::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
643 const std::vector<casadi_int>& rr,
644 const std::vector<casadi_int>& cc,
bool ind1) {
646 sp.
enlarge(nrow, ncol, rr, cc, ind1);
663 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
664 const std::vector<casadi_int>& dim_c,
665 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
666 const std::vector<casadi_int>& c) {
667 return C->get_einstein(A,
B, dim_c, dim_a, dim_b, c, a, b);
671 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
672 const std::vector<casadi_int>& dim_c,
673 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
674 const std::vector<casadi_int>& c) {
679 if (axis==-1) axis = x.
is_row();
680 MX r = axis==0 ? x.
T() : x;
687 MX ret = f(std::vector<MX>{0, r})[0];
689 return axis==0 ? ret.
T() : ret;
700 "Matrix product with incompatible dimensions. Lhs is "
701 + x.
dim() +
" and rhs is " + y.
dim() +
".");
725 "Error in attachAssert: assertion expression y must be scalar, "
726 "but got " + y.
dim());
727 return(*this)->get_assert(y, fail_message);
740 Function f(
"f", std::vector<MX>{}, {m}, {{
"allow_free",
true}});
741 return f(std::vector<DM>{})[0];
755 return (*this)->
dep(ch);
759 return (*this)->n_dep();
763 return (*this)->name();
779 return (*this)->which_function();
783 return (*this)->is_output();
787 return (*this)->has_output();
791 return (*this)->which_output();
795 return (*this)->op()==
op;
803 return dynamic_cast<const Norm*
>(
get())!=
nullptr;
806 MX::operator double()
const {
810 MX::operator
DM()
const {
811 return (*this)->get_DM();
815 return (*this)->is_binary();
819 return (*this)->is_unary();
823 return (*this)->op();
827 return (*this)->info();
831 return (*this)->serialize(s);
853 "MX::is_commutative: must be binary or unary operation");
854 return operation_checker<CommChecker>(
op());
858 return (*this)->mapping();
862 return (*this)->temp;
870 return (*this)->nout();
882 casadi_assert(sp.
size()==x.
size(),
"Cannot project " + x.
dim() +
" to " + sp.
dim());
889 }
catch (std::exception& e) {
890 CASADI_THROW_ERROR(
"project", e.what());
907 casadi_int MX::eq_depth_ = 1;
910 eq_depth_ = eq_depth;
926 return (*this)->is_valid_input();
930 return (*this)->n_primitives();
935 std::vector<MX>::iterator it=ret.begin();
936 (*this)->primitives(it);
937 casadi_assert_dev(it==ret.end());
943 std::vector<MX>::iterator it=ret.begin();
944 (*this)->split_primitives(x, it);
945 casadi_assert_dev(it==ret.end());
951 std::vector<SX>::iterator it=ret.begin();
952 (*this)->split_primitives(x, it);
953 casadi_assert_dev(it==ret.end());
959 std::vector<DM>::iterator it=ret.begin();
960 (*this)->split_primitives(x, it);
961 casadi_assert_dev(it==ret.end());
966 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
967 std::vector<MX>::const_iterator it=v.begin();
969 casadi_assert_dev(it==v.end());
974 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
975 std::vector<SX>::const_iterator it=v.begin();
976 SX ret = (*this)->join_primitives(it);
977 casadi_assert_dev(it==v.end());
982 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
983 std::vector<DM>::const_iterator it=v.begin();
984 DM ret = (*this)->join_primitives(it);
985 casadi_assert_dev(it==v.end());
990 return (*this)->has_duplicates();
994 (*this)->reset_input();
998 return (*this)->is_eye();
1005 return (*this)->is_zero();
1010 return (*this)->is_one();
1014 return (*this)->is_value(-1);
1025 casadi_error(
"Cannot check regularity for symbolic MX");
1034 return dynamic_cast<const MXNode*
>(ptr)!=
nullptr;
1039 for (
auto&& i : x) {
1040 if (i.is_empty(both))
return true;
1045 std::vector<MX>
trim_empty(
const std::vector<MX>& x,
bool both=
false) {
1046 std::vector<MX> ret;
1047 for (
auto&& i : x) {
1048 if (!i.is_empty(both)) ret.push_back(i);
1057 for (casadi_int i=0;i<
ne.
size();i++) {
1059 "horzcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1060 " and x[0]: " +
ne[0].
dim() +
".");
1066 }
else if (x.size()==1) {
1074 casadi_int nrow = 0;
1075 for (casadi_int i=0;i<ret.size();++i) {
1077 casadi_assert_dev(nrow==0 || nrow==ret[i].
size1());
1078 nrow = ret[i].size1();
1085 return x.front()->get_horzcat(x);
1091 if (x.empty())
return MX();
1092 if (x.size()==1)
return x.front();
1096 return x.front()->get_diagcat(x);
1103 for (casadi_int i=0;i<
ne.
size();i++) {
1105 "vertcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1106 " and x[0]: " +
ne[0].
dim() +
".");
1112 }
else if (x.size()==1) {
1120 casadi_int ncol = 0;
1121 for (casadi_int i=0;i<ret.size();++i) {
1123 casadi_assert_dev(ncol==0 || ret[i].
size2()==ncol);
1124 ncol = ret[i].size2();
1130 }
else if (!x.front().is_column()) {
1132 std::vector<MX> xT = x;
1133 for (std::vector<MX>::iterator i=xT.begin(); i!=xT.end(); ++i) *i = i->T();
1142 casadi_assert_dev(!
offset.empty());
1143 casadi_assert_dev(
offset.front()==0);
1149 return std::vector<MX>(0);
1150 }
else if (
offset.size()==2) {
1151 return std::vector<MX>(1, x);
1158 const std::vector<casadi_int>& offset2) {
1160 casadi_assert_dev(!offset1.empty());
1161 casadi_assert_dev(offset1.front()==0);
1162 casadi_assert_dev(offset1.back()==x.
size1());
1166 casadi_assert_dev(!offset2.empty());
1167 casadi_assert_dev(offset2.front()==0);
1168 casadi_assert_dev(offset2.back()==x.
size2());
1177 casadi_assert_dev(!
offset.empty());
1178 casadi_assert_dev(
offset.front()==0);
1184 return std::vector<MX>();
1185 }
else if (
offset.size()==2) {
1186 return std::vector<MX>(1, x);
1192 for (
auto&& e : ret) e = e.T();
1199 if (v.empty())
return MX(0, 0);
1202 casadi_int ncols = v.front().size();
1203 for (
auto&& e : v) {
1204 casadi_assert(e.size()==ncols,
"blockcat: Inconsistent number of block columns");
1208 if (v.front().empty())
return MX(0, 0);
1211 std::vector<MX>
rows;
1212 for (
auto&& e : v) {
1244 if (nrow==x.
size1() && ncol==x.
size2())
return x;
1261 casadi_assert(x.
nnz()==sp.
nnz(),
1262 "Mismatching nonzero count: " +
str(x.
nnz()) +
" versus " +
1273 if (short_circuit) {
1275 std::vector<MX> arg =
symvar(
veccat(std::vector<MX>{x_true, x_false}));
1278 Function f_true(
"f_true", arg, {x_true});
1279 Function f_false(
"f_false", arg, {x_false});
1285 std::vector<MX> sw_arg;
1286 sw_arg.push_back(cond);
1287 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1288 return sw(sw_arg).at(0);
1295 const MX& x_default,
bool short_circuit) {
1296 if (short_circuit) {
1298 std::vector<MX> arg = x;
1299 arg.push_back(x_default);
1303 std::vector<Function> f(x.size());
1304 for (casadi_int k=0; k<x.size(); ++k) {
1305 std::stringstream ss;
1306 ss <<
"f_case" << k;
1307 f[k] =
Function(ss.str(), arg, {x[k]});
1309 Function f_default(
"f_default", arg, {x_default});
1315 std::vector<MX> sw_arg;
1316 sw_arg.push_back(ind);
1317 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1318 return sw(sw_arg).at(0);
1321 for (casadi_int k=0; k<x.size(); ++k) {
1322 ret =
if_else(ind==
static_cast<double>(k), x[k], ret);
1330 std::vector<unsigned char>
mapping;
1334 std::vector<casadi_int> nzA, nzB;
1350 ret =
B->get_nzassign(ret, nzB);
1355 casadi_assert(x.
is_square(),
"trace: must be square");
1357 for (casadi_int i=0; i < x.
size2(); i ++) {
1365 std::vector<casadi_int>
mapping;
1375 Dict opts{{
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}};
1376 Function f(
"tmp_n_nodes", std::vector<MX>{}, {x}, opts);
1389 casadi_assert(p.
is_dense(),
"polynomial coefficients vector must be a vector");
1390 casadi_assert(p.
is_column() && p.
nnz()>0,
"polynomial coefficients must be a vector");
1392 for (casadi_int i=1; i<p.
nnz(); ++i) {
1393 ret = ret*x + p.
nz(i);
1399 return x->
disp(args);
1403 std::vector<MX>& ex,
bool reverse) {
1404 casadi_assert(v.size()==vdef.size(),
1405 "Mismatch in the number of expression to substitute.");
1406 for (casadi_int k=0; k<v.size(); ++k) {
1408 "Variable " +
str(k) +
" is not symbolic");
1409 casadi_assert(v[k].
size() == vdef[k].
size(),
1410 "Inconsistent shape for variable " +
str(k) +
".");
1412 casadi_assert(
reverse==
false,
"Not implemented");
1415 if (v.empty())
return;
1418 std::vector<MX> f_out = vdef;
1419 f_out.insert(f_out.end(), ex.begin(), ex.end());
1420 Function temp(
"tmp_substitute_inplace", {v}, f_out,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1425 return substitute(std::vector<MX>{ex}, std::vector<MX>{v}, std::vector<MX>{vdef}).front();
1429 const std::vector<MX> &vdef) {
1431 casadi_assert_dev(v.size()==vdef.size());
1434 bool all_equal =
true;
1435 for (casadi_int k=0; k<v.size(); ++k) {
1441 if (all_equal)
return ex;
1444 Function F(
"tmp_substitute", v, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1445 std::vector<MX> ret;
1446 F.
call(vdef, ret,
true);
1451 const std::vector<MX> &vdef) {
1456 const std::vector<MX> &vdef,
bool& updated) {
1461 const std::vector<MX>& v,
1462 const std::vector<MX>& vdef) {
1467 const std::vector<MX>& v,
1468 const std::vector<MX>& vdef,
1470 casadi_assert(v.size()==vdef.size(),
1471 "Mismatch in the number of expression to substitute: "
1472 +
str(v.size()) +
" <-> " +
str(vdef.size()) +
".");
1477 bool all_equal =
true;
1478 for (casadi_int k=0; k<v.size(); ++k) {
1484 if (all_equal)
return ex;
1487 for (casadi_int i=0;i<v.size();++i) {
1488 casadi_assert(v[i].
size()==vdef[i].
size(),
1489 "Inconsistent shapes for i = " +
str(i) +
": v[i] " + v[i].
dim() +
1490 " <-> vdef[i] " + vdef[i].
dim());
1494 Dict opts({{
"max_io", 0}, {
"allow_free",
true}});
1495 Function f(
"tmp_graph_substitute", std::vector<MX>{}, ex, opts);
1499 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1500 std::vector<MX> swork(ff->workloc_.size()-1);
1503 std::vector<bool> tainted(swork.size());
1506 std::stringstream ss;
1510 std::map<const MXNode*, casadi_int> expr_lookup;
1511 for (casadi_int i=0;i<v.size();++i) {
1512 auto it = expr_lookup.find(v[i].operator->());
1513 if (it==expr_lookup.end()) expr_lookup[v[i].operator->()] = i;
1517 std::vector<bool> expr_found(v.size(),
false);
1520 std::vector<MX> f_out(f.n_out());
1521 std::vector<MX> oarg, ores;
1524 std::map<const MXNode*, casadi_int>::const_iterator it_lookup;
1527 std::vector<std::vector<MX>> out_split(ex.size());
1528 for (casadi_int i = 0; i < out_split.size(); ++i) out_split[i].resize(ex[i].
n_primitives());
1530 for (
auto it=algorithm.begin(); it!=algorithm.end(); ++it) {
1534 it_lookup = expr_lookup.find((it->data).operator->());
1536 if (it_lookup!=expr_lookup.end()) {
1538 MX e = vdef[it_lookup->second];
1542 for (casadi_int i=0;i<it->res.size();++i) {
1543 casadi_int k = it->res[i];
1550 swork[it->res.front()] = e;
1551 tainted[it->res.front()] =
true;
1553 expr_found[it_lookup->second] =
true;
1555 }
else if (it->data->has_output()) {
1556 bool any_tainted =
false;
1558 for (casadi_int i=0;i<it->res.size();++i) {
1560 casadi_int k = it->res[i];
1564 it_lookup = expr_lookup.
find(out.operator->());
1565 if (it_lookup!=expr_lookup.end()) {
1567 MX e = vdef[it_lookup->second];
1571 expr_found[it_lookup->second] =
true;
1575 if (any_tainted)
continue;
1581 tainted[it->res.front()] =
false;
1584 swork[it->res.front()] = it->data;
1585 tainted[it->res.front()] =
false;
1588 out_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
1592 bool node_tainted =
false;
1595 oarg.resize(it->arg.size());
1596 for (casadi_int i=0; i<oarg.size(); ++i) {
1597 casadi_int el = it->arg[i];
1598 if (el>=0) node_tainted = node_tainted || tainted[el];
1599 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : swork.at(el);
1603 ores.resize(it->res.size());
1604 if (!node_tainted) {
1605 if (it->data.has_output()) {
1606 for (casadi_int i=0;i<it->res.size();++i) {
1607 ores.at(i) = it->data.get_output(i);
1610 ores.at(0) = it->data;
1613 it->data->eval_mx(oarg, ores);
1617 for (casadi_int i=0; i<ores.size(); ++i) {
1618 casadi_int el = it->res[i];
1619 if (el>=0) swork.at(el) = ores[i];
1620 if (el>=0) tainted[el] = node_tainted;
1627 for (
size_t k = 0; k < out_split.size(); ++k) {
1628 f_out[k] = ex[k].join_primitives(out_split.at(k));
1631 bool all_found=
true;
1632 for (casadi_int i=0;i<v.size();++i) {
1633 all_found = all_found && expr_found[i];
1636 updated =
any(expr_found);
1643 std::vector<MX>& vdef,
const Dict& opts) {
1646 std::string v_prefix =
"v_", v_suffix =
"";
1647 bool lift_shared =
true, lift_calls =
false;
1648 casadi_int v_ind = 0;
1649 for (
auto&&
op : opts) {
1650 if (
op.first ==
"prefix") {
1651 v_prefix = std::string(
op.second);
1652 }
else if (
op.first ==
"suffix") {
1653 v_suffix = std::string(
op.second);
1654 }
else if (
op.first ==
"lift_shared") {
1655 lift_shared =
op.second;
1656 }
else if (
op.first ==
"lift_calls") {
1657 lift_calls =
op.second;
1658 }
else if (
op.first ==
"offset") {
1661 casadi_error(
"No such option: " + std::string(
op.first));
1665 Function f(
"tmp_extract", std::vector<MX>{}, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1668 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1669 std::vector<MX> work(ff->workloc_.size()-1);
1671 std::vector<casadi_int> usecount(work.size(), 0);
1673 std::vector<std::pair<casadi_int, casadi_int> > origin(work.size(), std::make_pair(-1, -1));
1675 std::vector<std::pair<casadi_int, casadi_int> >
replace;
1678 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1685 for (casadi_int c=0; c<it->arg.size(); ++c) {
1687 if (lift_calls && it->op ==
OP_CALL) {
1689 if (usecount.at(it->arg[c]) >= 0) {
1690 replace.push_back(origin.at(it->arg[c]));
1691 usecount.at(it->arg[c]) = -1;
1693 }
else if (lift_shared && work[it->arg[c]].op() !=
OP_PARAMETER
1694 && work[it->arg[c]].op() !=
OP_CONST) {
1695 if (usecount.at(it->arg[c]) == 0) {
1697 usecount.at(it->arg[c]) = 1;
1698 }
else if (usecount.at(it->arg[c]) == 1) {
1700 replace.push_back(origin.at(it->arg[c]));
1701 usecount.at(it->arg[c]) = -1;
1711 usecount[it->res.front()] = -1;
1714 for (casadi_int c=0; c<it->res.size(); ++c) {
1715 if (it->res[c]>=0) {
1716 work[it->res[c]] = it->data.get_output(c);
1717 origin[it->res[c]] = std::make_pair(k, c);
1718 if (lift_calls && it->op ==
OP_CALL) {
1720 replace.push_back(origin.at(it->res[c]));
1721 usecount.at(it->res[c]) = -1;
1723 usecount.at(it->res[c]) = 0;
1739 std::vector<std::pair<casadi_int, casadi_int> >::const_iterator replace_it=
replace.begin();
1741 std::vector<MX> oarg, ores;
1744 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1747 casadi_assert(it->data->segment()==0,
"Not implemented");
1748 ex[it->data->ind()] = work[it->arg.front()];
1751 work[it->res.front()] = it->data;
1757 work[it->res.front()] = it->data;
1760 oarg.resize(it->arg.size());
1761 for (casadi_int i=0; i<oarg.size(); ++i) {
1762 casadi_int el = it->arg[i];
1763 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : work.at(el);
1766 ores.resize(it->res.size());
1767 it->data->eval_mx(oarg, ores);
1769 for (casadi_int i=0; i<ores.size(); ++i) {
1770 casadi_int el = it->res[i];
1771 if (el>=0) work.at(el) = ores[i];
1775 for (casadi_int c=0; c<it->res.size(); ++c) {
1777 casadi_int ind = it->res[c];
1779 bool replace_node = replace_it !=
replace.end()
1780 && replace_it->first==k && replace_it->second==c;
1782 bool output_node = lift_calls && it->op ==
OP_CALL;
1784 if (!replace_node && !output_node)
continue;
1787 v.push_back(
MX::sym(v_prefix + std::to_string(v_ind++) + v_suffix, v_sp));
1791 casadi_assert(replace_node,
"Consistency check");
1793 vdef.push_back(work[ind]);
1795 work[ind] = v.back();
1800 casadi_assert(output_node,
"Consistency check");
1802 vdef.push_back(ores.at(c));
1809 casadi_assert(replace_it ==
replace.end(),
"Consistency check failed");
1810 }
catch (std::exception& e) {
1811 CASADI_THROW_ERROR(
"extract", e.what());
1815 void MX::shared(std::vector<MX>& ex, std::vector<MX>& v, std::vector<MX>& vdef,
1816 const std::string& v_prefix,
const std::string& v_suffix) {
1818 return extract(ex, v, vdef,
Dict{{
"lift_shared",
true}, {
"lift_calls",
false},
1819 {
"prefix", v_prefix}, {
"suffix", v_suffix}});
1826 h_opts[
"allow_free"] =
true;
1827 Function h(
"helper_jacobian_MX", {x}, {f}, h_opts);
1829 }
catch (std::exception& e) {
1830 CASADI_THROW_ERROR(
"jacobian", e.what());
1836 return hessian(f, x, g, opts);
1841 Dict all_opts = opts;
1843 if (!opts.count(
"symmetric")) all_opts[
"symmetric"] =
true;
1845 }
catch (std::exception& e) {
1846 CASADI_THROW_ERROR(
"hessian", e.what());
1850 std::vector<std::vector<MX> >
1852 const std::vector<MX> &arg,
1853 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1856 bool always_inline =
true;
1857 bool never_inline =
false;
1861 h_opts[
"allow_free"] =
true;
1862 for (
auto&&
op : opts_remainder) {
1863 if (
op.first==
"always_inline") {
1864 always_inline =
op.second;
1865 }
else if (
op.first==
"never_inline") {
1866 never_inline =
op.second;
1868 casadi_error(
"No such option: " + std::string(
op.first));
1872 Function temp(
"forward_temp", arg, ex, h_opts);
1873 std::vector<std::vector<MX> > ret;
1874 temp->
call_forward(arg, ex, v, ret, always_inline, never_inline);
1876 }
catch (std::exception& e) {
1877 CASADI_THROW_ERROR(
"forward", e.what());
1881 std::vector<std::vector<MX> >
1883 const std::vector<MX> &arg,
1884 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1887 bool always_inline =
true;
1888 bool never_inline =
false;
1893 h_opts[
"allow_free"] =
true;
1895 for (
auto&&
op : opts_remainder) {
1896 if (
op.first==
"always_inline") {
1897 always_inline =
op.second;
1898 }
else if (
op.first==
"never_inline") {
1899 never_inline =
op.second;
1901 casadi_error(
"No such option: " + std::string(
op.first));
1905 Function temp(
"reverse_temp", arg, ex, h_opts);
1906 std::vector<std::vector<MX> > ret;
1907 temp->
call_reverse(arg, ex, v, ret, always_inline, never_inline);
1909 }
catch (std::exception& e) {
1910 CASADI_THROW_ERROR(
"reverse", e.what());
1931 casadi_error(
"Not implemented");
1939 Function f(
"f", std::vector<MX>{}, {x}, {{
"allow_free",
true}});
1944 return matrix_expand(std::vector<MX>{e}, boundary, options).at(0);
1948 const std::vector<MX> &boundary,
1949 const Dict &options) {
1952 std::vector<MX> syms(boundary.size());
1954 for (casadi_int i=0;i<syms.size();++i) {
1965 Function f(
"tmp_matrix_expand", v, ret,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1977 std::vector< std::vector< MX > > blocks(a.
size1(), std::vector< MX >(a.
size2(), filler));
1978 for (casadi_int i=0; i<a.
size1(); ++i) {
1979 for (casadi_int j=0; j<a.
size2(); ++j) {
1980 casadi_int k = a_sp.
get_nz(i, j);
1982 blocks[i][j] = a.
nz(k)*b;
1996 }
else if (n==1 && m==1) {
2021 return solve(a, b,
"qr");
2028 return mysolver.
solve(a, b,
false);
2041 opts[
"const_A"] =
true;
2043 return ret(std::vector<MX>{A, t})[0];
2048 return ret(std::vector<MX>{A, 1})[0];
2058 if (x.
nnz()==0)
return false;
2061 Function temp(
"tmp_depends_on", {arg}, {x},
Dict{{
"max_io", 0}, {
"allow_free",
true}});
2064 std::vector<bvec_t> t_in(arg.
nnz(), 1), t_out(x.
nnz());
2068 for (casadi_int i=0; i<t_out.size(); ++i) {
2069 if (t_out[i])
return true;
2077 if (n.empty())
return true;
2080 std::set<MXNode*> l;
2081 for (
const MX& e : v) l.insert(e.get());
2083 size_t l_unique = l.size();
2085 for (
const MX& e : n) l.insert(e.get());
2087 return l.size()==l_unique;
2091 if (n.empty())
return true;
2094 std::set<MXNode*> l;
2095 for (
const MX& e : v) l.insert(e.get());
2097 size_t l_unique = l.size();
2099 std::set<MXNode*> r;
2100 for (
const MX& e : n) r.insert(e.get());
2102 size_t r_unique = r.size();
2103 for (
const MX& e : n) l.insert(e.get());
2105 return l.size()<l_unique+r_unique;
2113 return p->
get_low(v, options);
2118 const std::vector< std::vector<double> >& knots,
2119 const std::vector<casadi_int>& degree,
2126 const std::vector< std::vector<double> >& knots,
2127 const std::vector<casadi_int>& degree,
2134 const std::vector< std::vector<double> >& knots,
2135 const std::vector<casadi_int>& degree,
2146 class IncrementalSerializerMX {
2149 IncrementalSerializerMX() : serializer(ss) {
2152 std::string pack(
const MX& a) {
2155 if (a.is_empty())
return "";
2161 a.serialize(serializer);
2164 a.serialize(serializer);
2165 std::string ret = ss.str();
2172 std::stringstream ss;
2174 std::vector<MX> ref;
2175 SerializingStream serializer;
2179 std::vector<MX>
MX::cse(
const std::vector<MX>& e) {
2180 std::vector<MX> orig = e;
2181 bool updated =
true;
2183 Function f(
"f", std::vector<MX>{}, orig,
2184 {{
"live_variables",
false}, {
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}});
2188 std::vector<MX> swork(ff->workloc_.size()-1);
2191 std::vector<std::vector<MX> > res_split(orig.size());
2192 for (casadi_int i=0; i<orig.size(); ++i) res_split[i].resize(orig[i].
n_primitives());
2194 std::vector<MX> arg1, res1;
2195 std::vector<MX> res(orig.size());
2197 std::unordered_map<std::string, MX > cache;
2198 IncrementalSerializerMX s;
2200 std::unordered_map<FunctionInternal*, Function> function_cache;
2203 casadi_int alg_counter = 0;
2204 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2209 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2212 MX& target = swork[it->res.front()];
2214 cache[s.pack(target)] = target;
2218 arg1.resize(it->arg.size());
2219 for (casadi_int i=0; i<arg1.size(); ++i) {
2220 casadi_int el = it->arg[i];
2221 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : swork[el];
2225 res1.resize(it->res.size());
2226 it->data->eval_mx(arg1, res1);
2229 for (casadi_int i=0; i<res1.size(); ++i) {
2230 casadi_int el = it->res[i];
2232 MX& out_i = res1[i];
2235 casadi_int output_node = -1;
2240 out_i = out_i.
dep(0);
2245 auto itk = function_cache.
find(key);
2246 if (itk==function_cache.end()) {
2256 std::string key = s.pack(out_i);
2258 auto itk = cache.find(key);
2259 if (itk==cache.end()) {
2262 out_i = itk->second;
2265 if (output_node==-1) {
2275 if (el>=0) swork[el] = out_i;
2281 for (casadi_int i=0; i<res.size(); ++i) res[i] = orig[i].
join_primitives(res_split[i]);
2283 std::vector<MX> subs_from;
2284 std::vector<MX> subs_to;
2285 for (
const auto& e : function_cache) {
2286 e.second->merge(res, subs_from, subs_to);
2295 std::vector<MX>& symbol_v, std::vector<MX>& parametric_v,
2296 bool extract_trivial, casadi_int v_offset,
2297 const std::string& v_prefix,
const std::string& v_suffix) {
2299 auto it = symbol_map.
find(node.
get());
2303 if (is_trivial && !extract_trivial) {
2307 if (it==symbol_map.end()) {
2310 symbol_map[node.
get()] = sym;
2313 symbol_v.push_back(sym);
2314 parametric_v.push_back(node);
2325 MX& expr_ret, std::vector<MX>& symbols, std::vector<MX>& parametric,
2327 std::string v_prefix =
"e_";
2328 std::string v_suffix =
"";
2329 bool extract_trivial =
false;
2330 casadi_int v_offset = 0;
2331 for (
auto&&
op : opts) {
2332 if (
op.first ==
"prefix") {
2333 v_prefix = std::string(
op.second);
2334 }
else if (
op.first ==
"suffix") {
2335 v_suffix = std::string(
op.second);
2336 }
else if (
op.first ==
"offset") {
2337 v_offset =
op.second;
2338 }
else if (
op.first ==
"extract_trivial") {
2339 extract_trivial =
op.second;
2341 casadi_error(
"No such option: " + std::string(
op.first));
2344 Function f(
"f", {par}, {expr}, {{
"live_variables",
false},
2345 {
"max_io", 0}, {
"allow_free",
true}});
2349 std::vector< MX > w(ff->workloc_.size()-1);
2355 std::vector< char > expr_status(ff->workloc_.size()-1, 0);
2361 std::vector<MX> res_split;
2365 std::vector<MX > arg1, res1;
2368 std::map<MXNode*, MX> symbol_map;
2371 std::vector<MX> symbol_v, parametric_v;
2374 casadi_int alg_counter = 0;
2375 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2377 w[it->res.front()] = arg_split.at(it->data->segment());
2378 expr_status[it->res.front()] = 1;
2380 MX arg = w[it->arg.front()];
2381 if (expr_status[it->arg.front()]==1) {
2383 extract_trivial, v_offset, v_prefix, v_suffix);
2386 res_split.at(it->data->segment()) = arg;
2389 w[it->res.front()] = it->data;
2390 expr_status[it->res.front()] = 0;
2393 w[it->res.front()] = it->data;
2394 expr_status[it->res.front()] = 2;
2397 arg1.resize(it->arg.size());
2398 for (casadi_int i=0; i<arg1.size(); ++i) {
2399 casadi_int el = it->arg[i];
2400 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : w[el];
2404 char max_status = 0;
2405 for (casadi_int i=0; i<arg1.size(); ++i) {
2406 casadi_int el = it->arg[i];
2408 max_status = std::max(max_status, expr_status[it->arg[i]]);
2411 bool any_tainted = max_status==2;
2415 for (casadi_int i=0; i<arg1.size(); ++i) {
2416 casadi_int el = it->arg[i];
2419 if (el>=0 && expr_status[el]==1) {
2422 extract_trivial, v_offset, v_prefix, v_suffix);
2428 res1.resize(it->res.size());
2429 it->data->eval_mx(arg1, res1);
2432 for (casadi_int i=0; i<res1.size(); ++i) {
2433 casadi_int el = it->res[i];
2437 expr_status[el] = max_status;
2447 parametric = parametric_v;
2451 const MX &sym_lin,
const MX &sym_const,
2452 MX& expr_const,
MX& expr_lin,
MX& expr_nonlin) {
2454 std::vector<MX> in = {sym_const, sym_lin};
2455 std::vector<MX> out = {expr};
2457 Function f(
"f", in, out, {{
"live_variables",
false},
2458 {
"max_io", 0}, {
"allow_free",
true}});
2462 std::vector< std::array<MX, 3> > w(ff->workloc_.size()-1);
2465 std::vector<std::vector<MX> > arg_split(in.size());
2466 for (casadi_int i=0; i<in.size(); ++i) arg_split[i] = in[i].
split_primitives(in[i]);
2469 std::array<std::vector<MX>, 3> res_split;
2470 for (
int k=0;k<3;++k) {
2474 std::vector<std::array<MX, 3> > arg1, res1;
2476 std::array<MX, 3> res;
2479 casadi_int alg_counter = 0;
2480 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2482 MX null =
MX::zeros(arg_split.at(it->data->ind()).at(it->data->segment()).sparsity());
2483 w[it->res.front()][0] =
null;
2484 w[it->res.front()][1] =
null;
2485 w[it->res.front()][2] =
null;
2486 w[it->res.front()][it->data->ind()] = arg_split.at(it->data->ind()).at(it->data->segment());
2489 for (
int i=0;i<3;++i) {
2490 res_split.at(i).at(it->data->segment()) = w[it->arg.front()][i];
2494 w[it->res.front()][0] = it->data;
2495 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2496 w[it->res.front()][2] =
MX::zeros(it->data->sparsity());
2499 w[it->res.front()][0] =
MX::zeros(it->data->sparsity());
2500 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2501 w[it->res.front()][2] = it->data;
2504 arg1.resize(it->arg.size());
2505 for (casadi_int i=0; i<arg1.size(); ++i) {
2506 casadi_int el = it->arg[i];
2507 for (
int k=0;k<3;++k) {
2508 arg1[i][k] = el<0 ?
MX(it->data->dep(i).size()) : w[el][k];
2514 res1.resize(it->res.size());
2515 for (casadi_int i=0;i<it->res.size();++i) {
2516 for (
int k=0;k<3;++k) {
2517 res1[i][k] =
MX::zeros(it->data->sparsity());
2520 it->data->eval_linear(arg1, res1);
2523 for (casadi_int i=0; i<res1.size(); ++i) {
2524 casadi_int el = it->res[i];
2525 for (
int k=0;k<3;++k) {
2526 if (el>=0) w[el][k] = res1[i][k];
2533 for (
int k=0;k<3;++k) {
2536 expr_const = res[0];
2538 expr_nonlin = res[2];
2542 std::vector<MX> s =
symvar(expr);
2545 options[
"never_inline"] =
true;
2547 Dict inline_options;
2548 inline_options[
"never_inline"] =
false;
2549 inline_options[
"always_inline"] =
true;
2550 Dict der_options =
Dict{{
"forward_options", inline_options},
2551 {
"reverse_options", inline_options},
2552 {
"jacobian_options", inline_options}};
2554 options[
"is_diff_in"] = std::vector<bool>{
false};
2555 options[
"is_diff_out"] = std::vector<bool>{
true};
2556 options =
combine(options, der_options);
2557 }
else if (order==2) {
2558 options[
"der_options"] = der_options;
2559 options[
"forward_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
2560 {
"is_diff_out", std::vector<bool>{
true}}};
2561 options[
"reverse_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
2562 {
"is_diff_out", std::vector<bool>{
true}}};
2563 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true} },
2564 {
"is_diff_out", std::vector<bool>{
false}}};
2566 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
2569 Function FS(
"FS", {x}, {expr}, {
"x"}, {
"z"}, options);
2570 return FS(std::vector<MX>{x})[0];
2574 casadi_warning(
"stop_diff(expr, var, order) is not well tested.");
2575 std::vector<MX> xv =
symvar(var);
2576 std::vector<MX> s =
symvar(expr);
2583 options[
"never_inline"] =
true;
2585 Dict inline_options;
2586 inline_options[
"never_inline"] =
false;
2587 inline_options[
"always_inline"] =
true;
2588 Dict der_options =
Dict{{
"forward_options", inline_options},
2589 {
"reverse_options", inline_options},
2590 {
"jacobian_options", inline_options}};
2592 options[
"is_diff_in"] = std::vector<bool>{
false,
true};
2593 options[
"is_diff_out"] = std::vector<bool>{
true};
2594 options =
combine(options, der_options);
2595 }
else if (order==2) {
2596 options[
"der_options"] = der_options;
2597 options[
"forward_options"] =
Dict{{
"is_diff_in",
2598 std::vector<bool>{
false,
true,
false,
true,
true} },
2599 {
"is_diff_out", std::vector<bool>{
true}}};
2600 options[
"reverse_options"] =
Dict{{
"is_diff_in",
2601 std::vector<bool>{
false,
true,
false,
true}},
2602 {
"is_diff_out", std::vector<bool>{
false,
true}}};
2603 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true}},
2604 {
"is_diff_out", std::vector<bool>{
true}}};
2606 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
2609 Function FS(
"FS", {x, y}, {expr}, {
"x",
"y"}, {
"z"}, options);
2610 return FS(std::vector<MX>{x, y})[0];
2615 std::set<MXNode*> bs;
2616 for (
const auto& e : b) {
2617 if (!e.is_null()) bs.insert(e.get());
2619 std::vector<MX> ret;
2620 for (
auto&& e : a) {
2622 if (bs.find(e.get())==bs.end()) {
2631 const std::vector<MX>& xis,
2632 const std::vector<MX>& L,
const std::vector<MX>& Lp,
2633 const std::vector<casadi_int>& strides,
2639 v.
get_nz(ret,
false, offset, I);
2642 casadi_int j = xis.
size()-i;
2643 MX offsetL, offsetR;
2644 if (strides[j]==1) {
2645 offsetL = offset+L[j];
2646 offsetR = offset+Lp[j];
2648 offsetL = offset+L[j]*strides[j];
2649 offsetR = offsetL+strides[j];
2651 MX vl =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetL);
2652 MX vu =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetR);
2655 return vl + xis[j]*(vu-vl);
2662 casadi_int n_dim = x.
size();
2663 std::vector<std::string> lookup_mode(n_dim,
"auto");
2664 for (
auto&&
op : opts) {
2665 if (
op.first==
"lookup_mode") {
2666 lookup_mode =
op.second;
2668 casadi_error(
"Unknown option '" +
op.first +
"'.");
2672 casadi_assert_dev(xq.size()==n_dim);
2676 std::vector<casadi_int> x_dims;
2677 for (
auto e : x) x_dims.push_back(e.numel());
2682 "Dimension mismatch: coefficients (" +
str(v.
numel()) +
") should be "
2683 "an integer multiple of product-of-dimensions (" +
str(
product(x_dims)) +
").");
2686 casadi_int nq = xq[0].numel();
2688 casadi_assert_dev(e.is_vector() && e.numel()==nq);
2692 std::vector<casadi_int> strides;
2693 strides.push_back(
n_out);
2694 for (
auto d : x_dims) strides.push_back(strides.back()*d);
2698 std::vector<MX> xis, Ls, Lps;
2699 for (casadi_int i=0;i<n_dim;++i) {
2700 MX L =
low(x[i], xq[i], {{
"lookup_mode", lookup_mode[i]}});
2703 x[i].
get_nz(xl,
false, L);
2704 x[i].get_nz(xu,
false, Lp);
2705 xis.push_back((xq[i]-xl)/(xu-xl));
2712 return interpn_G(n_dim, v, xis, Ls, Lps, strides, I);
2736 void MX::eval_mx(
const std::vector<MX>& arg, std::vector<MX>& res)
const {
2738 res.resize((*this)->nout());
2739 (*this)->eval_mx(arg, res);
2740 }
catch (std::exception& e) {
2741 CASADI_THROW_ERROR_OBJ(
"eval_mx", e.what());
2746 std::vector<std::vector<MX> >& fsens)
const {
2748 (*this)->ad_forward(fseed, fsens);
2749 }
catch (std::exception& e) {
2750 CASADI_THROW_ERROR_OBJ(
"ad_forward", e.what());
2755 std::vector<std::vector<MX> >& asens)
const {
2757 (*this)->ad_reverse(aseed, asens);
2758 }
catch (std::exception& e) {
2759 CASADI_THROW_ERROR_OBJ(
"ad_reverse", e.what());
2763 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2764 std::mutex MX::mutex_temp;
2767 #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 find(std::map< FunctionInternal *, Function > &all_fun, casadi_int max_depth) const
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)
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.
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.
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.
DM solve(const DM &A, const DM &B, bool tr=false) const
Internal node class for MXFunction.
std::vector< AlgEl > algorithm_
All the runtime elements in the order of evaluation.
Node class for MX objects.
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_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_mac(const MX &y, const MX &z) const
Matrix multiplication and addition.
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.
MX get_binary(casadi_int op, const MX &y) const
Get a binary operation operation.
virtual MX get_det() const
Determinant.
virtual MX get_solve_tril(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A.
virtual MX get_unary(casadi_int op) const
Get a unary operation.
virtual MX get_project(const Sparsity &sp) const
Create set sparse.
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
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_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_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz) const
Get the nonzeros of matrix.
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_binary(casadi_int op, const MX &y, bool scX, bool scY) const
Get a binary operation operation (matrix-matrix)
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)
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.
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 zero (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
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.
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.
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)
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 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
bool is_commutative() const
Check if commutative operation.
static MX project(const MX &x, const Sparsity &sp, bool intersect=false)
static MX mtimes(const MX &x, const MX &y)
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)
static MX inv(const MX &A, const std::string &lsolver="qr", const Dict &dict=Dict())
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 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_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.
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)
static MX unary(casadi_int op, const MX &x)
Create nodes by their ID.
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)
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.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res) const
Evaluate the MX node with new symbolic dependencies.
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 MX binary(casadi_int op, const MX &x, const MX &y)
Create nodes by their ID.
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 zero (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)
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
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.
static MX mac(const MX &x, const MX &y, const MX &z)
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
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)
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.
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
static Sparsity mtimes(const Sparsity &x, const Sparsity &y)
Enlarge matrix.
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::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 *.
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.
bool any(const std::vector< bool > &v)
Check if any arguments are true.
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.
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.