mx_node.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #include "mx_node.hpp"
27 #include "casadi_misc.hpp"
28 #include "transpose.hpp"
29 #include "reshape.hpp"
30 #include "sparsity_cast.hpp"
31 #include "multiplication.hpp"
32 #include "bilin.hpp"
33 #include "rank1.hpp"
34 #include "subref.hpp"
35 #include "subassign.hpp"
36 #include "getnonzeros.hpp"
37 #include "getnonzeros_param.hpp"
38 #include "setnonzeros.hpp"
39 #include "setnonzeros_param.hpp"
40 #include "project.hpp"
41 #include "solve.hpp"
42 #include "unary_mx.hpp"
43 #include "binary_mx.hpp"
44 #include "determinant.hpp"
45 #include "inverse.hpp"
46 #include "dot.hpp"
47 #include "norm.hpp"
48 #include "mmin.hpp"
49 #include "concat.hpp"
50 #include "split.hpp"
51 #include "assertion.hpp"
52 #include "monitor.hpp"
53 #include "dump.hpp"
54 #include "repmat.hpp"
55 #include "kron.hpp"
56 #include "casadi_find.hpp"
57 #include "casadi_low.hpp"
58 #include "einstein.hpp"
59 #include "io_instruction.hpp"
60 #include "symbolic_mx.hpp"
61 #include "constant_mx.hpp"
62 #include "map.hpp"
63 #include "bspline.hpp"
64 #include "convexify.hpp"
65 #include "logsumexp.hpp"
66 
67 // Template implementations
68 #include "setnonzeros_impl.hpp"
69 #include "setnonzeros_param_impl.hpp"
70 #include "solve_impl.hpp"
71 #include "binary_mx_impl.hpp"
72 
73 #include "serializing_stream.hpp"
74 
75 #include <typeinfo>
76 
77 namespace casadi {
78 
80  temp = 0;
81  }
82 
83 
85 
86  // Start destruction method if any of the dependencies has dependencies
87  for (std::vector<MX>::iterator cc=dep_.begin(); cc!=dep_.end(); ++cc) {
88  // Skip if constant
89  if (cc->is_constant()) continue;
90 
91  // Check if there are other "owners" of the node
92  if (cc->getCount()!= 1) {
93 
94  // Replace with a 0-by-0 matrix
95  *cc = MX();
96 
97  } else {
98  // Stack of expressions to be deleted
99  std::stack<MX> deletion_stack;
100 
101  // Move the child to the deletion stack
102  deletion_stack.push(*cc);
103  *cc = MX();
104 
105  // Process stack
106  while (!deletion_stack.empty()) {
107 
108  // Top element
109  MX t = deletion_stack.top();
110 
111  // Check if the top element has dependencies with dependencies
112  bool found_dep = false;
113 
114  // Start destruction method if any of the dependencies has dependencies
115  while (!t->dep_.empty()) {
116  const MX& ii = t->dep_.back();
117 
118  // Skip if constant
119  if (ii.is_constant()) {
120  t->dep_.pop_back();
121  continue;
122  }
123  // Check if this is the only reference to the element
124  if (ii.getCount()==1) {
125  // Remove and add to stack
126  deletion_stack.push(ii);
127  t->dep_.pop_back();
128  found_dep = true;
129  break;
130  } else {
131  t->dep_.pop_back();
132  }
133  }
134 
135  // Pop from stack if no dependencies found
136  if (!found_dep) {
137  deletion_stack.pop();
138  }
139  }
140  }
141  }
142  }
143 
144  casadi_int MXNode::n_primitives() const {
145  return 1;
146  }
147 
148  bool MXNode::has_duplicates() const {
149  casadi_error("'has_duplicates' not defined for class " + class_name());
150  }
151 
152  void MXNode::reset_input() const {
153  casadi_error("'reset_input' not defined for class " + class_name());
154  }
155 
156  void MXNode::primitives(std::vector<MX>::iterator& it) const {
157  *it++ = shared_from_this<MX>();
158  }
159 
160  void MXNode::split_primitives(const MX& x, std::vector<MX>::iterator& it) const {
161  *it++ = x;
162  }
163 
164  void MXNode::split_primitives(const SX& x, std::vector<SX>::iterator& it) const {
165  *it++ = x;
166  }
167 
168  void MXNode::split_primitives(const DM& x, std::vector<DM>::iterator& it) const {
169  *it++ = x;
170  }
171 
172  template<typename T>
173  T MXNode::join_primitives_gen(typename std::vector<T>::const_iterator& it) const {
174  T ret = *it++;
175  if (ret.size()==size()) {
176  return ret;
177  } else {
178  casadi_assert(ret.is_empty(true),
179  "Expected a primitive of dimension " + sparsity().dim() + ", but got " + ret.dim() + ".");
180  return T(size());
181  }
182  }
183 
184  MX MXNode::join_primitives(std::vector<MX>::const_iterator& it) const {
185  return join_primitives_gen<MX>(it);
186  }
187 
188  DM MXNode::join_primitives(std::vector<DM>::const_iterator& it) const {
189  return join_primitives_gen<DM>(it);
190  }
191 
192  SX MXNode::join_primitives(std::vector<SX>::const_iterator& it) const {
193  return join_primitives_gen<SX>(it);
194  }
195 
196  const std::string& MXNode::name() const {
197  casadi_error("'name' not defined for class " + class_name());
198  }
199 
200  std::string MXNode::class_name() const {
201  // Lazy solution
202  return typeid(*this).name();
203  }
204 
205  bool MXNode::__nonzero__() const {
206  casadi_error("Can only determine truth value of a numeric MX.");
207  }
208 
209  casadi_int MXNode::n_dep() const {
210  return dep_.size();
211  }
212 
213  casadi_int MXNode::ind() const {
214  casadi_error("'ind' not defined for class " + class_name());
215  }
216 
217  casadi_int MXNode::segment() const {
218  casadi_error("'segment' not defined for class " + class_name());
219  }
220 
221  casadi_int MXNode::offset() const {
222  casadi_error("'offset' not defined for class " + class_name());
223  }
224 
225  void MXNode::set_sparsity(const Sparsity& sparsity) {
227  }
228 
229  void MXNode::set_dep(const MX& dep) {
230  dep_.resize(1);
231  dep_[0] = dep;
232  check_dep();
233  }
234 
235  void MXNode::set_dep(const MX& dep1, const MX& dep2) {
236  dep_.resize(2);
237  dep_[0] = dep1;
238  dep_[1] = dep2;
239  check_dep();
240  }
241 
242  void MXNode::set_dep(const MX& dep1, const MX& dep2, const MX& dep3) {
243  dep_.resize(3);
244  dep_[0] = dep1;
245  dep_[1] = dep2;
246  dep_[2] = dep3;
247  check_dep();
248  }
249 
250  void MXNode::set_dep(const std::vector<MX>& dep) {
251  dep_ = dep;
252  check_dep();
253  }
254 
255  void MXNode::check_dep() const {
256  for (const MX& e : dep_) {
257  if (e->has_output()) {
258  casadi_assert(is_output(),
259  "You cannot build an expression out of a MultipleOutput node. "
260  "You must select a concrete output by making a get_output() call.");
261  }
262  }
263  }
264 
265  const Sparsity& MXNode::sparsity(casadi_int oind) const {
266  casadi_assert(oind==0, "Index out of bounds");
267  return sparsity_;
268  }
269 
270  void MXNode::disp(std::ostream& stream, bool more) const {
271  // Find out which noded can be inlined
272  std::map<const MXNode*, casadi_int> nodeind;
273  can_inline(nodeind);
274 
275  // Print expression
276  std::vector<std::string> intermed;
277  std::string s = print_compact(nodeind, intermed);
278 
279  // Print intermediate expressions
280  for (casadi_int i=0; i<intermed.size(); ++i)
281  stream << "@" << (i+1) << "=" << intermed[i] << ", ";
282 
283  // Print this
284  stream << s;
285  }
286 
287  void MXNode::can_inline(std::map<const MXNode*, casadi_int>& nodeind) const {
288  // Add or mark node in map
289  std::map<const MXNode*, casadi_int>::iterator it=nodeind.find(this);
290  if (it==nodeind.end()) {
291  // First time encountered, mark inlined
292  nodeind.insert(it, std::make_pair(this, 0));
293 
294  // Handle dependencies with recursion
295  for (casadi_int i=0; i<n_dep(); ++i) {
296  dep(i)->can_inline(nodeind);
297  }
298  } else if (it->second==0 && op()!=OP_PARAMETER) {
299  // Node encountered before, do not inline (except if symbolic primitive)
300  it->second = -1;
301  }
302  }
303 
304  std::string MXNode::print_compact(std::map<const MXNode*, casadi_int>& nodeind,
305  std::vector<std::string>& intermed) const {
306  // Get reference to node index
307  casadi_int& ind = nodeind[this];
308 
309  // If positive, already in intermediate expressions
310  if (ind>0) return "@" + str(ind);
311 
312  // Get expressions for dependencies
313  std::vector<std::string> arg(n_dep());
314  for (casadi_int i=0; i<arg.size(); ++i) {
315  arg[i] = dep(i)->print_compact(nodeind, intermed);
316  }
317 
318  // Get expression for this
319  std::string s = disp(arg);
320 
321  // Decide what to do with the expression
322  if (ind==0) {
323  // Inline expression
324  return s;
325  } else {
326  // Add to list of intermediate expressions and return reference
327  intermed.push_back(s);
328  ind = intermed.size(); // For subsequent references
329  return "@" + str(ind);
330  }
331  }
332 
334  casadi_error("'which_function' not defined for class " + class_name());
335  }
336 
337  casadi_int MXNode::which_output() const {
338  casadi_error("'which_output' not defined for class " + class_name());
339  }
340 
341  int MXNode::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
342  casadi_error("'eval' not defined for class " + class_name());
343  return 1;
344  }
345 
346  int MXNode::eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
347  casadi_error("'eval_sx' not defined for class " + class_name());
348  return 1;
349  }
350 
351  void MXNode::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
352  const std::vector<bool>& unique) const {
353  casadi_error("'eval_mx' not defined for class " + class_name());
354  }
355 
356  void MXNode::eval_linear(const std::vector<std::array<MX, 3> >& arg,
357  std::vector<std::array<MX, 3> >& res) const {
358  std::vector<MX> arg_sum(arg.size());
359  for (casadi_int i=0; i<arg.size(); ++i) {
360  arg_sum[i] = arg[i][0] + arg[i][1] + arg[i][2];
361  }
362  std::vector<MX> res_nonlin(res.size());
363  eval_mx(arg_sum, res_nonlin);
364  for (casadi_int i=0; i<res.size(); ++i) {
365  res[i][0] = MX::zeros(sparsity());
366  res[i][1] = MX::zeros(sparsity());
367  res[i][2] = res_nonlin[i];
368  }
369  }
370 
371  void MXNode::eval_linear_rearrange(const std::vector<std::array<MX, 3> >& arg,
372  std::vector<std::array<MX, 3> >& res) const {
373  // Treat each category separately
374  for (casadi_int i=0; i<3; ++i) {
375  // Read arguments for categiry i
376  std::vector<MX> eval_arg(n_dep());
377  for (casadi_int j=0; j<n_dep(); ++j) {
378  eval_arg[j] = arg[j][i];
379  }
380  std::vector<MX> eval_res(nout());
381  // Normal symbolic evaluation
382  eval_mx(eval_arg, eval_res);
383  // Assign results
384  for (casadi_int j=0; j<nout(); ++j) {
385  res[j][i] = eval_res[j];
386  }
387  }
388  }
389 
390  void MXNode::ad_forward(const std::vector<std::vector<MX> >& fseed,
391  std::vector<std::vector<MX> >& fsens) const {
392  casadi_error("'ad_forward' not defined for class " + class_name());
393  }
394 
395  void MXNode::ad_reverse(const std::vector<std::vector<MX> >& aseed,
396  std::vector<std::vector<MX> >& asens) const {
397  casadi_error("'ad_reverse' not defined for class " + class_name());
398  }
399 
400  int MXNode::sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
401  // By default, everything depends on everything
402  bvec_t all_depend(0);
403 
404  // Get dependencies of all inputs
405  for (casadi_int k=0; k<n_dep(); ++k) {
406  const bvec_t* v = arg[k];
407  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
408  all_depend |= v[i];
409  }
410  }
411 
412  // Propagate to all outputs
413  for (casadi_int k=0; k<nout(); ++k) {
414  bvec_t* v = res[k];
415  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
416  v[i] = all_depend;
417  }
418  }
419  return 0;
420  }
421 
422  int MXNode::sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
423  // By default, everything depends on everything
424  bvec_t all_depend(0);
425 
426  // Get dependencies of all outputs
427  for (casadi_int k=0; k<nout(); ++k) {
428  bvec_t* v = res[k];
429  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
430  all_depend |= v[i];
431  v[i] = 0;
432  }
433  }
434 
435  // Propagate to all inputs
436  for (casadi_int k=0; k<n_dep(); ++k) {
437  bvec_t* v = arg[k];
438  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
439  v[i] |= all_depend;
440  }
441  }
442  return 0;
443  }
444 
445  MX MXNode::get_output(casadi_int oind) const {
446  casadi_assert(oind==0, "Output index out of bounds");
447  return shared_from_this<MX>();
448  }
449 
451  const std::vector<casadi_int>& arg,
452  const std::vector<casadi_int>& res,
453  const std::vector<bool>& arg_is_ref,
454  std::vector<bool>& res_is_ref) const {
455  casadi_warning("Cannot code generate MX nodes of type " + class_name() +
456  "The generation will proceed, but compilation of the code will "
457  "not be possible.");
458  g << "#error " << class_name() << ": " << arg << " => " << res << '\n';
459  }
460 
462  const std::vector<casadi_int>& arg,
463  const std::vector<casadi_int>& res,
464  const std::vector<bool>& arg_is_ref,
465  std::vector<bool>& res_is_ref,
466  casadi_int i) const {
467  res_is_ref[i] = arg_is_ref[i];
468  if (arg[i]==res[i]) return;
469  if (nnz()==1) {
470  g << g.workel(res[i]) << " = " << g.workel(arg[i]) << ";\n";
471  } else if (arg_is_ref[i]) {
472  g << g.work(res[i], nnz(), true) << " = " << g.work(arg[i], nnz(), true) << ";\n";
473  } else {
474  g << g.copy(g.work(arg[i], nnz(), false), nnz(), g.work(res[i], nnz(), false)) << "\n";
475  }
476  }
477 
478 
479 
480  double MXNode::to_double() const {
481  casadi_error("'to_double' not defined for class " + class_name());
482  }
483 
484  casadi_int MXNode::to_int() const {
485  casadi_error("'to_int' not defined for class " + class_name());
486  }
487 
488  DM MXNode::get_DM() const {
489  casadi_error("'get_DM' not defined for class " + class_name());
490  }
491 
493  if (sparsity().is_scalar()) {
494  return shared_from_this<MX>();
495  } else if (sparsity().is_vector()) {
496  return get_reshape(sparsity().T());
497  } else if (sparsity().is_dense()) {
498  return MX::create(new DenseTranspose(shared_from_this<MX>()));
499  } else {
500  return MX::create(new Transpose(shared_from_this<MX>()));
501  }
502  }
503 
504  MX MXNode::get_reshape(const Sparsity& sp) const {
505  casadi_assert_dev(sp.is_reshape(sparsity()));
506  if (sp==sparsity()) {
507  return shared_from_this<MX>();
508  } else {
509  return MX::create(new Reshape(shared_from_this<MX>(), sp));
510  }
511  }
512 
514  casadi_assert_dev(sp.nnz()==nnz());
515  if (sp==sparsity()) {
516  return shared_from_this<MX>();
517  } else {
518  return MX::create(new SparsityCast(shared_from_this<MX>(), sp));
519  }
520  }
521 
522  Dict MXNode::info() const {
523  return Dict();
524  }
525 
527  serialize_type(s);
528  serialize_body(s);
529  }
530 
532  s.pack("MXNode::deps", dep_);
533  s.pack("MXNode::sp", sparsity_);
534  }
535 
537  s.pack("MXNode::op", static_cast<int>(op()));
538  }
539 
541  temp = 0;
542 
543  s.unpack("MXNode::deps", dep_);
544  s.unpack("MXNode::sp", sparsity_);
545  }
546 
547 
549  int op;
550  s.unpack("MXNode::op", op);
551 
554  } else if (casadi_math<MX>::is_unary(op)) {
555  return UnaryMX::deserialize(s);
556  }
557 
558  auto it = MXNode::deserialize_map.find(op);
559  if (it==MXNode::deserialize_map.end()) {
560  casadi_error("Not implemented op " + str(casadi_int(op)) + ":" + str(OP_GETNONZEROS));
561  } else {
562  return it->second(s);
563  }
564  }
565 
566 
567  MX MXNode::get_mac(const MX& y, const MX& z, const std::string& blas) const {
568  if (sparsity().is_orthonormal() && y.is_column() && y.is_dense()
569  && y.sparsity()==z.sparsity() && z.is_zero()) {
570  std::vector<casadi_int> perm = sparsity().permutation_vector();
571  MX nz = sparsity_cast(shared_from_this<MX>(), Sparsity::dense(nnz()));
572  return (nz*y)(perm);
573  }
574  // Get reference to transposed first argument
575  MX x = shared_from_this<MX>();
576 
577  casadi_assert(y.size2()==z.size2(),
578  "Dimension error x.mac(z). Got y=" + str(y.size2()) + " and z=" + z.dim() + ".");
579  casadi_assert(x.size1()==z.size1(),
580  "Dimension error x.mac(z). Got x=" + x.dim() + " and z=" + z.dim() + ".");
581  casadi_assert(y.size1()==x.size2(),
582  "Dimension error x.mac(z). Got y=" + str(y.size1()) + " and x" + x.dim() + ".");
583  return Multiplication::create(z, x, y, blas);
584  }
585 
586  MX MXNode::get_einstein(const MX& A, const MX& B,
587  const std::vector<casadi_int>& dim_c, const std::vector<casadi_int>& dim_a,
588  const std::vector<casadi_int>& dim_b,
589  const std::vector<casadi_int>& c, const std::vector<casadi_int>& a,
590  const std::vector<casadi_int>& b) const {
591 
592  if (A.is_zero() || B.is_zero())
593  return shared_from_this<MX>();
594 
595  MX C = densify(shared_from_this<MX>());
596 
597  if (A.is_constant() && B.is_constant() && C.is_constant()) {
598  // Constant folding
599  DM Ac = A->get_DM();
600  DM Bc = B->get_DM();
601  DM Cc = C->get_DM();
602  return einstein(vec(densify(Ac)), vec(densify(Bc)), vec(densify(Cc)),
603  dim_a, dim_b, dim_c, a, b, c);
604  }
605 
606  return MX::create(new Einstein(C, densify(A), densify(B), dim_c, dim_a, dim_b, c, a, b));
607  }
608 
609  MX MXNode::get_bilin(const MX& x, const MX& y) const {
610  return MX::create(new Bilin(shared_from_this<MX>(), x, y));
611  }
612 
613  MX MXNode::get_rank1(const MX& alpha, const MX& x, const MX& y) const {
614  return MX::create(new Rank1(shared_from_this<MX>(), alpha, x, y));
615  }
616 
618  return MX::create(new LogSumExp(shared_from_this<MX>()));
619  }
620 
621  MX MXNode::get_solve_triu(const MX& r, bool tr) const {
622  if (tr) {
623  return MX::create(new TriuSolve<true>(densify(r), shared_from_this<MX>()));
624  } else {
625  return MX::create(new TriuSolve<false>(densify(r), shared_from_this<MX>()));
626  }
627  }
628 
629  MX MXNode::get_solve_tril(const MX& r, bool tr) const {
630  if (tr) {
631  return MX::create(new TrilSolve<true>(densify(r), shared_from_this<MX>()));
632  } else {
633  return MX::create(new TrilSolve<false>(densify(r), shared_from_this<MX>()));
634  }
635  }
636 
637  MX MXNode::get_solve_triu_unity(const MX& r, bool tr) const {
638  if (tr) {
639  return MX::create(new TriuSolveUnity<true>(densify(r), shared_from_this<MX>()));
640  } else {
641  return MX::create(new TriuSolveUnity<false>(densify(r), shared_from_this<MX>()));
642  }
643  }
644 
645  MX MXNode::get_solve_tril_unity(const MX& r, bool tr) const {
646  if (tr) {
647  return MX::create(new TrilSolveUnity<true>(densify(r), shared_from_this<MX>()));
648  } else {
649  return MX::create(new TrilSolveUnity<false>(densify(r), shared_from_this<MX>()));
650  }
651  }
652 
653  MX MXNode::get_solve(const MX& r, bool tr, const Linsol& linear_solver) const {
654  if (tr) {
655  return MX::create(new LinsolCall<true>(densify(r), shared_from_this<MX>(), linear_solver));
656  } else {
657  return MX::create(new LinsolCall<false>(densify(r), shared_from_this<MX>(), linear_solver));
658  }
659  }
660 
661  MX MXNode::get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz, bool unique) const {
662  if (sparsity().is_dense() && is_range(nz, 0, nnz())) {
663  return sparsity_cast(shared_from_this<MX>(), sp);
664  }
665  return GetNonzeros::create(sp, shared_from_this<MX>(), nz);
666  }
667 
668  MX MXNode::get_nz_ref(const MX& nz) const {
669  return GetNonzerosParam::create(shared_from_this<MX>(), nz);
670  }
671 
672  MX MXNode::get_nz_ref(const MX& inner, const Slice& outer) const {
673  if (outer.all()==std::vector<casadi_int>{0}) {
674  return get_nz_ref(inner);
675  } else {
676  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
677  }
678  }
679 
680  MX MXNode::get_nz_ref(const Slice& inner, const MX& outer) const {
681  if (inner.all()==std::vector<casadi_int>{0}) {
682  return get_nz_ref(outer);
683  } else {
684  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
685  }
686  }
687 
688  MX MXNode::get_nz_ref(const MX& inner, const MX& outer) const {
689  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
690  }
691 
692  MX MXNode::get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const {
693  // Check if any element needs to be set at all
694  bool set_any = false;
695  for (auto i=nz.begin(); i!=nz.end() && !set_any; ++i) {
696  set_any = *i >= 0;
697  }
698  if (!set_any) return y;
699 
700  return SetNonzeros<false>::create(y, shared_from_this<MX>(), nz);
701  }
702 
703 
704  MX MXNode::get_nzadd(const MX& y, const std::vector<casadi_int>& nz) const {
705  if (nz.empty() || is_zero()) {
706  return y;
707  } else {
708  return SetNonzeros<true>::create(y, shared_from_this<MX>(), nz);
709  }
710  }
711 
712  MX MXNode::get_nzassign(const MX& y, const MX& nz) const {
713  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), nz);
714  }
715 
716  MX MXNode::get_nzassign(const MX& y, const MX& inner, const Slice& outer) const {
717  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
718  }
719 
720  MX MXNode::get_nzassign(const MX& y, const Slice& inner, const MX& outer) const {
721  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
722  }
723 
724  MX MXNode::get_nzassign(const MX& y, const MX& inner, const MX& outer) const {
725  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
726  }
727 
728  MX MXNode::get_nzadd(const MX& y, const MX& nz) const {
729  if (nz.is_empty() || is_zero()) {
730  return y;
731  } else {
732  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), nz);
733  }
734  }
735 
736  MX MXNode::get_nzadd(const MX& y, const MX& inner, const Slice& outer) const {
737  if (inner.is_empty() || outer.is_empty() || is_zero()) {
738  return y;
739  } else {
740  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
741  }
742  }
743 
744  MX MXNode::get_nzadd(const MX& y, const Slice& inner, const MX& outer) const {
745  if (outer.is_empty() || outer.is_empty() || is_zero()) {
746  return y;
747  } else {
748  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
749  }
750  }
751 
752  MX MXNode::get_nzadd(const MX& y, const MX& inner, const MX& outer) const {
753  if (inner.is_empty() || outer.is_empty() || is_zero()) {
754  return y;
755  } else {
756  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
757  }
758  }
759 
760  MX MXNode::get_project(const Sparsity& sp, bool unique) const {
761  if (sp==sparsity()) {
762  return shared_from_this<MX>();
763  } else if (sp.nnz()==0) {
764  return MX::zeros(sp);
765  } else if (sp.is_dense()) {
766  return MX::create(new Densify(shared_from_this<MX>(), sp));
767  } else if (sparsity().is_dense()) {
768  return MX::create(new Sparsify(shared_from_this<MX>(), sp));
769  } else {
770  return MX::create(new Project(shared_from_this<MX>(), sp));
771  }
772  }
773 
774  MX MXNode::get_subref(const Slice& i, const Slice& j) const {
775  return MX::create(new SubRef(shared_from_this<MX>(), i, j));
776  }
777 
778  MX MXNode::get_subassign(const MX& y, const Slice& i, const Slice& j) const {
779  return MX::create(new SubAssign(shared_from_this<MX>(), y, i, j));
780  }
781 
782  MX MXNode::get_unary(casadi_int op, bool unique) const {
783  if (operation_checker<F0XChecker>(op) && is_zero()) {
784  // If identically zero
785  return MX::zeros(sparsity());
786  } else {
787  bool hit;
788  MX ret = common_simp_unary(op, shared_from_this<MX>(), maxDepth(),
789  [](casadi_int op, const MX& a) { return a->get_unary(op);},
790  unique,
791  hit);
792  if (hit) return ret;
793  // Create a new node
794  return MX::create(new UnaryMX(Operation(op), shared_from_this<MX>()));
795  }
796  }
797 
798  MX MXNode::get_binary(casadi_int op, const MX& y, bool unique_x, bool unique_y) const {
799  // If-else-zero nodes are always simplified at top level to avoid NaN propagation
800  if (y.op() == OP_IF_ELSE_ZERO) {
801  if (op == OP_MUL) {
802  // (Rule 1.) x * if_else_zero(c, y), simplified to if_else_zero(c, x * y)
803  // Background: x is often a partial derivative and may evaluate to INF or NAN.
804  // The simplification ensures that the zero seed corresponding to an inactive branch does
805  // not give rise to any NaN contribution to the derivative due to NaN * 0 == NaN.
806  return if_else_zero(y.dep(0), shared_from_this<MX>() * y.dep(1));
807  } else if (op == OP_ADD && this->op() == OP_IF_ELSE_ZERO && MX::is_equal(dep(0), y.dep(0))) {
808  // (Rule 2.) if_else_zero(c, x) + if_else_zero(c, y) is simplified to if_else_zero(c, x + y)
809  // Background: During the backward propagation, seeds are added together. Without this rule,
810  // the addition node can prevent rule (1.) from working in subsequent steps.
811  return if_else_zero(y.dep(0), dep(1) + y.dep(1));
812  }
813  } else if (this->op() == OP_IF_ELSE_ZERO && op == OP_MUL) {
814  // Same as Rule 1. above, but with factors swapped. For symmetry.
815  return if_else_zero(dep(0), dep(1) * y);
816  }
817  // Create binary node
818  if (sparsity().is_scalar(false)) {
819  if (nnz()==0) {
820  if (operation_checker<F0XChecker>(op)) return MX::zeros(Sparsity(y.size()));
821  return to_matrix(MX(0)->_get_binary(op, y, true, false, unique_x, unique_y), y.sparsity());
822  } else {
823  return to_matrix(_get_binary(op, y, true, false, unique_x, unique_y), y.sparsity());
824  }
825  } else if (y.is_scalar()) {
826  if (y.nnz()==0) {
827  if (operation_checker<FX0Checker>(op)) return MX::zeros(Sparsity(size()));
828  return to_matrix(_get_binary(op, MX(0), false, true, unique_x, unique_y), sparsity());
829  } else {
830  return to_matrix(_get_binary(op, y, false, true, unique_x, unique_y), sparsity());
831  }
832  } else {
833  casadi_assert(sparsity().size() == y.sparsity().size(), "Dimension mismatch.");
834  if (sparsity()==y.sparsity()) {
835  // Matching sparsities
836  return _get_binary(op, y, false, false, unique_x, unique_y);
837  } else {
838  // Get the sparsity pattern of the result
839  // (ignoring structural zeros giving rise to nonzero result)
840  const Sparsity& x_sp = sparsity();
841  const Sparsity& y_sp = y.sparsity();
842  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
843  operation_checker<FX0Checker>(op));
844 
845  // Project the arguments to this sparsity
846  MX xx = project(shared_from_this<MX>(), r_sp);
847  MX yy = project(y, r_sp);
848  return xx->_get_binary(op, yy, false, false, unique_x, unique_y);
849  }
850  }
851  }
852 
853  MX MXNode::_get_binary(casadi_int op, const MX& y, bool scX, bool scY,
854  bool unique_x, bool unique_y) const {
855  casadi_assert_dev(sparsity()==y.sparsity() || scX || scY);
856 
858 
859  // If identically zero due to one argument being zero
860  if ((operation_checker<F0XChecker>(op) && nnz()==0) ||
861  (operation_checker<FX0Checker>(op) && y->nnz()==0)) {
862  return MX::zeros(Sparsity(size()));
863  }
864 
865  if ((operation_checker<F0XChecker>(op) && is_zero()) ||
866  (operation_checker<FX0Checker>(op) && y->is_zero())) {
867  return MX::zeros(sparsity());
868  }
869 
870  if (sparsity().is_scalar(true) && y.is_scalar(true)) {
871  bool hit;
872  MX ret = common_simp_binary(op, shared_from_this<MX>(), y, maxDepth(),
873  [](casadi_int op, const MX& a) { return a->get_unary(op);},
874  [](casadi_int op, const MX& a, const MX& b) {
875  return a->_get_binary(op, b, true, true);
876  },
877  unique_x,
878  unique_y,
879  hit);
880  if (hit) return ret;
881  }
882 
883  // Handle special operations (independent of type)
884  switch (op) {
885  case OP_ADD:
886  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_TWICE);
887  break;
888  case OP_SUB:
889  case OP_NE:
890  case OP_LT:
891  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::zeros(sparsity());
892  break;
893  case OP_DIV:
894  if (y->is_zero()) return MX::nan(sparsity());
895  // fall-through
896  case OP_EQ:
897  case OP_LE:
898  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::ones(sparsity());
899  break;
900  case OP_MUL:
901  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_SQ);
902  break;
903  default: break; // no rule
904  }
905 
906  // Handle special cases for the second argument
907  switch (y->op()) {
908  case OP_CONST:
909  // Make the constant the first argument, if possible
910  if (this->op()!=OP_CONST && operation_checker<CommChecker>(op)) {
911  return y->_get_binary(op, shared_from_this<MX>(), scY, scX);
912  } else {
913  switch (op) {
914  case OP_POW:
915  return _get_binary(OP_CONSTPOW, y, scX, scY);
916  case OP_CONSTPOW:
917  if (y->is_value(-1)) return get_unary(OP_INV);
918  else if (y->is_value(0)) return MX::ones(size());
919  else if (y->is_value(1)) return shared_from_this<MX>();
920  else if (y->is_value(2)) return get_unary(OP_SQ);
921  break;
922  case OP_ADD:
923  case OP_SUB:
924  if (y->is_zero())
925  return scX ? repmat(shared_from_this<MX>(), y.size()) : shared_from_this<MX>();
926  break;
927  case OP_MUL:
928  if (y->is_value(1)) return shared_from_this<MX>();
929  break;
930  case OP_DIV:
931  if (y->is_value(1)) return shared_from_this<MX>();
932  else if (y->is_value(0.5)) return get_unary(OP_TWICE);
933  break;
934  default: break; // no rule
935  }
936  }
937  break;
938  case OP_NEG:
939  if (op==OP_ADD) {
940  return _get_binary(OP_SUB, y->dep(), scX, scY);
941  } else if (op==OP_SUB) {
942  return _get_binary(OP_ADD, y->dep(), scX, scY);
943  } else if (op==OP_MUL) {
944  return -_get_binary(OP_MUL, y->dep(), scX, scY);
945  } else if (op==OP_DIV) {
946  return -_get_binary(OP_DIV, y->dep(), scX, scY);
947  }
948  break;
949  case OP_INV:
950  if (op==OP_MUL) {
951  return _get_binary(OP_DIV, y->dep(), scX, scY);
952  } else if (op==OP_DIV) {
953  return _get_binary(OP_MUL, y->dep(), scX, scY);
954  }
955  break;
956  default: break; // no rule
957  }
958 
959  }
960 
961  if (scX) {
962  // Check if it is ok to loop over nonzeros only
963  if (y.is_dense() || operation_checker<FX0Checker>(op) ||
964  (is_zero() && operation_checker<F00Checker>(op))) {
965  // Loop over nonzeros
966  return MX::create(new BinaryMX<true, false>(Operation(op), shared_from_this<MX>(), y));
967  } else {
968  // Put a densification node in between
969  return _get_binary(op, densify(y), true, false);
970  }
971  } else if (scY) {
972  // Check if it is ok to loop over nonzeros only
973  if (sparsity().is_dense() || operation_checker<F0XChecker>(op) ||
974  (y.is_zero() && operation_checker<F00Checker>(op)) ||
975  (y.is_constant() && static_cast<double>(y)>0 && (op==OP_CONSTPOW || op==OP_POW))) {
976  // Loop over nonzeros
977  return MX::create(new BinaryMX<false, true>(Operation(op), shared_from_this<MX>(), y));
978  } else {
979  // Put a densification node in between
980  return densify(shared_from_this<MX>())->_get_binary(op, y, false, true);
981  }
982  } else {
983  // Loop over nonzeros only
984  MX rr = MX::create(new BinaryMX<false, false>(Operation(op), shared_from_this<MX>(), y));
985 
986  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
987  if (!rr.is_dense() && !operation_checker<F00Checker>(op)) {
988  // Get the value for the structural zeros
989  double fcn_0(0);
990  casadi_math<double>::fun(op, 0, 0, fcn_0);
991  rr = densify(rr, fcn_0);
992  }
993  return rr;
994  }
995  }
996 
998  casadi_error("'mapping' not defined for class " + class_name());
999  }
1000 
1001  bool MXNode::sameOpAndDeps(const MXNode* node, casadi_int depth) const {
1002  if (op()!=node->op() || n_dep()!=node->n_dep())
1003  return false;
1004  for (casadi_int i=0; i<n_dep(); ++i) {
1005  if (!MX::is_equal(dep(i), node->dep(i), depth-1))
1006  return false;
1007  }
1008  return true;
1009  }
1010 
1011  MX MXNode::get_assert(const MX& y, const std::string& fail_message) const {
1012  return MX::create(new Assertion(shared_from_this<MX>(), y, fail_message));
1013  }
1014 
1015  MX MXNode::get_monitor(const std::string& comment) const {
1016  if (nnz()==0) {
1017  return shared_from_this<MX>();
1018  } else {
1019  return MX::create(new Monitor(shared_from_this<MX>(), comment));
1020  }
1021  }
1022 
1023  MX MXNode::get_dump(const std::string& base_filename, const Dict& opts) const {
1024  if (nnz()==0) {
1025  return shared_from_this<MX>();
1026  } else {
1027  std::string dir = ".";
1028  std::string format = "mtx";
1029  bool verbose = false;
1030  for (auto&& op : opts) {
1031  if (op.first=="dir") {
1032  dir = op.second.to_string();
1033  } else if (op.first=="format") {
1034  format = op.second.to_string();
1035  } else if (op.first=="verbose") {
1036  verbose = op.second.to_bool();
1037  } else {
1038  casadi_error("Unknown option '" + op.first + "' for dump. "
1039  "Allowed options: 'dir', 'format', 'verbose'.");
1040  }
1041  }
1042  return MX::create(new Dump(shared_from_this<MX>(), base_filename,
1043  dir, format, verbose));
1044  }
1045  }
1046 
1048  MX x = shared_from_this<MX>();
1049  casadi_assert(x.is_vector(), "Argument must be vector, got " + x.dim() + ".");
1050  if (x.is_column()) {
1051  return MX::create(new Find(shared_from_this<MX>()));
1052  } else {
1053  return find(x.T());
1054  }
1055  }
1056 
1057  MX MXNode::get_low(const MX& v, const Dict& options) const {
1058  return MX::create(new Low(v, shared_from_this<MX>(), options));
1059  }
1060 
1061  MX MXNode::get_bspline(const std::vector<double>& knots,
1062  const std::vector<casadi_int>& offset,
1063  const std::vector<double>& coeffs,
1064  const std::vector<casadi_int>& degree,
1065  casadi_int m,
1066  const std::vector<casadi_int>& lookup_mode) const {
1067  MX x = shared_from_this<MX>();
1068  return MX::create(new BSpline(x, knots, offset, coeffs, degree, m, lookup_mode));
1069  }
1070 
1071  MX MXNode::get_bspline(const MX& coeffs,
1072  const std::vector<double>& knots,
1073  const std::vector<casadi_int>& offset,
1074  const std::vector<casadi_int>& degree,
1075  casadi_int m,
1076  const std::vector<casadi_int>& lookup_mode) const {
1077  MX x = shared_from_this<MX>();
1078  return MX::create(new BSplineParametric(x, coeffs, knots, offset, degree, m, lookup_mode));
1079  }
1080 
1081  MX MXNode::get_convexify(const Dict& opts) const {
1082  return MX::create(new Convexify(shared_from_this<MX>(), opts));
1083  }
1084 
1085  MX MXNode::get_det(const Linsol& linear_solver) const {
1086  return MX::create(new Determinant(shared_from_this<MX>(), linear_solver));
1087  }
1088 
1090  return MX::create(new Inverse(shared_from_this<MX>()));
1091  }
1092 
1093 
1094  MX MXNode::get_dot(const MX& y) const {
1095  casadi_assert(
1096  size2()==y.size2() && size1()==y.size1(),
1097  "MXNode::dot: Dimension mismatch. dot requires its "
1098  "two arguments to have equal shapes, but got ("
1099  + str(size2()) + ", " + str(size1()) + ") and ("
1100  + str(y.size2()) + ", " + str(y.size1()) + ").");
1101  if (sparsity()==y.sparsity()) {
1102  if (sparsity().nnz()==0) {
1103  return 0;
1104  } else if (sparsity().is_scalar()) {
1105  return get_binary(OP_MUL, y);
1106  } else {
1107  if (shared_from_this<MX>().is_zero() || y.is_zero()) return 0;
1108  return MX::create(new Dot(shared_from_this<MX>(), y));
1109  }
1110  } else {
1111  // Project to pattern intersection
1112  Sparsity sp = sparsity().intersect(y.sparsity());
1113  MX xx = project(shared_from_this<MX>(), sp);
1114  MX yy = project(y, sp);
1115  return xx->get_dot(yy);
1116  }
1117  }
1118 
1120  return MX::create(new NormF(shared_from_this<MX>()));
1121  }
1122 
1124  return MX::create(new Norm2(shared_from_this<MX>()));
1125  }
1126 
1128  return MX::create(new NormInf(shared_from_this<MX>()));
1129  }
1130 
1132  return MX::create(new Norm1(shared_from_this<MX>()));
1133  }
1134 
1136  if (sparsity_.is_empty()) return MX();
1137  return MX::create(new MMin(shared_from_this<MX>()));
1138  }
1139 
1141  if (sparsity_.is_empty()) return MX();
1142  return MX::create(new MMax(shared_from_this<MX>()));
1143  }
1144 
1145  MX MXNode::get_horzcat(const std::vector<MX>& x) const {
1146  // Check if there is any existing horzcat operation
1147  for (auto i=x.begin(); i!=x.end(); ++i) {
1148  if (i->op()==OP_HORZCAT) {
1149  // Split up
1150  std::vector<MX> x_split(x.begin(), i);
1151  for (; i!=x.end(); ++i) {
1152  if (i->op()==OP_HORZCAT) {
1153  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1154  } else {
1155  x_split.push_back(*i);
1156  }
1157  }
1158  return horzcat(x_split);
1159  }
1160  }
1161 
1162  // Create a Horzcat node
1163  return MX::create(new Horzcat(x));
1164  }
1165 
1166  MX MXNode::get_diagcat(const std::vector<MX>& x) const {
1167  // Create a Horzcat node
1168  return MX::create(new Diagcat(x));
1169  }
1170 
1171  MX MXNode::get_vertcat(const std::vector<MX>& x) const {
1172  // Check if there is any existing vertcat operation
1173  for (auto i=x.begin(); i!=x.end(); ++i) {
1174  if (i->op()==OP_VERTCAT) {
1175  // Split up
1176  std::vector<MX> x_split(x.begin(), i);
1177  for (; i!=x.end(); ++i) {
1178  if (i->op()==OP_VERTCAT) {
1179  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1180  } else {
1181  x_split.push_back(*i);
1182  }
1183  }
1184  return vertcat(x_split);
1185  }
1186  }
1187 
1188  return MX::create(new Vertcat(x));
1189  }
1190 
1191  std::vector<MX> MXNode::get_horzsplit(const std::vector<casadi_int>& output_offset) const {
1192  if (is_zero()) {
1193  std::vector<MX> ret =
1194  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1195  for (casadi_int i=0;i<ret.size();++i) {
1196  ret[i]=MX::zeros(ret[i].sparsity());
1197  }
1198  return ret;
1199  }
1200  std::vector<MX> ret =
1201  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1202 
1204  // Simplify horzsplit(horzcat)
1205  if (op()==OP_HORZCAT) {
1206  casadi_int offset_deps = 0;
1207  casadi_int j = 0;
1208  for (casadi_int i=0;i<output_offset.size();++i) {
1209  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size2();++j; }
1210  if (j>=n_dep()) j = n_dep()-1;
1211  if (output_offset[i]==offset_deps &&
1212  (i+1<output_offset.size()?output_offset[i+1]:size2()) ==
1213  offset_deps +dep(j).size2()) {
1214  // Aligned with vertcat dependency
1215  ret[i] = dep(j);
1216  }
1217  }
1218  }
1219  }
1220  return ret;
1221  }
1222 
1223  MX MXNode::get_repmat(casadi_int n, casadi_int m) const {
1224  if (n==1) {
1225  return MX::create(new HorzRepmat(shared_from_this<MX>(), m));
1226  } else {
1227  // Fallback to generic_matrix impl
1228  return GenericMatrix<MX>::repmat(shared_from_this<MX>(), n, m);
1229  }
1230  }
1231 
1232  MX MXNode::get_repsum(casadi_int n, casadi_int m) const {
1233  if (n==1) {
1234  return MX::create(new HorzRepsum(shared_from_this<MX>(), m));
1235  } else {
1236  // Fallback to generic_matrix impl
1237  return GenericMatrix<MX>::repsum(shared_from_this<MX>(), n, m);
1238  }
1239  }
1240 
1241  MX MXNode::get_kron(const MX& b) const {
1242  if (nnz() == 0 || b.nnz() == 0) {
1243  return MX::zeros(Sparsity::kron(sparsity(), b.sparsity()));
1244  }
1245  return Kron::create(shared_from_this<MX>(), b);
1246  }
1247 
1248  MX MXNode::get_kron_contract(const MX& x, bool inner) const {
1249  if (nnz() == 0 || x.nnz() == 0) {
1250  return MX::zeros(Sparsity::kron_contract(sparsity(), x.sparsity(), inner));
1251  }
1252  return KronContract::create(shared_from_this<MX>(), x, inner);
1253  }
1254 
1255  std::vector<MX> MXNode::get_diagsplit(const std::vector<casadi_int>& offset1,
1256  const std::vector<casadi_int>& offset2) const {
1257  if (is_zero()) {
1258  std::vector<MX> ret =
1259  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1260  for (casadi_int i=0;i<ret.size();++i) {
1261  ret[i]=MX::zeros(ret[i].sparsity());
1262  }
1263  return ret;
1264  }
1265  std::vector<MX> ret =
1266  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1267 
1268  return ret;
1269  }
1270 
1271  std::vector<MX> MXNode::get_vertsplit(const std::vector<casadi_int>& output_offset) const {
1272  if (is_zero()) {
1273  std::vector<MX> ret =
1274  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1275  for (casadi_int i=0;i<ret.size();++i) {
1276  ret[i]=MX::zeros(ret[i].sparsity());
1277  }
1278  return ret;
1279  }
1280  std::vector<MX> ret =
1281  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1282 
1284  // Simplify vertsplit(vertcat)
1285  if (op()==OP_VERTCAT) {
1286  casadi_int offset_deps = 0;
1287  casadi_int j = 0;
1288  for (casadi_int i=0;i<output_offset.size();++i) {
1289  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size1();++j; }
1290  if (j>=n_dep()) j = n_dep()-1;
1291  if (output_offset[i]==offset_deps &&
1292  (i+1<output_offset.size()?output_offset[i+1]:size1()) ==
1293  offset_deps +dep(j).size1()) {
1294  // Aligned with vertcat dependency
1295  ret[i] = dep(j);
1296  }
1297  }
1298  }
1299  }
1300  return ret;
1301  }
1302 
1303  void MXNode::copy_fwd(const bvec_t* arg, bvec_t* res, casadi_int len) {
1304  if (arg!=res) {
1305  std::copy(arg, arg+len, res);
1306  }
1307  }
1308 
1309  void MXNode::copy_rev(bvec_t* arg, bvec_t* res, casadi_int len) {
1310  if (arg!=res) {
1311  for (casadi_int k=0; k<len; ++k) {
1312  *arg++ |= *res;
1313  *res++ = 0;
1314  }
1315  }
1316  }
1317 
1318  bool MXNode::is_equal(const MXNode* x, const MXNode* y, casadi_int depth) {
1319  if (x==y) {
1320  return true;
1321  } else if (depth>0) {
1322  return x->is_equal(y, depth);
1323  } else {
1324  return false;
1325  }
1326  }
1327 
1328 
1329  // Note: binary/unary operations are omitted here
1330  std::map<casadi_int, MXNode* (*)(DeserializingStream&)> MXNode::deserialize_map = {
1338  //{OP_MAP, Map::deserialize}, Map is a function
1355  // OP_SUBREF
1356  // OP_SUBASSIGN,
1375  //OP_ERFINV,
1376  //OP_PRINTME,
1377  //OP_LIFT,
1385  };
1386 
1387 
1388 } // namespace casadi
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: bspline.cpp:30
Calculate quadratic form.
Definition: bilin.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: bilin.hpp:111
Represents any binary operation that involves two matrices.
Definition: binary_mx.hpp:41
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
std::string workel(casadi_int n) const
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Convexify a symmetric matrix.
Definition: convexify.hpp:46
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: convexify.hpp:105
Matrix transpose (dense)
Definition: transpose.hpp:185
Densify.
Definition: project.hpp:167
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Matrix determinant.
Definition: determinant.hpp:43
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Diagonal concatenation of matrices.
Definition: concat.hpp:316
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:387
Diag split, x -> x0, x1, ...
Definition: split.hpp:188
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:232
Matrix dot.
Definition: dot.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: dot.hpp:117
Dump.
Definition: dump.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: dump.hpp:127
An MX atomic for an Einstein product,.
Definition: einstein.hpp:40
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: einstein.hpp:132
Finds the first nonzero element in a vector.
Definition: casadi_find.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Function object.
Definition: function.hpp:126
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 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 MatType repsum(const MatType &x, casadi_int n, casadi_int m=1)
Functions called by friend functions defined here.
static MX 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.
casadi_int getCount() const
Get the reference count.
static MX create(const MX &x, const MX &nz)
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MX create(const Sparsity &sp, const MX &x, const std::vector< casadi_int > &nz)
Definition: getnonzeros.cpp:32
static bool simplification_on_the_fly
Indicates whether simplifications should be made on the fly.
Horizontal repmat.
Definition: repmat.hpp:43
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: repmat.hpp:138
Horizontal repsum.
Definition: repmat.hpp:153
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: repmat.hpp:229
Horizontal concatenation.
Definition: concat.hpp:145
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:216
Horizontal split, x -> x0, x1, ...
Definition: split.hpp:130
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:173
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Matrix inverse.
Definition: inverse.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: inverse.hpp:82
static MX create(const MX &m, const MX &x, bool inner)
Factory: dispatch to the most specific subclass for the given operands.
Definition: kron.cpp:286
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: kron.cpp:507
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: kron.cpp:162
static MX create(const MX &a, const MX &b)
Factory: dispatch to the most specific subclass for the given operands.
Definition: kron.cpp:85
Linear solve operation with a linear solver instance.
Definition: solve.hpp:154
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: solve_impl.hpp:353
Linear solver.
Definition: linsol.hpp:144
Calculate logsumexp update.
Definition: logsumexp.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: logsumexp.hpp:101
Lows the first nonzero element in a vector.
Definition: casadi_low.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: casadi_low.hpp:109
Matrix maximum.
Definition: mmin.hpp:117
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: mmin.hpp:180
Matrix minimum.
Definition: mmin.hpp:40
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: mmin.hpp:103
Node class for MX objects.
Definition: mx_node.hpp:51
virtual MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz, bool unique=false) const
Get the nonzeros of matrix.
Definition: mx_node.cpp:661
virtual void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const
Evaluate symbolically (MX)
Definition: mx_node.cpp:351
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:536
virtual MX get_logsumexp() const
Logsumexp.
Definition: mx_node.cpp:617
virtual void reset_input() const
Reset the marker for an input expression.
Definition: mx_node.cpp:152
std::string class_name() const override
Get name of public class.
Definition: mx_node.cpp:200
virtual MX get_nzassign(const MX &y, const std::vector< casadi_int > &nz) const
Assign the nonzeros of a matrix to another matrix.
Definition: mx_node.cpp:692
virtual const std::string & name() const
Get the name.
Definition: mx_node.cpp:196
virtual casadi_int n_primitives() const
Get the number of symbolic primitives.
Definition: mx_node.cpp:144
virtual MX get_norm_2() const
Spectral norm.
Definition: mx_node.cpp:1123
~MXNode() override=0
Destructor.
Definition: mx_node.cpp:84
virtual MX get_output(casadi_int oind) const
Get an output.
Definition: mx_node.cpp:445
virtual casadi_int offset() const
Definition: mx_node.cpp:221
virtual bool is_zero() const
Check if identically zero.
Definition: mx_node.hpp:71
virtual MX get_sparsity_cast(const Sparsity &sp) const
Sparsity cast.
Definition: mx_node.cpp:513
virtual MX get_mmax() const
Max.
Definition: mx_node.cpp:1140
static bool is_equal(const MXNode *x, const MXNode *y, casadi_int depth)
Check if two nodes are equivalent up to a given depth.
Definition: mx_node.cpp:1318
virtual MX get_unary(casadi_int op, bool unique=false) const
Get a unary operation.
Definition: mx_node.cpp:782
static void copy_fwd(const bvec_t *arg, bvec_t *res, casadi_int len)
Propagate sparsities forward through a copy operation.
Definition: mx_node.cpp:1303
virtual int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const
Evaluate symbolically (SX)
Definition: mx_node.cpp:346
virtual int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate sparsity forward.
Definition: mx_node.cpp:400
virtual Matrix< casadi_int > mapping() const
Get an IM representation of a GetNonzeros or SetNonzeros node.
Definition: mx_node.cpp:997
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.
Definition: mx_node.cpp:586
virtual DM get_DM() const
Get the value (only for constant nodes)
Definition: mx_node.cpp:488
virtual void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const
Calculate reverse mode directional derivatives.
Definition: mx_node.cpp:395
virtual bool has_duplicates() const
Detect duplicate symbolic expressions.
Definition: mx_node.cpp:148
virtual void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const
Generate code for the operation.
Definition: mx_node.cpp:450
virtual casadi_int ind() const
Definition: mx_node.cpp:213
virtual MX get_solve(const MX &r, bool tr, const Linsol &linear_solver) const
Solve a system of linear equations.
Definition: mx_node.cpp:653
virtual MX get_solve_triu(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A.
Definition: mx_node.cpp:621
void can_inline(std::map< const MXNode *, casadi_int > &nodeind) const
Find out which nodes can be inlined.
Definition: mx_node.cpp:287
friend class MX
Definition: mx_node.hpp:52
MX get_find() const
Find.
Definition: mx_node.cpp:1047
virtual MX get_solve_tril_unity(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A, unity diagnal.
Definition: mx_node.cpp:645
virtual MX get_kron(const MX &b) const
Create a Kronecker-product node.
Definition: mx_node.cpp:1241
virtual Dict info() const
Definition: mx_node.cpp:522
static bool maxDepth()
Get equality checking depth.
Definition: mx_node.hpp:380
virtual MX join_primitives(std::vector< MX >::const_iterator &it) const
Join an expression along symbolic primitives.
Definition: mx_node.cpp:184
virtual MX get_dot(const MX &y) const
Inner product.
Definition: mx_node.cpp:1094
virtual MX get_repmat(casadi_int m, casadi_int n) const
Create a repeated matrix node.
Definition: mx_node.cpp:1223
virtual int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate sparsity backwards.
Definition: mx_node.cpp:422
MX get_bspline(const std::vector< double > &knots, const std::vector< casadi_int > &offset, const std::vector< double > &coeffs, const std::vector< casadi_int > &degree, casadi_int m, const std::vector< casadi_int > &lookup_mode) const
BSpline.
Definition: mx_node.cpp:1061
static void copy_rev(bvec_t *arg, bvec_t *res, casadi_int len)
Propagate sparsities backwards through a copy operation.
Definition: mx_node.cpp:1309
virtual MX get_diagcat(const std::vector< MX > &x) const
Create a diagonal concatenation node.
Definition: mx_node.cpp:1166
std::pair< casadi_int, casadi_int > size() const
Definition: mx_node.hpp:430
Sparsity sparsity_
The sparsity pattern.
Definition: mx_node.hpp:829
virtual void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const
Calculate forward mode directional derivatives.
Definition: mx_node.cpp:390
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)
Definition: mx_node.cpp:853
MXNode()
Constructor.
Definition: mx_node.cpp:79
virtual MX get_solve_tril(const MX &r, bool tr) const
Solve a system of linear equations, lower triangular A.
Definition: mx_node.cpp:629
void generate_copy(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref, casadi_int i) const
Definition: mx_node.cpp:461
casadi_int temp
Definition: mx_node.hpp:819
void check_dep() const
Check validatity of dependencies.
Definition: mx_node.cpp:255
virtual casadi_int to_int() const
Get the value (only for scalar constant nodes)
Definition: mx_node.cpp:484
static std::map< casadi_int, MXNode *(*)(DeserializingStream &)> deserialize_map
Definition: mx_node.hpp:841
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:410
casadi_int size2() const
Definition: mx_node.hpp:429
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:427
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: mx_node.cpp:548
virtual MX get_solve_triu_unity(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A, unity diagonal.
Definition: mx_node.cpp:637
virtual const Function & which_function() const
Get called function.
Definition: mx_node.cpp:333
virtual casadi_int nout() const
Number of outputs.
Definition: mx_node.hpp:402
virtual bool is_value(double val) const
Check if a certain value.
Definition: mx_node.hpp:111
virtual casadi_int which_output() const
Get function output.
Definition: mx_node.cpp:337
virtual MX get_subref(const Slice &i, const Slice &j) const
Get submatrix reference.
Definition: mx_node.cpp:774
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:392
std::vector< MX > dep_
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:824
MX get_binary(casadi_int op, const MX &y, bool unique_x=false, bool unique_y=false) const
Get a binary operation operation.
Definition: mx_node.cpp:798
MX get_dump(const std::string &base_filename, const Dict &opts) const
Dump.
Definition: mx_node.cpp:1023
virtual MX get_norm_1() const
1-norm
Definition: mx_node.cpp:1131
virtual MX get_nz_ref(const MX &nz) const
Get the nonzeros of matrix, parametrically.
Definition: mx_node.cpp:668
virtual MX get_subassign(const MX &y, const Slice &i, const Slice &j) const
Get submatrix assignment.
Definition: mx_node.cpp:778
MX get_monitor(const std::string &comment) const
Monitor.
Definition: mx_node.cpp:1015
virtual MX get_det(const Linsol &linear_solver) const
Determinant.
Definition: mx_node.cpp:1085
casadi_int n_dep() const
Number of dependencies.
Definition: mx_node.cpp:209
virtual MX get_reshape(const Sparsity &sp) const
Reshape.
Definition: mx_node.cpp:504
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:531
virtual casadi_int segment() const
Definition: mx_node.cpp:217
virtual void primitives(std::vector< MX >::iterator &it) const
Get symbolic primitives.
Definition: mx_node.cpp:156
MX get_convexify(const Dict &opts) const
Convexify.
Definition: mx_node.cpp:1081
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:225
virtual MX get_horzcat(const std::vector< MX > &x) const
Create a horizontal concatenation node.
Definition: mx_node.cpp:1145
virtual MX get_project(const Sparsity &sp, bool unique=false) const
Create set sparse.
Definition: mx_node.cpp:760
virtual casadi_int op() const =0
Get the operation.
virtual MX get_mac(const MX &y, const MX &z, const std::string &blas="reference") const
Matrix multiplication and addition.
Definition: mx_node.cpp:567
virtual MX get_transpose() const
Transpose.
Definition: mx_node.cpp:492
virtual MX get_norm_fro() const
Frobenius norm.
Definition: mx_node.cpp:1119
virtual std::vector< MX > get_diagsplit(const std::vector< casadi_int > &offset1, const std::vector< casadi_int > &offset2) const
Create a diagonal split node.
Definition: mx_node.cpp:1255
virtual std::vector< MX > get_horzsplit(const std::vector< casadi_int > &output_offset) const
Create a horizontal split node.
Definition: mx_node.cpp:1191
virtual MX get_vertcat(const std::vector< MX > &x) const
Create a vertical concatenation node (vectors only)
Definition: mx_node.cpp:1171
casadi_int size1() const
Definition: mx_node.hpp:428
virtual MX get_repsum(casadi_int m, casadi_int n) const
Create a repeated sum node.
Definition: mx_node.cpp:1232
virtual MX get_mmin() const
Min.
Definition: mx_node.cpp:1135
virtual MX get_nzadd(const MX &y, const std::vector< casadi_int > &nz) const
Add the nonzeros of a matrix to another matrix.
Definition: mx_node.cpp:704
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w) const
Evaluate numerically.
Definition: mx_node.cpp:341
virtual MX get_norm_inf() const
Infinity norm.
Definition: mx_node.cpp:1127
MX get_low(const MX &v, const Dict &options) const
Find.
Definition: mx_node.cpp:1057
virtual MX get_inv() const
Inverse.
Definition: mx_node.cpp:1089
bool sameOpAndDeps(const MXNode *node, casadi_int depth) const
Checks if two nodes have the same operation and have.
Definition: mx_node.cpp:1001
virtual std::vector< MX > get_vertsplit(const std::vector< casadi_int > &output_offset) const
Create a vertical split node (vectors only)
Definition: mx_node.cpp:1271
virtual bool __nonzero__() const
Check the truth value of this node.
Definition: mx_node.cpp:205
virtual MX get_bilin(const MX &x, const MX &y) const
Bilinear form.
Definition: mx_node.cpp:609
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:229
MX get_assert(const MX &y, const std::string &fail_message) const
Assertion.
Definition: mx_node.cpp:1011
virtual MX get_kron_contract(const MX &x, bool inner) const
Create a Kronecker-contraction node.
Definition: mx_node.cpp:1248
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.
Definition: mx_node.cpp:613
virtual bool is_output() const
Check if evaluation output.
Definition: mx_node.hpp:320
virtual void split_primitives(const MX &x, std::vector< MX >::iterator &it) const
Split up an expression along symbolic primitives.
Definition: mx_node.cpp:160
static MX to_matrix(const MX &x, const Sparsity &sp)
Convert scalar to matrix.
Definition: mx_node.hpp:489
void eval_linear_rearrange(const std::vector< std::array< MX, 3 > > &arg, std::vector< std::array< MX, 3 > > &res) const
Evaluate the MX node on a const/linear/nonlinear partition.
Definition: mx_node.cpp:371
T join_primitives_gen(typename std::vector< T >::const_iterator &it) const
Join an expression along symbolic primitives (template)
Definition: mx_node.cpp:173
void serialize(SerializingStream &s) const
Serialize an object.
Definition: mx_node.cpp:526
virtual double to_double() const
Get the value (only for scalar constant nodes)
Definition: mx_node.cpp:480
virtual void eval_linear(const std::vector< std::array< MX, 3 > > &arg, std::vector< std::array< MX, 3 > > &res) const
Evaluate the MX node on a const/linear/nonlinear partition.
Definition: mx_node.cpp:356
std::string print_compact(std::map< const MXNode *, casadi_int > &nodeind, std::vector< std::string > &intermed) const
Print compact.
Definition: mx_node.cpp:304
MX - Matrix expression.
Definition: mx.hpp:145
static MX create(MXNode *node)
Create from node.
Definition: mx.cpp:69
const Sparsity & sparsity() const
Get the sparsity pattern.
Definition: mx.cpp:615
bool is_constant() const
Check if the node is a constant.
Definition: mx.cpp:802
MXNode * get() const
Get a const pointer to the node.
Definition: mx.cpp:567
static bool is_equal(const MX &x, const MX &y, casadi_int depth=0)
Definition: mx.cpp:870
MX T() const
Transpose the matrix.
Definition: mx.cpp:1098
static std::vector< MX > createMultipleOutput(MXNode *node)
Create from node (multiple-outputs)
Definition: mx.cpp:131
static MX nan(const Sparsity &sp)
Create a constant with all nonzeros NaN.
Definition: mx.cpp:599
MX dep(casadi_int ch=0) const
Get the ch-th dependency (child node) of this node.
Definition: mx.cpp:786
bool is_zero() const
Check if the node is a constant zero (false negatives are possible)
Definition: mx.cpp:1033
casadi_int op() const
Get the operation type of the node.
Definition: mx.cpp:854
Sparse matrix class. SX and DM are specializations.
Monitor.
Definition: monitor.hpp:41
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: monitor.hpp:129
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static MX create(const MX &z, const MX &x, const MX &y, const std::string &blas="reference")
Factory: dispatch to the most specific subclass for the given operands.
1-norm
Definition: norm.hpp:191
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:254
Represents a 2-norm (spectral norm)
Definition: norm.hpp:144
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:176
Represents a Frobenius norm.
Definition: norm.hpp:66
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:129
Represents an infinity-norm operation on a MX.
Definition: norm.hpp:269
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: norm.hpp:332
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Change the sparsity of an expression.
Definition: project.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: project.cpp:154
Calculate rank1 update.
Definition: rank1.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: rank1.hpp:114
Reshape an expression.
Definition: reshape.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: reshape.hpp:192
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static MX create(const MX &y, const MX &x, const MX &nz)
Create functions.
static MX create(const MX &y, const MX &x, const std::vector< casadi_int > &nz)
Create functions.
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Class representing a Slice.
Definition: slice.hpp:48
bool is_empty() const
Check if slice is empty.
Definition: slice.cpp:111
std::vector< casadi_int > all() const
Get a vector of indices.
Definition: slice.cpp:90
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
static MatType repmat(const MatType &x, casadi_int n, casadi_int m=1)
General sparsity class.
Definition: sparsity.hpp:200
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns of the same shape (also the * operator)
Definition: sparsity.cpp:419
const std::vector< casadi_int > permutation_vector(bool invert=false) const
Recover the permutation vector p from the pattern of a permutation matrix.
Definition: sparsity.cpp:1407
std::string dim(bool with_nz=false) const
Dimensions as a string "nrow x ncol", optionally with the number of nonzeros.
Definition: sparsity.cpp:595
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
Definition: sparsity.cpp:1041
bool is_reshape(const Sparsity &y) const
Check whether y is a reshape of this pattern.
Definition: sparsity.cpp:815
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
Combine two patterns of the same shape, as the result of a binary operation.
Definition: sparsity.cpp:400
casadi_int nnz() const
Number of structural nonzeros.
Definition: sparsity.cpp:150
std::pair< casadi_int, casadi_int > size() const
Shape as a pair (number of rows, number of columns)
Definition: sparsity.cpp:154
bool is_empty(bool both=false) const
Check whether the pattern has a zero dimension.
Definition: sparsity.cpp:146
static Sparsity kron(const Sparsity &a, const Sparsity &b)
Accessed by SparsityInterface.
Definition: sparsity.cpp:1466
static Sparsity kron_contract(const Sparsity &sp_m, const Sparsity &sp_x, bool inner)
Output sparsity of casadi::KronContract.
Definition: sparsity.cpp:1510
bool is_dense() const
Check whether every entry is a structural nonzero, i.e. nnz() == numel()
Definition: sparsity.cpp:275
Reference to a submatrix.
Definition: subassign.hpp:41
Reference to a submatrix.
Definition: subref.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Matrix transpose.
Definition: transpose.hpp:42
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: transpose.cpp:46
Linear solve with an upper triangular matrix.
Definition: solve.hpp:393
Linear solve with an upper triangular matrix.
Definition: solve.hpp:269
Linear solve with an upper triangular matrix, unity diagonal.
Definition: solve.hpp:352
Linear solve with an upper triangular matrix.
Definition: solve.hpp:228
Represents a general unary operation on an MX.
Definition: unary_mx.hpp:39
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: unary_mx.hpp:148
Vertical concatenation of vectors.
Definition: concat.hpp:230
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: concat.hpp:301
Vertical split of vectors, x -> x0, x1, ...
Definition: split.hpp:247
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: split.hpp:290
The casadi namespace.
Definition: archiver.cpp:28
double if_else_zero(double x, double y)
Conditional assignment.
Definition: calculus.hpp:295
unsigned long long bvec_t
bool is_range(const std::vector< casadi_int > &v, casadi_int start, casadi_int stop, casadi_int step)
Check if a vector matches a range.
Definition: casadi_misc.cpp:95
std::vector< casadi_int > find(const std::vector< T > &v)
find nonzeros
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T common_simp_binary(casadi_int op, const T &x, const T &y, casadi_int depth, SU &&gen_unary, SB &&gen_binary, bool unique_x, bool unique_y, bool &hit)
Definition: calculus.hpp:1891
T common_simp_unary(casadi_int op, const T &x, casadi_int depth, SU &&gen_unary, bool unique, bool &hit)
Definition: calculus.hpp:1827
Operation
Enum for quick access to any node.
Definition: calculus.hpp:60
@ OP_DIAGCAT
Definition: calculus.hpp:130
@ OP_NE
Definition: calculus.hpp:70
@ OP_HORZCAT
Definition: calculus.hpp:124
@ OP_VERTCAT
Definition: calculus.hpp:127
@ OP_SPARSITY_CAST
Definition: calculus.hpp:200
@ OP_LOW
Definition: calculus.hpp:94
@ OP_HORZREPSUM
Definition: calculus.hpp:187
@ OP_ADDNONZEROS_PARAM
Definition: calculus.hpp:160
@ OP_IF_ELSE_ZERO
Definition: calculus.hpp:71
@ OP_MMAX
Definition: calculus.hpp:181
@ OP_KRON_CONTRACT
Definition: calculus.hpp:216
@ OP_BSPLINE
Definition: calculus.hpp:195
@ OP_KRON
Definition: calculus.hpp:214
@ OP_DIAGSPLIT
Definition: calculus.hpp:139
@ OP_INV
Definition: calculus.hpp:73
@ OP_INVERSE
Definition: calculus.hpp:112
@ OP_OUTPUT
Definition: calculus.hpp:82
@ OP_MMIN
Definition: calculus.hpp:181
@ OP_SETNONZEROS
Definition: calculus.hpp:163
@ OP_FIND
Definition: calculus.hpp:91
@ OP_VERTSPLIT
Definition: calculus.hpp:136
@ OP_LT
Definition: calculus.hpp:70
@ OP_EQ
Definition: calculus.hpp:70
@ OP_CONST
Definition: calculus.hpp:79
@ OP_TWICE
Definition: calculus.hpp:67
@ OP_EINSTEIN
Definition: calculus.hpp:193
@ OP_INPUT
Definition: calculus.hpp:82
@ OP_SUB
Definition: calculus.hpp:65
@ OP_DETERMINANT
Definition: calculus.hpp:109
@ OP_DUMP
Definition: calculus.hpp:212
@ OP_DOT
Definition: calculus.hpp:115
@ OP_POW
Definition: calculus.hpp:66
@ OP_PROJECT
Definition: calculus.hpp:169
@ OP_ADDNONZEROS
Definition: calculus.hpp:157
@ OP_PARAMETER
Definition: calculus.hpp:85
@ OP_SETNONZEROS_PARAM
Definition: calculus.hpp:166
@ OP_BILIN
Definition: calculus.hpp:118
@ OP_MTIMES
Definition: calculus.hpp:100
@ OP_CONVEXIFY
Definition: calculus.hpp:197
@ OP_LOGSUMEXP
Definition: calculus.hpp:208
@ OP_NORM1
Definition: calculus.hpp:178
@ OP_CALL
Definition: calculus.hpp:88
@ OP_ADD
Definition: calculus.hpp:65
@ OP_NORM2
Definition: calculus.hpp:178
@ OP_LE
Definition: calculus.hpp:70
@ OP_RESHAPE
Definition: calculus.hpp:142
@ OP_DIV
Definition: calculus.hpp:65
@ OP_TRANSPOSE
Definition: calculus.hpp:106
@ OP_SOLVE
Definition: calculus.hpp:103
@ OP_ASSERTION
Definition: calculus.hpp:172
@ OP_NEG
Definition: calculus.hpp:66
@ OP_RANK1
Definition: calculus.hpp:121
@ OP_CONSTPOW
Definition: calculus.hpp:66
@ OP_MUL
Definition: calculus.hpp:65
@ OP_HORZREPMAT
Definition: calculus.hpp:184
@ OP_HORZSPLIT
Definition: calculus.hpp:133
@ OP_GETNONZEROS_PARAM
Definition: calculus.hpp:154
@ OP_SQ
Definition: calculus.hpp:67
@ OP_NORMF
Definition: calculus.hpp:178
@ OP_MONITOR
Definition: calculus.hpp:175
@ OP_GETNONZEROS
Definition: calculus.hpp:151
@ OP_NORMINF
Definition: calculus.hpp:178
Easy access to all the functions for a particular type.
Definition: calculus.hpp:1149
static void fun(unsigned char op, const T &x, const T &y, T &f)
Evaluate a built in function (scalar-scalar)
Definition: calculus.hpp:1313