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));
102 "Expected a column vector with " +
str(sp.
nnz()) +
" nonzeros, but got " + val.
dim() +
".");
111 MX::MX(casadi_int nrow, casadi_int ncol) {
115 MX::MX(
const std::pair<casadi_int, casadi_int>& rc) {
132 casadi_assert_dev(
dynamic_cast<MultipleOutput*
>(node) !=
nullptr);
134 std::vector<MX> ret(x->
nout());
135 for (casadi_int i=0; i<ret.size(); ++i) {
139 }
else if (ret[i].
nnz()==0) {
140 ret[i] =
MX(ret[i].
size());
147 return (*this)->__nonzero__();
172 "Marix::get: First index must be a dense vector");
174 "Marix::get: Second index must be a dense vector");
177 std::vector<casadi_int>
mapping;
200 std::vector<casadi_int>
mapping;
210 "get(Sparsity sp): shape mismatch. This matrix has shape "
211 +
str(
size()) +
", but supplied sparsity index has shape "
217 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices."
218 "Got " +
dim(
true) +
" instead.");
223 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices. ");
228 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
233 casadi_assert(
is_dense(),
"Parametric slicing only supported for dense matrices.");
255 set(m, ind1, rr.
T(), cc);
261 set(m, ind1, rr, cc.
T());
267 "MX::set: First index not dense vector");
269 "MX::set: Second index not dense vector");
280 set(m.
T(), ind1, rr, cc);
284 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size1()) +
"-by-"
293 casadi_assert_in_range(rr.
nonzeros(), -sz1+ind1, sz1+ind1);
294 casadi_assert_in_range(cc.
nonzeros(), -sz2+ind1, sz2+ind1);
303 for (casadi_int j=0; j<el.
size2(); ++j) {
304 casadi_int this_j = cc->at(j) - ind1;
305 if (this_j<0) this_j += sz2;
306 for (casadi_int k=el.
colind(j); k<el.
colind(j+1); ++k) {
307 casadi_int i = m.
row(k);
308 casadi_int this_i = rr->at(i) - ind1;
309 if (this_i<0) this_i += sz1;
310 el->at(k) = this_i + this_j*sz1;
345 set(m.
T(), ind1, rr);
349 casadi_error(
"Dimension mismatch. lhs is " +
str(rr.
size())
350 +
", while rhs is " +
str(m.
size()));
361 casadi_assert_in_range(rr.
nonzeros(), -nel+ind1, nel+ind1);
372 new_row.reserve(sz+rrsz);
373 new_col.reserve(sz+rrsz);
375 for (std::vector<casadi_int>::iterator i=
nz.begin(); i!=
nz.end(); ++i) {
378 new_row.push_back(*i % sz1);
379 new_col.push_back(*i / sz1);
395 "set(Sparsity sp): shape mismatch. This matrix has shape "
396 +
str(
size()) +
", but supplied sparsity index has shape "
398 std::vector<casadi_int> ii = sp.
find();
422 casadi_int sz =
nnz();
423 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
426 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
428 for (
auto&& i : kk_mod.
nonzeros()) {
429 casadi_assert(!(ind1 && i<=0),
430 "Matlab is 1-based, but requested index " +
str(i) +
". "
431 "Note that negative slices are disabled in the Matlab interface. "
432 "Possibly you may want to use 'end'.");
451 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1.0: outer);
456 m = (*this)->
get_nz_ref(ind1 ? inner-1: inner, ind1 ? outer-1.0: outer);
461 m = (*this)->
get_nz_ref(ind1 ? inner-1.0: inner, ind1 ? outer-1: outer);
470 casadi_assert(kk.
nnz()==m.
nnz() || m.
nnz()==1,
471 "MX::set_nz: length of non-zero indices (" +
str(kk.
nnz()) +
") " +
472 "must match size of rhs (" +
str(m.
nnz()) +
").");
492 casadi_error(
"Dimension mismatch. lhs is " +
str(kk.
size())
493 +
", while rhs is " +
str(m.
size()));
505 casadi_int sz =
nnz();
506 casadi_assert_in_range(kk.
nonzeros(), -sz+ind1, sz+ind1);
509 if (kk.
nnz()==0)
return;
512 if (ind1 || *std::min_element(kk->begin(), kk->end())<0) {
514 for (
auto&& i : kk_mod.
nonzeros()) {
515 casadi_assert(!(ind1 && i<=0),
516 "Matlab is 1-based, but requested index " +
str(i) +
". "
517 "Note that negative slices are disabled in the Matlab interface. "
518 "Possibly you may want to use 'end'.");
556 ", x is " + x.
dim() +
", while y is " + y.
dim());
583 MX MX::inf(
const std::pair<casadi_int, casadi_int> &rc) {
584 return inf(rc.first, rc.second);
595 MX MX::nan(
const std::pair<casadi_int, casadi_int>& rc) {
596 return nan(rc.first, rc.second);
608 if ((*this)->op()==
OP_NEG) {
609 return (*this)->
dep(0);
616 return (*this)->sparsity();
619 void MX::erase(
const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
bool ind1) {
624 std::vector<casadi_int>
mapping = sp.
erase(rr, cc, ind1);
636 for (
const MX& e : p) {
643 for (casadi_int i=0; i<
nz.
nnz(); ++i) {
644 ret.push_back(
nz(i));
651 void MX::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
666 const std::vector<casadi_int>& rr,
667 const std::vector<casadi_int>& cc,
bool ind1) {
669 sp.
enlarge(nrow, ncol, rr, cc, ind1);
681 return mac(x, y, z, blas);
686 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
687 const std::vector<casadi_int>& dim_c,
688 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
689 const std::vector<casadi_int>& c) {
690 return C->get_einstein(A,
B, dim_c, dim_a, dim_b, c, a, b);
694 const std::vector<casadi_int>& dim_a,
const std::vector<casadi_int>& dim_b,
695 const std::vector<casadi_int>& dim_c,
696 const std::vector<casadi_int>& a,
const std::vector<casadi_int>& b,
697 const std::vector<casadi_int>& c) {
702 if (axis==-1) axis = x.
is_row();
703 MX r = axis==0 ? x.
T() : x;
710 MX ret = f(std::vector<MX>{0, r})[0];
712 return axis==0 ? ret.
T() : ret;
723 "Matrix product with incompatible dimensions. Lhs is "
724 + x.
dim() +
" and rhs is " + y.
dim() +
".");
748 "Error in attachAssert: assertion expression y must be scalar, "
749 "but got " + y.
dim());
750 return(*this)->get_assert(y, fail_message);
758 return(*this)->
get_dump(base_filename, opts);
762 casadi_assert(
op()==
OP_DUMP,
"reset_dump_count: not a dump node");
772 Function f(
"f", std::vector<MX>{}, {m}, {{
"allow_free",
true}});
773 return f(std::vector<DM>{})[0];
777 if (a.
is_scalar() || b.is_scalar())
return b/a;
778 return solve(a.
T(), b.T()).
T();
782 if (a.
is_scalar() || b.is_scalar())
return b/a;
787 return (*this)->
dep(ch);
791 return (*this)->n_dep();
795 return (*this)->name();
811 return (*this)->which_function();
815 return (*this)->is_output();
819 return (*this)->has_output();
823 return (*this)->which_output();
827 return (*this)->op()==
op;
835 return dynamic_cast<const Norm*
>(
get())!=
nullptr;
838 MX::operator double()
const {
842 MX::operator
DM()
const {
843 return (*this)->get_DM();
847 return (*this)->is_binary();
851 return (*this)->is_unary();
855 return (*this)->op();
859 return (*this)->info();
863 (*this)->serialize(s);
885 "MX::is_commutative: must be binary or unary operation");
886 return operation_checker<CommChecker>(
op());
890 return (*this)->mapping();
894 return (*this)->temp;
902 return (*this)->nout();
914 casadi_assert(sp.
size()==x.
size(),
"Cannot project " + x.
dim() +
" to " + sp.
dim());
921 }
catch (std::exception& e) {
922 CASADI_THROW_ERROR(
"project", e.what());
939 casadi_int MX::eq_depth_ = 1;
942 eq_depth_ = eq_depth;
958 return (*this)->is_valid_input();
962 return (*this)->n_primitives();
967 std::vector<MX>::iterator it=ret.begin();
968 (*this)->primitives(it);
969 casadi_assert_dev(it==ret.end());
975 std::vector<MX>::iterator it=ret.begin();
976 (*this)->split_primitives(x, it);
977 casadi_assert_dev(it==ret.end());
983 std::vector<SX>::iterator it=ret.begin();
984 (*this)->split_primitives(x, it);
985 casadi_assert_dev(it==ret.end());
991 std::vector<DM>::iterator it=ret.begin();
992 (*this)->split_primitives(x, it);
993 casadi_assert_dev(it==ret.end());
998 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
999 std::vector<MX>::const_iterator it=v.begin();
1001 casadi_assert_dev(it==v.end());
1006 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
1007 std::vector<SX>::const_iterator it=v.begin();
1008 SX ret = (*this)->join_primitives(it);
1009 casadi_assert_dev(it==v.end());
1014 casadi_assert(v.size()==
n_primitives(),
"Wrong number of primitives supplied");
1015 std::vector<DM>::const_iterator it=v.begin();
1016 DM ret = (*this)->join_primitives(it);
1017 casadi_assert_dev(it==v.end());
1022 return (*this)->has_duplicates();
1026 (*this)->reset_input();
1030 return (*this)->is_eye();
1037 return (*this)->is_zero();
1042 return (*this)->is_one();
1046 return (*this)->is_value(-1);
1050 return (*this)->is_half();
1054 return (*this)->is_value(val);
1058 return (*this)->is_nonnegative();
1069 casadi_error(
"Cannot check regularity for symbolic MX");
1074 return (*this)->is_inf();
1078 return (*this)->is_minus_inf();
1082 return (*this)->is_integer();
1094 return (*this)->get_unary(
OP_INV);
1103 return dynamic_cast<const MXNode*
>(ptr)!=
nullptr;
1108 for (
auto&& i : x) {
1109 if (i.is_empty(both))
return true;
1114 std::vector<MX>
trim_empty(
const std::vector<MX>& x,
bool both=
false) {
1115 std::vector<MX> ret;
1116 for (
auto&& i : x) {
1117 if (!i.is_empty(both)) ret.push_back(i);
1126 for (casadi_int i=0;i<
ne.
size();i++) {
1128 "horzcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1129 " and x[0]: " +
ne[0].
dim() +
".");
1135 }
else if (x.size()==1) {
1143 casadi_int nrow = 0;
1144 for (casadi_int i=0;i<ret.size();++i) {
1146 casadi_assert_dev(nrow==0 || nrow==ret[i].
size1());
1147 nrow = ret[i].size1();
1154 return x.front()->get_horzcat(x);
1160 if (x.empty())
return MX();
1161 if (x.size()==1)
return x.front();
1165 return x.front()->get_diagcat(x);
1172 for (casadi_int i=0;i<
ne.
size();i++) {
1174 "vertcat dimension mismatch x[" +
str(i) +
"]:" +
ne[i].
dim() +
1175 " and x[0]: " +
ne[0].
dim() +
".");
1181 }
else if (x.size()==1) {
1189 casadi_int ncol = 0;
1190 for (casadi_int i=0;i<ret.size();++i) {
1192 casadi_assert_dev(ncol==0 || ret[i].
size2()==ncol);
1193 ncol = ret[i].size2();
1199 }
else if (!x.front().is_column()) {
1201 std::vector<MX> xT = x;
1202 for (std::vector<MX>::iterator i=xT.begin(); i!=xT.end(); ++i) *i = i->T();
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) {
1228 casadi_assert(offset1.size()==offset2.size(),
1229 "diagsplit: offset1 and offset2 must have the same length");
1241 return std::vector<MX>();
1242 }
else if (
offset.size()==2) {
1243 return std::vector<MX>(1, x);
1249 for (
auto&& e : ret) e = e.T();
1256 if (v.empty())
return MX(0, 0);
1259 casadi_int ncols = v.front().size();
1260 for (
auto&& e : v) {
1261 casadi_assert(e.size()==ncols,
"blockcat: Inconsistent number of block columns");
1265 if (v.front().empty())
return MX(0, 0);
1268 std::vector<MX>
rows;
1269 for (
auto&& e : v) {
1296 std::vector<MX>& res,
1307 return transform(std::vector<MX>{x}, opts).at(0);
1311 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
1312 return transform(std::vector<MX>{x}, passes, opts).at(0);
1319 {{
"allow_free",
true}, {
"allow_duplicate_io_names",
true}});
1325 const std::vector<std::vector<GenericType> >& passes,
const Dict& opts) {
1329 {{
"allow_free",
true}, {
"allow_duplicate_io_names",
true}});
1336 if (nrow==x.
size1() && ncol==x.
size2())
return x;
1353 casadi_assert(x.
nnz()==sp.
nnz(),
1354 "Mismatching nonzero count: " +
str(x.
nnz()) +
" versus " +
1365 if (short_circuit) {
1367 std::vector<MX> arg =
symvar(
veccat(std::vector<MX>{x_true, x_false}));
1370 Function f_true(
"f_true", arg, {x_true});
1371 Function f_false(
"f_false", arg, {x_false});
1377 std::vector<MX> sw_arg;
1378 sw_arg.push_back(cond);
1379 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1380 return sw(sw_arg).at(0);
1387 const MX& x_default,
bool short_circuit) {
1388 if (short_circuit) {
1390 std::vector<MX> arg = x;
1391 arg.push_back(x_default);
1395 std::vector<Function> f(x.size());
1396 for (casadi_int k=0; k<x.size(); ++k) {
1397 std::stringstream ss;
1398 ss <<
"f_case" << k;
1399 f[k] =
Function(ss.str(), arg, {x[k]});
1401 Function f_default(
"f_default", arg, {x_default});
1407 std::vector<MX> sw_arg;
1408 sw_arg.push_back(ind);
1409 sw_arg.insert(sw_arg.end(), arg.begin(), arg.end());
1410 return sw(sw_arg).at(0);
1413 for (casadi_int k=0; k<x.size(); ++k) {
1414 ret =
if_else(ind==
static_cast<double>(k), x[k], ret);
1422 std::vector<unsigned char>
mapping;
1426 std::vector<casadi_int> nzA, nzB;
1442 ret =
B->get_nzassign(ret, nzB);
1447 casadi_assert(x.
is_square(),
"trace: must be square");
1449 for (casadi_int i=0; i < x.
size2(); i ++) {
1457 std::vector<casadi_int>
mapping;
1467 Dict opts{{
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}};
1468 Function f(
"tmp_n_nodes", std::vector<MX>{}, {x}, opts);
1481 casadi_assert(p.
is_dense(),
"polynomial coefficients vector must be dense");
1482 casadi_assert(p.
is_vector() && p.
nnz()>0,
"polynomial coefficients must be a vector");
1484 for (casadi_int i=1; i<p.
nnz(); ++i) {
1485 ret = ret*x + p.
nz(i);
1491 casadi_assert(args.size()>=x.
n_dep(),
1492 "Expected " +
str(x.
n_dep()) +
" argument names, but got " +
str(args.size()) +
".");
1493 return x->
disp(args);
1497 std::vector<MX>& ex,
bool reverse) {
1498 casadi_assert(v.size()==vdef.size(),
1499 "Mismatch in the number of expression to substitute.");
1500 for (casadi_int k=0; k<v.size(); ++k) {
1502 "Variable " +
str(k) +
" is not symbolic");
1503 casadi_assert(v[k].
size() == vdef[k].
size(),
1504 "Inconsistent shape for variable " +
str(k) +
".");
1506 casadi_assert(
reverse==
false,
"Not implemented");
1509 if (v.empty())
return;
1512 std::vector<MX> f_out = vdef;
1513 f_out.insert(f_out.end(), ex.begin(), ex.end());
1514 Function temp(
"tmp_substitute_inplace", {v}, f_out,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1519 return substitute(std::vector<MX>{ex}, std::vector<MX>{v}, std::vector<MX>{vdef}).front();
1523 const std::vector<MX> &vdef) {
1525 casadi_assert_dev(v.size()==vdef.size());
1528 bool all_equal =
true;
1529 for (casadi_int k=0; k<v.size(); ++k) {
1535 if (all_equal)
return ex;
1538 Function F(
"tmp_substitute", v, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1539 std::vector<MX> ret;
1540 F.
call(vdef, ret,
true);
1545 const std::vector<MX> &vdef) {
1550 const std::vector<MX> &vdef,
bool& updated) {
1555 const std::vector<MX>& v,
1556 const std::vector<MX>& vdef) {
1561 const std::vector<MX>& v,
1562 const std::vector<MX>& vdef,
1564 casadi_assert(v.size()==vdef.size(),
1565 "Mismatch in the number of expression to substitute: "
1566 +
str(v.size()) +
" <-> " +
str(vdef.size()) +
".");
1571 bool all_equal =
true;
1572 for (casadi_int k=0; k<v.size(); ++k) {
1578 if (all_equal)
return ex;
1581 for (casadi_int i=0;i<v.size();++i) {
1582 casadi_assert(v[i].
size()==vdef[i].
size(),
1583 "Inconsistent shapes for i = " +
str(i) +
": v[i] " + v[i].
dim() +
1584 " <-> vdef[i] " + vdef[i].
dim());
1588 Dict opts({{
"max_io", 0}, {
"allow_free",
true}});
1589 Function f(
"tmp_graph_substitute", std::vector<MX>{}, ex, opts);
1593 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1594 std::vector<MX> swork(ff->workloc_.size()-1);
1597 std::vector<bool> tainted(swork.size());
1601 std::map<const MXNode*, casadi_int> expr_lookup;
1602 for (casadi_int i=0;i<v.size();++i) {
1603 auto it = expr_lookup.find(v[i].operator->());
1604 if (it==expr_lookup.end()) expr_lookup[v[i].operator->()] = i;
1608 std::vector<bool> expr_found(v.size(),
false);
1611 std::vector<MX> f_out(f.n_out());
1612 std::vector<MX> oarg, ores;
1615 std::map<const MXNode*, casadi_int>::const_iterator it_lookup;
1618 std::vector<std::vector<MX>> out_split(ex.size());
1619 for (casadi_int i = 0; i < out_split.size(); ++i) out_split[i].resize(ex[i].
n_primitives());
1621 for (
auto it=algorithm.begin(); it!=algorithm.end(); ++it) {
1625 it_lookup = expr_lookup.find((it->data).operator->());
1627 if (it_lookup!=expr_lookup.end()) {
1629 MX e = vdef[it_lookup->second];
1633 for (casadi_int i=0;i<it->res.size();++i) {
1634 casadi_int k = it->res[i];
1641 swork[it->res.front()] = e;
1642 tainted[it->res.front()] =
true;
1644 expr_found[it_lookup->second] =
true;
1646 }
else if (it->data->has_output()) {
1647 bool any_tainted =
false;
1649 for (casadi_int i=0;i<it->res.size();++i) {
1651 casadi_int k = it->res[i];
1655 it_lookup = expr_lookup.
find(out.operator->());
1656 if (it_lookup!=expr_lookup.end()) {
1658 MX e = vdef[it_lookup->second];
1662 expr_found[it_lookup->second] =
true;
1666 if (any_tainted)
continue;
1672 tainted[it->res.front()] =
false;
1675 swork[it->res.front()] = it->data;
1676 tainted[it->res.front()] =
false;
1679 out_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
1683 bool node_tainted =
false;
1686 oarg.resize(it->arg.size());
1687 for (casadi_int i=0; i<oarg.size(); ++i) {
1688 casadi_int el = it->arg[i];
1689 if (el>=0) node_tainted = node_tainted || tainted[el];
1690 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : swork.at(el);
1694 ores.resize(it->res.size());
1695 if (!node_tainted) {
1696 if (it->data.has_output()) {
1697 for (casadi_int i=0;i<it->res.size();++i) {
1698 ores.at(i) = it->data.get_output(i);
1701 ores.at(0) = it->data;
1704 it->data->eval_mx(oarg, ores);
1708 for (casadi_int i=0; i<ores.size(); ++i) {
1709 casadi_int el = it->res[i];
1710 if (el>=0) swork.at(el) = ores[i];
1711 if (el>=0) tainted[el] = node_tainted;
1718 for (
size_t k = 0; k < out_split.size(); ++k) {
1719 f_out[k] = ex[k].join_primitives(out_split.at(k));
1722 bool all_found=
true;
1723 for (casadi_int i=0;i<v.size();++i) {
1724 all_found = all_found && expr_found[i];
1727 updated =
any(expr_found);
1734 std::vector<MX>& vdef,
const Dict& opts) {
1737 std::string v_prefix =
"v_", v_suffix =
"";
1738 bool lift_shared =
true, lift_calls =
false;
1739 casadi_int v_ind = 0;
1740 for (
auto&&
op : opts) {
1741 if (
op.first ==
"prefix") {
1742 v_prefix = std::string(
op.second);
1743 }
else if (
op.first ==
"suffix") {
1744 v_suffix = std::string(
op.second);
1745 }
else if (
op.first ==
"lift_shared") {
1746 lift_shared =
op.second;
1747 }
else if (
op.first ==
"lift_calls") {
1748 lift_calls =
op.second;
1749 }
else if (
op.first ==
"offset") {
1752 casadi_error(
"No such option: " + std::string(
op.first));
1756 Function f(
"tmp_extract", std::vector<MX>{}, ex,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
1759 const std::vector<MXAlgEl>& algorithm = ff->
algorithm_;
1760 std::vector<MX> work(ff->workloc_.size()-1);
1762 std::vector<casadi_int> usecount(work.size(), 0);
1764 std::vector<std::pair<casadi_int, casadi_int> > origin(work.size(), std::make_pair(-1, -1));
1766 std::vector<std::pair<casadi_int, casadi_int> >
replace;
1769 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1776 for (casadi_int c=0; c<it->arg.size(); ++c) {
1778 if (lift_calls && it->op ==
OP_CALL) {
1780 if (usecount.at(it->arg[c]) >= 0) {
1781 replace.push_back(origin.at(it->arg[c]));
1782 usecount.at(it->arg[c]) = -1;
1784 }
else if (lift_shared && work[it->arg[c]].op() !=
OP_PARAMETER
1785 && work[it->arg[c]].op() !=
OP_CONST) {
1786 if (usecount.at(it->arg[c]) == 0) {
1788 usecount.at(it->arg[c]) = 1;
1789 }
else if (usecount.at(it->arg[c]) == 1) {
1791 replace.push_back(origin.at(it->arg[c]));
1792 usecount.at(it->arg[c]) = -1;
1802 usecount[it->res.front()] = -1;
1805 for (casadi_int c=0; c<it->res.size(); ++c) {
1806 if (it->res[c]>=0) {
1807 work[it->res[c]] = it->data.get_output(c);
1808 origin[it->res[c]] = std::make_pair(k, c);
1809 if (lift_calls && it->op ==
OP_CALL) {
1811 replace.push_back(origin.at(it->res[c]));
1812 usecount.at(it->res[c]) = -1;
1814 usecount.at(it->res[c]) = 0;
1830 std::vector<std::pair<casadi_int, casadi_int> >::const_iterator replace_it=
replace.begin();
1832 std::vector<MX> oarg, ores;
1835 for (
auto it=algorithm.begin(); it<algorithm.end(); ++it, ++k) {
1838 casadi_assert(it->data->segment()==0,
"Not implemented");
1839 ex[it->data->ind()] = work[it->arg.front()];
1842 work[it->res.front()] = it->data;
1848 work[it->res.front()] = it->data;
1851 oarg.resize(it->arg.size());
1852 for (casadi_int i=0; i<oarg.size(); ++i) {
1853 casadi_int el = it->arg[i];
1854 oarg[i] = el<0 ?
MX(it->data->dep(i).size()) : work.at(el);
1857 ores.resize(it->res.size());
1858 it->data->eval_mx(oarg, ores);
1860 for (casadi_int i=0; i<ores.size(); ++i) {
1861 casadi_int el = it->res[i];
1862 if (el>=0) work.at(el) = ores[i];
1866 for (casadi_int c=0; c<it->res.size(); ++c) {
1868 casadi_int ind = it->res[c];
1870 bool replace_node = replace_it !=
replace.end()
1871 && replace_it->first==k && replace_it->second==c;
1873 bool output_node = lift_calls && it->op ==
OP_CALL;
1875 if (!replace_node && !output_node)
continue;
1878 v.push_back(
MX::sym(v_prefix + std::to_string(v_ind++) + v_suffix, v_sp));
1882 casadi_assert(replace_node,
"Consistency check");
1884 vdef.push_back(work[ind]);
1886 work[ind] = v.back();
1891 casadi_assert(output_node,
"Consistency check");
1893 vdef.push_back(ores.at(c));
1900 casadi_assert(replace_it ==
replace.end(),
"Consistency check failed");
1901 }
catch (std::exception& e) {
1902 CASADI_THROW_ERROR(
"extract", e.what());
1906 void MX::shared(std::vector<MX>& ex, std::vector<MX>& v, std::vector<MX>& vdef,
1907 const std::string& v_prefix,
const std::string& v_suffix) {
1909 extract(ex, v, vdef,
Dict{{
"lift_shared",
true}, {
"lift_calls",
false},
1910 {
"prefix", v_prefix}, {
"suffix", v_suffix}});
1917 h_opts[
"allow_free"] =
true;
1918 Function h(
"helper_jacobian_MX", {x}, {f}, h_opts);
1920 }
catch (std::exception& e) {
1921 CASADI_THROW_ERROR(
"jacobian", e.what());
1927 return hessian(f, x, g, opts);
1932 Dict all_opts = opts;
1934 if (!opts.count(
"symmetric")) all_opts[
"symmetric"] =
true;
1936 }
catch (std::exception& e) {
1937 CASADI_THROW_ERROR(
"hessian", e.what());
1941 std::vector<std::vector<MX> >
1943 const std::vector<MX> &arg,
1944 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1947 bool always_inline =
true;
1948 bool never_inline =
false;
1952 h_opts[
"allow_free"] =
true;
1953 for (
auto&&
op : opts_remainder) {
1954 if (
op.first==
"always_inline") {
1955 always_inline =
op.second;
1956 }
else if (
op.first==
"never_inline") {
1957 never_inline =
op.second;
1959 casadi_error(
"No such option: " + std::string(
op.first));
1963 Function temp(
"forward_temp", arg, ex, h_opts);
1964 std::vector<std::vector<MX> > ret;
1965 temp->
call_forward(arg, ex, v, ret, always_inline, never_inline);
1967 }
catch (std::exception& e) {
1968 CASADI_THROW_ERROR(
"forward", e.what());
1972 std::vector<std::vector<MX> >
1974 const std::vector<MX> &arg,
1975 const std::vector<std::vector<MX> > &v,
const Dict& opts) {
1978 bool always_inline =
true;
1979 bool never_inline =
false;
1984 h_opts[
"allow_free"] =
true;
1986 for (
auto&&
op : opts_remainder) {
1987 if (
op.first==
"always_inline") {
1988 always_inline =
op.second;
1989 }
else if (
op.first==
"never_inline") {
1990 never_inline =
op.second;
1992 casadi_error(
"No such option: " + std::string(
op.first));
1996 Function temp(
"reverse_temp", arg, ex, h_opts);
1997 std::vector<std::vector<MX> > ret;
1998 temp->
call_reverse(arg, ex, v, ret, always_inline, never_inline);
2000 }
catch (std::exception& e) {
2001 CASADI_THROW_ERROR(
"reverse", e.what());
2014 return det(x,
"qr");
2019 return mysolver.
det(x);
2027 casadi_error(
"Not implemented");
2035 Function f(
"f", std::vector<MX>{}, {x}, {{
"allow_free",
true}});
2040 return matrix_expand(std::vector<MX>{e}, boundary, options).at(0);
2044 const std::vector<MX> &boundary,
2045 const Dict &options) {
2048 std::vector<MX> syms(boundary.size());
2050 for (casadi_int i=0;i<syms.size();++i) {
2061 Function f(
"tmp_matrix_expand", v, ret,
Dict{{
"max_io", 0}, {
"allow_free",
true}});
2085 }
else if (n==1 && m==1) {
2101 if (nsteps < 2)
return b;
2102 MX step = (b - a) /
static_cast<double>(nsteps - 1);
2103 std::vector<double> idx(nsteps - 1);
2104 for (casadi_int i = 0; i < nsteps - 1; ++i) idx[i] =
static_cast<double>(i);
2105 return vertcat(std::vector<MX>{a +
DM(idx) * step, b});
2122 return solve(a, b,
"qr");
2129 return mysolver.
solve(a, b,
false);
2142 opts[
"const_A"] =
true;
2144 return ret(std::vector<MX>{A, t})[0];
2149 return ret(std::vector<MX>{A, 1})[0];
2159 if (x.
nnz()==0)
return false;
2162 Function temp(
"tmp_depends_on", {arg}, {x},
Dict{{
"max_io", 0}, {
"allow_free",
true}});
2165 std::vector<bvec_t> t_in(arg.
nnz(), 1), t_out(x.
nnz());
2169 for (casadi_int i=0; i<t_out.size(); ++i) {
2170 if (t_out[i])
return true;
2178 if (n.empty())
return true;
2181 std::set<MXNode*> l;
2182 for (
const MX& e : v) l.insert(e.get());
2184 size_t l_unique = l.size();
2186 for (
const MX& e : n) l.insert(e.get());
2188 return l.size()==l_unique;
2192 if (n.empty())
return true;
2195 std::set<MXNode*> l;
2196 for (
const MX& e : v) l.insert(e.get());
2198 size_t l_unique = l.size();
2200 std::set<MXNode*> r;
2201 for (
const MX& e : n) r.insert(e.get());
2203 size_t r_unique = r.size();
2204 for (
const MX& e : n) l.insert(e.get());
2206 return l.size()<l_unique+r_unique;
2214 return p->
get_low(v, options);
2219 const std::vector< std::vector<double> >& knots,
2220 const std::vector<casadi_int>& degree,
2227 const std::vector< std::vector<double> >& knots,
2228 const std::vector<casadi_int>& degree,
2235 const std::vector<MX>& knots,
2236 const std::vector<casadi_int>& degree,
2243 const std::vector< std::vector<double> >& knots,
2244 const std::vector<casadi_int>& degree,
2255 std::vector<MX>& res,
2257 Dict temp_opts = {{
"live_variables",
false},
2260 {
"allow_free",
true}};
2261 Function f(
"temp", arg, res, temp_opts);
2263 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2267 std::vector<bool> is_numeric(workloc_.size()-1);
2269 std::vector<MX> swork(workloc_.size()-1);
2272 std::vector<std::vector<MX> > arg_split(arg.size());
2273 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].split_primitives(arg[i]);
2276 std::vector<std::vector<MX> > res_split(res.size());
2277 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].n_primitives());
2279 std::vector<MX> arg1, res1;
2281 std::unordered_map<const MXNode*, bool> numeric_node;
2283 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2285 swork[it->res.front()] = project(arg_split.at(it->data->ind()).at(it->data->segment()),
2286 it->data.sparsity(),
true);
2287 is_numeric[it->res.front()] =
false;
2290 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2293 swork[it->res.front()] = it->data;
2294 is_numeric[it->res.front()] =
false;
2297 arg1.resize(it->arg.size());
2300 bool numeric =
true;
2302 for (casadi_int i=0; i<arg1.size(); ++i) {
2303 casadi_int el = it->arg[i];
2305 arg1[i] =
MX(it->data->dep(i).size());
2307 arg1[i] = swork[el];
2308 numeric = numeric && is_numeric[el];
2312 numeric_node[it->data.get()] = numeric;
2315 res1.resize(it->res.size());
2317 bool matched =
false;
2320 if (it->op ==
OP_MUL && is_numeric[it->arg[0]] &&
2321 !is_numeric[it->arg[1]] && arg1[1].is_op(
OP_MUL)) {
2322 if (numeric_node[arg1[1].dep(0).get()]) {
2324 res1[0] = (arg1[0]*arg1[1].dep(0))*arg1[1].dep(1);
2328 if (!matched) it->data->eval_mx(arg1, res1);
2330 for (casadi_int i=0; i<res1.size(); ++i) {
2331 casadi_int el = it->res[i];
2333 is_numeric[el] = numeric;
2338 for (casadi_int i=0; i<res1.size(); ++i) {
2339 casadi_int el = it->res[i];
2341 swork[el] = res1[i];
2348 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].join_primitives(res_split[i]);
2354 std::unordered_multimap< std::size_t, std::pair<MX, DM> >& cache) {
2356 std::size_t h = sp.
hash();
2360 auto r = cache.equal_range(h);
2361 for (
auto it = r.first; it != r.second; ++it) {
2362 const DM& d = it->second.second;
2365 return it->second.first;
2372 std::vector<double> vec(v, v+sp.
nnz());
2375 cache.emplace(h, std::make_pair(ret, m));
2382 std::vector<MX>& res,
2385 Dict temp_opts = {{
"live_variables",
false},
2388 {
"allow_free",
true}};
2389 Function f(
"temp", arg, res, temp_opts);
2391 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2395 std::vector<double> w_vec(f.
sz_w());
2397 std::vector<casadi_int> iw_vec(f.
sz_iw());
2398 casadi_int* iw =
get_ptr(iw_vec);
2399 std::vector<const double*> arg_num_vec(f.
sz_arg());
2400 const double** arg_num =
get_ptr(arg_num_vec);
2401 std::vector<double*> res_num_vec(f.
sz_res());
2402 double** res_num =
get_ptr(res_num_vec);
2405 std::vector<bool> is_numeric(workloc_.size()-1);
2410 std::vector<MX> swork(workloc_.size()-1);
2413 std::vector<std::vector<MX> > arg_split(arg.size());
2414 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].
split_primitives(arg[i]);
2417 std::vector<std::vector<MX> > res_split(res.size());
2418 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].
n_primitives());
2420 std::vector<MX> arg1, res1;
2422 std::unordered_multimap< std::size_t, std::pair<MX, DM> > cache;
2424 bool performed_folding =
false;
2427 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2429 swork[it->res.front()] =
project(arg_split.at(it->data->ind()).at(it->data->segment()),
2430 it->data.sparsity(),
true);
2431 is_numeric[it->res.front()] =
false;
2434 MX& target = res_split.at(it->data->ind()).at(it->data->segment());
2435 casadi_int el = it->arg.front();
2436 if (is_numeric[el] && !it->data->dep().is_constant()) {
2437 target =
get_const(it->data->dep().sparsity(), w + workloc_[el], cache);
2443 swork[it->res.front()] = it->data;
2444 is_numeric[it->res.front()] =
false;
2447 arg1.resize(it->arg.size());
2450 bool numeric =
true;
2453 for (casadi_int i=0; i<arg1.size(); ++i) {
2454 casadi_int el = it->arg[i];
2457 arg1[i] =
MX(it->data->dep(i).size());
2460 arg1[i] = swork[el];
2462 numeric = numeric && is_numeric[el];
2468 for (casadi_int i=0; i<it->arg.size(); ++i)
2469 arg_num[i] = it->arg[i]>=0 ? w+workloc_[it->arg[i]] :
nullptr;
2470 for (casadi_int i=0; i<it->res.size(); ++i)
2471 res_num[i] = it->res[i]>=0 ? w+workloc_[it->res[i]] :
nullptr;
2473 if (it->data->eval(arg_num, res_num, iw, w)) casadi_error(
"Evaluation error");
2474 performed_folding =
true;
2477 for (casadi_int i=0; i<arg1.size(); ++i) {
2478 casadi_int el = it->arg[i];
2480 MX& target = arg1[i];
2481 if (is_numeric[el] && !it->data->dep(i).is_constant()) {
2482 target =
get_const(it->data->dep(i).sparsity(), w + workloc_[el], cache);
2491 res1.resize(it->res.size());
2492 it->data->
eval_mx(arg1, res1);
2495 for (casadi_int i=0; i<res1.size(); ++i) {
2496 casadi_int el = it->res[i];
2498 swork[el] = res1[i];
2499 is_numeric[el] = numeric;
2506 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].
join_primitives(res_split[i]);
2508 return performed_folding;
2512 std::vector<MX>& res,
2514 Dict temp_opts = {{
"live_variables",
false},
2517 {
"allow_free",
true}};
2518 Function f(
"temp", arg, res, temp_opts);
2520 const std::vector<casadi_int>& workloc_ = ff->
workloc_;
2523 std::vector<casadi_int> rwork(workloc_.size()-1);
2524 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2527 rwork[it->arg.front()]++;
2529 rwork[it->res.front()]++;
2531 for (casadi_int i=0; i<it->arg.size(); ++i) {
2532 casadi_int el = it->arg[i];
2544 std::vector<MX> swork(workloc_.size()-1);
2547 std::vector<std::vector<MX> > arg_split(arg.size());
2548 for (casadi_int i=0; i<arg.size(); ++i) arg_split[i] = arg[i].
split_primitives(arg[i]);
2551 std::vector<std::vector<MX> > res_split(res.size());
2552 for (casadi_int i=0; i<res.size(); ++i) res_split[i].resize(res[i].
n_primitives());
2554 std::vector<MX> arg1, res1;
2557 for (
auto it=algorithm_.begin(); it!=algorithm_.end(); ++it) {
2559 swork[it->res.front()] =
project(arg_split.at(it->data->ind()).at(it->data->segment()),
2560 it->data.sparsity(),
true);
2563 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2566 swork[it->res.front()] = it->data;
2569 arg1.resize(it->arg.size());
2571 std::vector<bool> unique(it->arg.size(),
true);
2572 for (casadi_int i=0; i<arg1.size(); ++i) {
2573 casadi_int el = it->arg[i];
2575 arg1[i] =
MX(it->data->dep(i).size());
2577 arg1[i] = swork[el];
2578 if (rwork[el]>1) unique[i] =
false;
2583 res1.resize(it->res.size());
2584 it->data->eval_mx(arg1, res1, unique);
2587 for (casadi_int i=0; i<res1.size(); ++i) {
2588 casadi_int el = it->res[i];
2590 swork[el] = res1[i];
2597 for (casadi_int i=0; i<res.size(); ++i) res[i] = res[i].
join_primitives(res_split[i]);
2602 class IncrementalSerializerMX {
2605 IncrementalSerializerMX() : serializer(ss) {
2608 std::string pack(
const MX& a) {
2611 if (a.is_empty())
return "";
2617 a.serialize(serializer);
2620 a.serialize(serializer);
2621 std::string ret = ss.str();
2628 std::stringstream ss;
2630 std::vector<MX> ref;
2631 SerializingStream serializer;
2635 std::vector<MX>
MX::cse(
const std::vector<MX>& e) {
2636 std::vector<MX> orig = e;
2637 bool updated =
true;
2639 Function f(
"f", std::vector<MX>{}, orig,
2640 {{
"live_variables",
false}, {
"max_io", 0}, {
"cse",
false}, {
"allow_free",
true}});
2644 std::vector<MX> swork(ff->workloc_.size()-1);
2647 std::vector<std::vector<MX> > res_split(orig.size());
2648 for (casadi_int i=0; i<orig.size(); ++i) res_split[i].resize(orig[i].
n_primitives());
2650 std::vector<MX> arg1, res1;
2651 std::vector<MX> res(orig.size());
2653 std::unordered_map<std::string, MX > cache;
2654 IncrementalSerializerMX s;
2661 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it) {
2664 std::string key = s.pack(it->data);
2666 auto itk = cache.find(key);
2667 if (itk==cache.end()) {
2668 cache[key] = it->data;
2673 casadi_int alg_counter = 0;
2674 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2679 res_split.at(it->data->ind()).at(it->data->segment()) = swork[it->arg.front()];
2682 MX& target = swork[it->res.front()];
2684 cache[s.pack(target)] = target;
2688 arg1.resize(it->arg.size());
2689 for (casadi_int i=0; i<arg1.size(); ++i) {
2690 casadi_int el = it->arg[i];
2691 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : swork[el];
2695 res1.resize(it->res.size());
2696 it->data->eval_mx(arg1, res1);
2699 for (casadi_int i=0; i<res1.size(); ++i) {
2700 casadi_int el = it->res[i];
2702 MX& out_i = res1[i];
2705 casadi_int output_node = -1;
2710 out_i = out_i.
dep(0);
2718 if (!function_serialize_cache.
incache(fptr, key_s)) {
2720 function_serialize_cache.
tocache(fptr, key_s);
2725 if (!function_cache.
incache(key_s, canonical)) {
2735 std::string key = s.pack(out_i);
2737 auto itk = cache.find(key);
2738 if (itk==cache.end()) {
2741 out_i = itk->second;
2744 if (output_node==-1) {
2754 if (el>=0) swork[el] = out_i;
2760 for (casadi_int i=0; i<res.size(); ++i) res[i] = orig[i].
join_primitives(res_split[i]);
2762 std::vector<MX> subs_from;
2763 std::vector<MX> subs_to;
2764 for (
const auto& e : function_cache.
cache_map()) {
2765 e.second->merge(res, subs_from, subs_to);
2774 std::vector<MX>& symbol_v, std::vector<MX>& parametric_v,
2775 bool extract_trivial, casadi_int v_offset,
2776 const std::string& v_prefix,
const std::string& v_suffix) {
2778 auto it = symbol_map.
find(node.
get());
2782 if (is_trivial && !extract_trivial) {
2786 if (it==symbol_map.end()) {
2789 symbol_map[node.
get()] = sym;
2792 symbol_v.push_back(sym);
2793 parametric_v.push_back(node);
2804 MX& expr_ret, std::vector<MX>& symbols, std::vector<MX>& parametric,
2806 std::string v_prefix =
"e_";
2807 std::string v_suffix =
"";
2808 bool extract_trivial =
false;
2809 casadi_int v_offset = 0;
2810 for (
auto&&
op : opts) {
2811 if (
op.first ==
"prefix") {
2812 v_prefix = std::string(
op.second);
2813 }
else if (
op.first ==
"suffix") {
2814 v_suffix = std::string(
op.second);
2815 }
else if (
op.first ==
"offset") {
2816 v_offset =
op.second;
2817 }
else if (
op.first ==
"extract_trivial") {
2818 extract_trivial =
op.second;
2820 casadi_error(
"No such option: " + std::string(
op.first));
2823 Function f(
"f", {par}, {expr}, {{
"live_variables",
false},
2824 {
"max_io", 0}, {
"allow_free",
true}});
2828 std::vector< MX > w(ff->workloc_.size()-1);
2834 std::vector< char > expr_status(ff->workloc_.size()-1, 0);
2840 std::vector<MX> res_split;
2844 std::vector<MX > arg1, res1;
2847 std::map<MXNode*, MX> symbol_map;
2850 std::vector<MX> symbol_v, parametric_v;
2853 casadi_int alg_counter = 0;
2854 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2856 w[it->res.front()] = arg_split.at(it->data->segment());
2857 expr_status[it->res.front()] = 1;
2859 MX arg = w[it->arg.front()];
2860 if (expr_status[it->arg.front()]==1) {
2862 extract_trivial, v_offset, v_prefix, v_suffix);
2865 res_split.at(it->data->segment()) = arg;
2868 w[it->res.front()] = it->data;
2869 expr_status[it->res.front()] = 0;
2872 w[it->res.front()] = it->data;
2873 expr_status[it->res.front()] = 2;
2876 arg1.resize(it->arg.size());
2877 for (casadi_int i=0; i<arg1.size(); ++i) {
2878 casadi_int el = it->arg[i];
2879 arg1[i] = el<0 ?
MX(it->data->dep(i).size()) : w[el];
2883 char max_status = 0;
2884 for (casadi_int i=0; i<arg1.size(); ++i) {
2885 casadi_int el = it->arg[i];
2887 max_status = std::max(max_status, expr_status[it->arg[i]]);
2890 bool any_tainted = max_status==2;
2894 for (casadi_int i=0; i<arg1.size(); ++i) {
2895 casadi_int el = it->arg[i];
2898 if (el>=0 && expr_status[el]==1) {
2901 extract_trivial, v_offset, v_prefix, v_suffix);
2907 res1.resize(it->res.size());
2908 it->data->eval_mx(arg1, res1);
2911 for (casadi_int i=0; i<res1.size(); ++i) {
2912 casadi_int el = it->res[i];
2916 expr_status[el] = max_status;
2926 parametric = parametric_v;
2930 const MX &sym_lin,
const MX &sym_const,
2931 MX& expr_const,
MX& expr_lin,
MX& expr_nonlin) {
2933 std::vector<MX> in = {sym_const, sym_lin};
2934 std::vector<MX> out = {expr};
2936 Function f(
"f", in, out, {{
"live_variables",
false},
2937 {
"max_io", 0}, {
"allow_free",
true}});
2941 std::vector< std::array<MX, 3> > w(ff->workloc_.size()-1);
2944 std::vector<std::vector<MX> > arg_split(in.size());
2945 for (casadi_int i=0; i<in.size(); ++i) arg_split[i] = in[i].
split_primitives(in[i]);
2948 std::array<std::vector<MX>, 3> res_split;
2949 for (
int k=0;k<3;++k) {
2953 std::vector<std::array<MX, 3> > arg1, res1;
2955 std::array<MX, 3> res;
2958 casadi_int alg_counter = 0;
2959 for (
auto it=ff->algorithm_.begin(); it!=ff->algorithm_.end(); ++it, ++alg_counter) {
2961 MX null =
MX::zeros(arg_split.at(it->data->ind()).at(it->data->segment()).sparsity());
2962 w[it->res.front()][0] =
null;
2963 w[it->res.front()][1] =
null;
2964 w[it->res.front()][2] =
null;
2965 w[it->res.front()][it->data->ind()] = arg_split.at(it->data->ind()).at(it->data->segment());
2968 for (
int i=0;i<3;++i) {
2969 res_split.at(i).at(it->data->segment()) = w[it->arg.front()][i];
2973 w[it->res.front()][0] = it->data;
2974 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2975 w[it->res.front()][2] =
MX::zeros(it->data->sparsity());
2978 w[it->res.front()][0] =
MX::zeros(it->data->sparsity());
2979 w[it->res.front()][1] =
MX::zeros(it->data->sparsity());
2980 w[it->res.front()][2] = it->data;
2983 arg1.resize(it->arg.size());
2984 for (casadi_int i=0; i<arg1.size(); ++i) {
2985 casadi_int el = it->arg[i];
2986 for (
int k=0;k<3;++k) {
2987 arg1[i][k] = el<0 ?
MX(it->data->dep(i).size()) : w[el][k];
2993 res1.resize(it->res.size());
2994 for (casadi_int i=0;i<it->res.size();++i) {
2995 for (
int k=0;k<3;++k) {
2996 res1[i][k] =
MX::zeros(it->data->sparsity());
2999 it->data->eval_linear(arg1, res1);
3002 for (casadi_int i=0; i<res1.size(); ++i) {
3003 casadi_int el = it->res[i];
3004 for (
int k=0;k<3;++k) {
3005 if (el>=0) w[el][k] = res1[i][k];
3012 for (
int k=0;k<3;++k) {
3015 expr_const = res[0];
3017 expr_nonlin = res[2];
3021 std::vector<MX> s =
symvar(expr);
3024 options[
"never_inline"] =
true;
3026 Dict inline_options;
3027 inline_options[
"never_inline"] =
false;
3028 inline_options[
"always_inline"] =
true;
3029 Dict der_options =
Dict{{
"forward_options", inline_options},
3030 {
"reverse_options", inline_options},
3031 {
"jacobian_options", inline_options}};
3033 options[
"is_diff_in"] = std::vector<bool>{
false};
3034 options[
"is_diff_out"] = std::vector<bool>{
true};
3035 options =
combine(options, der_options);
3036 }
else if (order==2) {
3037 options[
"der_options"] = der_options;
3038 options[
"forward_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
3039 {
"is_diff_out", std::vector<bool>{
true}}};
3040 options[
"reverse_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true} },
3041 {
"is_diff_out", std::vector<bool>{
true}}};
3042 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true} },
3043 {
"is_diff_out", std::vector<bool>{
false}}};
3045 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
3048 Function FS(
"FS", {x}, {expr}, {
"x"}, {
"z"}, options);
3049 return FS(std::vector<MX>{x})[0];
3053 casadi_warning(
"stop_diff(expr, var, order) is not well tested.");
3054 std::vector<MX> xv =
symvar(var);
3055 std::vector<MX> s =
symvar(expr);
3062 options[
"never_inline"] =
true;
3064 Dict inline_options;
3065 inline_options[
"never_inline"] =
false;
3066 inline_options[
"always_inline"] =
true;
3067 Dict der_options =
Dict{{
"forward_options", inline_options},
3068 {
"reverse_options", inline_options},
3069 {
"jacobian_options", inline_options}};
3071 options[
"is_diff_in"] = std::vector<bool>{
false,
true};
3072 options[
"is_diff_out"] = std::vector<bool>{
true};
3073 options =
combine(options, der_options);
3074 }
else if (order==2) {
3075 options[
"der_options"] = der_options;
3076 options[
"forward_options"] =
Dict{{
"is_diff_in",
3077 std::vector<bool>{
false,
true,
false,
true,
true} },
3078 {
"is_diff_out", std::vector<bool>{
true}}};
3079 options[
"reverse_options"] =
Dict{{
"is_diff_in",
3080 std::vector<bool>{
false,
true,
false,
true}},
3081 {
"is_diff_out", std::vector<bool>{
false,
true}}};
3082 options[
"jacobian_options"] =
Dict{{
"is_diff_in", std::vector<bool>{
false,
true,
true}},
3083 {
"is_diff_out", std::vector<bool>{
true}}};
3085 casadi_error(
"stop_diff: order must be 1 or 2, got " +
str(order) +
".");
3088 Function FS(
"FS", {x, y}, {expr}, {
"x",
"y"}, {
"z"}, options);
3089 return FS(std::vector<MX>{x, y})[0];
3094 std::set<MXNode*> bs;
3095 for (
const auto& e : b) {
3096 if (!e.is_null()) bs.insert(e.get());
3098 std::vector<MX> ret;
3099 for (
auto&& e : a) {
3101 if (bs.find(e.get())==bs.end()) {
3110 const std::vector<MX>& xis,
3111 const std::vector<MX>& L,
const std::vector<MX>& Lp,
3112 const std::vector<casadi_int>& strides,
3118 v.
get_nz(ret,
false, offset, I);
3121 casadi_int j = xis.
size()-i;
3122 MX offsetL, offsetR;
3123 if (strides[j]==1) {
3124 offsetL = offset+L[j];
3125 offsetR = offset+Lp[j];
3127 offsetL = offset+L[j]*strides[j];
3128 offsetR = offsetL+strides[j];
3130 MX vl =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetL);
3131 MX vu =
interpn_G(i-1, v, xis, L, Lp, strides, I, offsetR);
3134 return vl + xis[j]*(vu-vl);
3141 casadi_int n_dim = x.
size();
3142 std::vector<std::string> lookup_mode(n_dim,
"auto");
3143 for (
auto&&
op : opts) {
3144 if (
op.first==
"lookup_mode") {
3145 lookup_mode =
op.second;
3147 casadi_error(
"Unknown option '" +
op.first +
"'.");
3151 casadi_assert(xq.size()==n_dim,
3152 "Expected " +
str(n_dim) +
" query vectors, but got " +
str(xq.size()) +
".");
3153 casadi_assert(v.
is_vector(),
"Expected a vector of values, but got " + v.
dim() +
".");
3156 std::vector<casadi_int> x_dims;
3157 for (
auto e : x) x_dims.push_back(e.numel());
3162 "Dimension mismatch: coefficients (" +
str(v.
numel()) +
") should be "
3163 "an integer multiple of product-of-dimensions (" +
str(
product(x_dims)) +
").");
3166 casadi_int nq = xq[0].numel();
3168 casadi_assert_dev(e.is_vector() && e.numel()==nq);
3172 std::vector<casadi_int> strides;
3173 strides.push_back(
n_out);
3174 for (
auto d : x_dims) strides.push_back(strides.back()*d);
3178 std::vector<MX> xis, Ls, Lps;
3179 for (casadi_int i=0;i<n_dim;++i) {
3180 MX L =
low(x[i], xq[i], {{
"lookup_mode", lookup_mode[i]}});
3183 x[i].
get_nz(xl,
false, L);
3184 x[i].get_nz(xu,
false, Lp);
3185 xis.push_back((xq[i]-xl)/(xu-xl));
3192 return interpn_G(n_dim, v, xis, Ls, Lps, strides, I);
3217 const std::vector<bool>& unique)
const {
3219 casadi_assert(arg.size()==
n_dep(),
3220 "Expected " +
str(
n_dep()) +
" arguments, but got " +
str(arg.size()) +
".");
3221 res.resize((*this)->nout());
3222 (*this)->eval_mx(arg, res, unique);
3223 }
catch (std::exception& e) {
3224 CASADI_THROW_ERROR_OBJ(
"eval_mx", e.what());
3229 std::vector<std::vector<MX> >& fsens)
const {
3231 (*this)->ad_forward(fseed, fsens);
3232 }
catch (std::exception& e) {
3233 CASADI_THROW_ERROR_OBJ(
"ad_forward", e.what());
3238 std::vector<std::vector<MX> >& asens)
const {
3240 (*this)->ad_reverse(aseed, asens);
3241 }
catch (std::exception& e) {
3242 CASADI_THROW_ERROR_OBJ(
"ad_reverse", e.what());
3246 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3247 std::mutex MX::mutex_temp;
3250 #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())
Create a function that evaluates f_true or f_false depending on.
size_t sz_res() const
Get the length of the output pointer array needed to evaluate (at least.
static Function conditional(const std::string &name, const std::vector< Function > &f, const Function &f_def, const Dict &opts=Dict())
Create a function that selects one of several functions by an index input.
const MX mx_in(casadi_int ind) const
Create fresh symbols with the names and sparsity patterns of the inputs.
FunctionInternal * get() const
Function mapaccum(const std::string &name, casadi_int N, const Dict &opts=Dict()) const
Create a function that applies this function N times, feeding outputs back.
Function expand() const
Convert an MXFunction into an equivalent SXFunction.
std::vector< MX > free_mx() const
Get the free variables of an MXFunction as MX symbols; other classes raise.
casadi_int n_nodes() const
Get the number of nodes in the expression graph (SXFunction and MXFunction)
size_t sz_iw() const
Get the length of the integer work vector needed to evaluate.
size_t sz_w() const
Get the length of the real work vector needed to evaluate.
size_t sz_arg() const
Get the length of the input pointer array needed to evaluate (at least n_in)
Function transform(const Dict &opts=Dict()) const
Rebuild the function after graph simplification or other passes.
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate with a list or a dict of arguments; the result has the same form.
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, size1()*size2()
bool is_dense() const
Check if the matrix is dense, i.e. nnz() equals numel()
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 matrix is empty, i.e. if one of the dimensions is zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape as a pair (number of rows, number of columns)
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of structural nonzeros.
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 (same as size1())
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 is square, i.e. size1() equals size2()
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 is scalar, i.e. 1-by-1.
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
Solve the linear system A*X = B (or A'*X = B with tr true)
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 the node is a matrix product (mtimes)
static MX unary(casadi_int op, const MX &x, bool unique=false)
Create an elementwise binary or unary node from an operation code.
void reset_input() const
Reset the marker set by has_duplicates on 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 the node is a constant with all nonzeros -1 (false negatives possible)
static MX mmax(const MX &x)
bool is_valid_input() const
Check if the expression can be used as a Function input.
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 the node is a constant identity matrix.
bool is_value(double val) const
Check if the node is a constant with all nonzeros equal to val.
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)
MX operator-() const
Unary minus.
bool is_output() const
Check if the node selects one output of a multiple-output node.
casadi_int n_out() const
Number of outputs of this node.
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)
Compute a dense tensor contraction in Einstein notation.
casadi_int n_dep() const
Get the number of dependencies (child nodes) of this node.
casadi_int n_primitives() const
Get the number of symbolic primitives in a valid Function input.
static MX norm_inf(const MX &x)
bool __nonzero__() const
Truth value of a 1-by-1 constant.
bool is_half() const
Check if the node is a constant with all nonzeros 0.5 (false negatives possible)
static std::vector< MX > vertsplit(const MX &x, const std::vector< casadi_int > &offset)
bool is_call() const
Check if the node is a call to a Function.
std::string name() const
Get the name of a symbolic primitive.
bool has_output() const
Check if this is a multiple-output node.
bool is_integer() const
Check if the node is a constant with integer-valued nonzeros.
static MX jacobian(const MX &f, const MX &x, const Dict &opts=Dict())
Matrix< casadi_int > mapping() const
Get the nonzero mapping 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 the node is a constant with all nonzeros +inf (false negatives 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 the node is a constant.
static MX eye(casadi_int n)
Identity matrix constant of size n-by-n, with a diagonal sparsity pattern.
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 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 constant with all nonzeros +inf.
MX dump(const std::string &base_filename, const Dict &opts=Dict()) const
Return the expression with the side effect of writing its value to a file.
void reset_dump_count()
Reset the file counter of a dump node; raises an error on any other node.
bool is_commutative() const
Check if a binary operation is commutative.
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 a value along the symbolic primitives of this expression.
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 primitives in a Function input.
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 the nonzeros as a list of 1-by-1 expressions.
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 the Function of a call node.
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
Check if the node is a certain operation.
bool is_minus_inf() const
Check if the node is a constant with all nonzeros -inf (false negatives possible)
bool is_norm() const
Check if the node is a norm (norm_1, norm_2, norm_inf or norm_fro)
std::vector< MX > primitives() const
Get the symbolic primitives of a valid Function input.
static casadi_int n_nodes(const MX &x)
void set_nz(const MX &m, bool ind1, const Slice &kk)
Assign to a set of nonzeros (what x.nz[k] = m does)
static MX polyval(const MX &p, const MX &x)
MX()
Default constructor: a 0-by-0 constant.
static MX graph_substitute(const MX &x, const std::vector< MX > &v, const std::vector< MX > &vdef)
bool is_regular() const
Check that a constant node contains neither NaN nor Inf.
static MX kron_contract(const MX &m, const MX &x, bool inner)
casadi_int which_output() const
Get the output index of an OutputNode.
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 the expression to a stream.
static MX densify(const MX &x, const MX &val=0)
static std::vector< MX > get_free(const Function &f)
Get the free variables of a Function.
static bool depends_on(const MX &x, const MX &arg)
MX inv() const
Element-wise inverse, 1/x.
static MX mtimes(const MX &x, const MX &y, const std::string &blas="reference")
static MX deserialize(DeserializingStream &s)
Deserialize an expression from a stream, with type disambiguation.
static void set_max_depth(casadi_int eq_depth=1)
Set the depth to which equalities are 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
Return the expression with a run-time assertion attached.
static MX nan(const Sparsity &sp)
Create a constant with all nonzeros NaN.
Dict info() const
Obtain information about the node as a dictionary.
static MX _sym(const std::string &name, const Sparsity &sp)
void set(const MX &m, bool ind1, const Slice &rr)
Assign to a submatrix by linear index (what x[k] = m does)
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())
Evaluate the B-spline basis functions at given points.
static MX trace(const MX &x)
bool is_one() const
Check if the node is a constant with all nonzeros one (false negatives 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 inlined multilinear 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 values along the symbolic primitives of this expression.
MX dep(casadi_int ch=0) const
Get the ch-th dependency (child node) of this node.
MX monitor(const std::string &comment) const
Return the expression with the side effect of printing its value.
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 an elementwise binary or unary node from an operation code.
bool is_binary() const
Check if the node is an elementwise binary operation.
static std::vector< MX > get_input(const Function &f)
Get the symbolic inputs of a Function, as MX.
bool is_unary() const
Check if the node is an elementwise unary operation.
bool is_zero() const
Check if the node is a constant zero (false negatives are possible)
bool is_transpose() const
Check if the node is a transpose operation.
MXNode * operator->()
Access a member of the node.
static bool test_cast(const SharedObjectInternal *ptr)
Check if a SharedObjectInternal pointer refers to an MX node (C++ only)
void get_nz(MX &m, bool ind1, const Slice &kk) const
Get a set of nonzeros (what x.nz[k] does)
bool is_doubled() const
Check if the node is the sum of two equal expressions, or 2*x.
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 the node is a symbolic primitive (created by MX.sym)
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
Return the expression with the side effect of printing its value with a tag.
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 of a multiple-output node.
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 the operation type of the node.
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
Re-apply the operation of this node to new 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
Check that no entry is nan, inf 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
Nonzero index of entry (rr, cc), or -1 if it is a structural zero.
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns of the same shape (also the * operator)
std::vector< casadi_int > erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Turn the entries with rows rr and columns cc into structural zeros, in place.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Pattern of the submatrix with rows rr and columns cc.
void enlarge(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the pattern in place by inserting empty rows and columns.
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Flat (column-major) element index of every nonzero.
bool is_orthonormal(bool allow_empty=false) const
Check whether every row and every column has at most one nonzero.
std::string dim(bool with_nz=false) const
Dimensions as a string "nrow x ncol", optionally with the number of nonzeros.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
Sparsity T() const
Transposed pattern.
Sparsity unite(const Sparsity &y, std::vector< unsigned char > &mapping) const
Union of two sparsity patterns of the same shape (also available as the + operator)
bool is_reshape(const Sparsity &y) const
Check whether y is a reshape of this pattern.
Sparsity get_diag(std::vector< casadi_int > &mapping) const
Pattern of the diagonal of a matrix, or of the diagonal matrix built from a vector.
std::vector< casadi_int > get_col() const
Column index of every nonzero, in nonzero (column-major) order.
static Sparsity reshape(const Sparsity &x, casadi_int nrow, casadi_int ncol)
Accessed by SparsityInterface.
casadi_int nnz() const
Number of structural nonzeros.
std::pair< casadi_int, casadi_int > size() const
Shape as a pair (number of rows, number of columns)
std::size_t hash() const
Hash of the pattern (dimensions, colind and row)
std::vector< casadi_int > get_row() const
Row index of every nonzero, in nonzero (column-major) order.
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern from the (row, col) index of every nonzero.
static Sparsity mtimes(const Sparsity &x, const Sparsity &y, const std::string &blas="reference")
Accessed by SparsityInterface.
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)
void check_offset(const std::vector< casadi_int > &offset, casadi_int n, const std::string &fname)
Assert that offset starts at 0, is nondecreasing and ends at n.
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.