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_dev(ret.is_empty(true));
179  return T(size());
180  }
181  }
182 
183  MX MXNode::join_primitives(std::vector<MX>::const_iterator& it) const {
184  return join_primitives_gen<MX>(it);
185  }
186 
187  DM MXNode::join_primitives(std::vector<DM>::const_iterator& it) const {
188  return join_primitives_gen<DM>(it);
189  }
190 
191  SX MXNode::join_primitives(std::vector<SX>::const_iterator& it) const {
192  return join_primitives_gen<SX>(it);
193  }
194 
195  const std::string& MXNode::name() const {
196  casadi_error("'name' not defined for class " + class_name());
197  }
198 
199  std::string MXNode::class_name() const {
200  // Lazy solution
201  return typeid(*this).name();
202  }
203 
204  bool MXNode::__nonzero__() const {
205  casadi_error("Can only determine truth value of a numeric MX.");
206  }
207 
208  casadi_int MXNode::n_dep() const {
209  return dep_.size();
210  }
211 
212  casadi_int MXNode::ind() const {
213  casadi_error("'ind' not defined for class " + class_name());
214  }
215 
216  casadi_int MXNode::segment() const {
217  casadi_error("'segment' not defined for class " + class_name());
218  }
219 
220  casadi_int MXNode::offset() const {
221  casadi_error("'offset' not defined for class " + class_name());
222  }
223 
224  void MXNode::set_sparsity(const Sparsity& sparsity) {
226  }
227 
228  void MXNode::set_dep(const MX& dep) {
229  dep_.resize(1);
230  dep_[0] = dep;
231  check_dep();
232  }
233 
234  void MXNode::set_dep(const MX& dep1, const MX& dep2) {
235  dep_.resize(2);
236  dep_[0] = dep1;
237  dep_[1] = dep2;
238  check_dep();
239  }
240 
241  void MXNode::set_dep(const MX& dep1, const MX& dep2, const MX& dep3) {
242  dep_.resize(3);
243  dep_[0] = dep1;
244  dep_[1] = dep2;
245  dep_[2] = dep3;
246  check_dep();
247  }
248 
249  void MXNode::set_dep(const std::vector<MX>& dep) {
250  dep_ = dep;
251  check_dep();
252  }
253 
254  void MXNode::check_dep() const {
255  for (const MX& e : dep_) {
256  if (e->has_output()) {
257  casadi_assert(is_output(),
258  "You cannot build an expression out of a MultipleOutput node. "
259  "You must select a concrete output by making a get_output() call.");
260  }
261  }
262  }
263 
264  const Sparsity& MXNode::sparsity(casadi_int oind) const {
265  casadi_assert(oind==0, "Index out of bounds");
266  return sparsity_;
267  }
268 
269  void MXNode::disp(std::ostream& stream, bool more) const {
270  // Find out which noded can be inlined
271  std::map<const MXNode*, casadi_int> nodeind;
272  can_inline(nodeind);
273 
274  // Print expression
275  std::vector<std::string> intermed;
276  std::string s = print_compact(nodeind, intermed);
277 
278  // Print intermediate expressions
279  for (casadi_int i=0; i<intermed.size(); ++i)
280  stream << "@" << (i+1) << "=" << intermed[i] << ", ";
281 
282  // Print this
283  stream << s;
284  }
285 
286  void MXNode::can_inline(std::map<const MXNode*, casadi_int>& nodeind) const {
287  // Add or mark node in map
288  std::map<const MXNode*, casadi_int>::iterator it=nodeind.find(this);
289  if (it==nodeind.end()) {
290  // First time encountered, mark inlined
291  nodeind.insert(it, std::make_pair(this, 0));
292 
293  // Handle dependencies with recursion
294  for (casadi_int i=0; i<n_dep(); ++i) {
295  dep(i)->can_inline(nodeind);
296  }
297  } else if (it->second==0 && op()!=OP_PARAMETER) {
298  // Node encountered before, do not inline (except if symbolic primitive)
299  it->second = -1;
300  }
301  }
302 
303  std::string MXNode::print_compact(std::map<const MXNode*, casadi_int>& nodeind,
304  std::vector<std::string>& intermed) const {
305  // Get reference to node index
306  casadi_int& ind = nodeind[this];
307 
308  // If positive, already in intermediate expressions
309  if (ind>0) return "@" + str(ind);
310 
311  // Get expressions for dependencies
312  std::vector<std::string> arg(n_dep());
313  for (casadi_int i=0; i<arg.size(); ++i) {
314  arg[i] = dep(i)->print_compact(nodeind, intermed);
315  }
316 
317  // Get expression for this
318  std::string s = disp(arg);
319 
320  // Decide what to do with the expression
321  if (ind==0) {
322  // Inline expression
323  return s;
324  } else {
325  // Add to list of intermediate expressions and return reference
326  intermed.push_back(s);
327  ind = intermed.size(); // For subsequent references
328  return "@" + str(ind);
329  }
330  }
331 
333  casadi_error("'which_function' not defined for class " + class_name());
334  }
335 
336  casadi_int MXNode::which_output() const {
337  casadi_error("'which_output' not defined for class " + class_name());
338  }
339 
340  int MXNode::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
341  casadi_error("'eval' not defined for class " + class_name());
342  return 1;
343  }
344 
345  int MXNode::eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
346  casadi_error("'eval_sx' not defined for class " + class_name());
347  return 1;
348  }
349 
350  void MXNode::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
351  const std::vector<bool>& unique) const {
352  casadi_error("'eval_mx' not defined for class " + class_name());
353  }
354 
355  void MXNode::eval_linear(const std::vector<std::array<MX, 3> >& arg,
356  std::vector<std::array<MX, 3> >& res) const {
357  std::vector<MX> arg_sum(arg.size());
358  for (casadi_int i=0; i<arg.size(); ++i) {
359  arg_sum[i] = arg[i][0] + arg[i][1] + arg[i][2];
360  }
361  std::vector<MX> res_nonlin(res.size());
362  eval_mx(arg_sum, res_nonlin);
363  for (casadi_int i=0; i<res.size(); ++i) {
364  res[i][0] = MX::zeros(sparsity());
365  res[i][1] = MX::zeros(sparsity());
366  res[i][2] = res_nonlin[i];
367  }
368  }
369 
370  void MXNode::eval_linear_rearrange(const std::vector<std::array<MX, 3> >& arg,
371  std::vector<std::array<MX, 3> >& res) const {
372  // Treat each category separately
373  for (casadi_int i=0; i<3; ++i) {
374  // Read arguments for categiry i
375  std::vector<MX> eval_arg(n_dep());
376  for (casadi_int j=0; j<n_dep(); ++j) {
377  eval_arg[j] = arg[j][i];
378  }
379  std::vector<MX> eval_res(nout());
380  // Normal symbolic evaluation
381  eval_mx(eval_arg, eval_res);
382  // Assign results
383  for (casadi_int j=0; j<nout(); ++j) {
384  res[j][i] = eval_res[j];
385  }
386  }
387  }
388 
389  void MXNode::ad_forward(const std::vector<std::vector<MX> >& fseed,
390  std::vector<std::vector<MX> >& fsens) const {
391  casadi_error("'ad_forward' not defined for class " + class_name());
392  }
393 
394  void MXNode::ad_reverse(const std::vector<std::vector<MX> >& aseed,
395  std::vector<std::vector<MX> >& asens) const {
396  casadi_error("'ad_reverse' not defined for class " + class_name());
397  }
398 
399  int MXNode::sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
400  // By default, everything depends on everything
401  bvec_t all_depend(0);
402 
403  // Get dependencies of all inputs
404  for (casadi_int k=0; k<n_dep(); ++k) {
405  const bvec_t* v = arg[k];
406  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
407  all_depend |= v[i];
408  }
409  }
410 
411  // Propagate to all outputs
412  for (casadi_int k=0; k<nout(); ++k) {
413  bvec_t* v = res[k];
414  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
415  v[i] = all_depend;
416  }
417  }
418  return 0;
419  }
420 
421  int MXNode::sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
422  // By default, everything depends on everything
423  bvec_t all_depend(0);
424 
425  // Get dependencies of all outputs
426  for (casadi_int k=0; k<nout(); ++k) {
427  bvec_t* v = res[k];
428  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) {
429  all_depend |= v[i];
430  v[i] = 0;
431  }
432  }
433 
434  // Propagate to all inputs
435  for (casadi_int k=0; k<n_dep(); ++k) {
436  bvec_t* v = arg[k];
437  for (casadi_int i=0; i<dep(k).nnz(); ++i) {
438  v[i] |= all_depend;
439  }
440  }
441  return 0;
442  }
443 
444  MX MXNode::get_output(casadi_int oind) const {
445  casadi_assert(oind==0, "Output index out of bounds");
446  return shared_from_this<MX>();
447  }
448 
450  const std::vector<casadi_int>& arg,
451  const std::vector<casadi_int>& res,
452  const std::vector<bool>& arg_is_ref,
453  std::vector<bool>& res_is_ref) const {
454  casadi_warning("Cannot code generate MX nodes of type " + class_name() +
455  "The generation will proceed, but compilation of the code will "
456  "not be possible.");
457  g << "#error " << class_name() << ": " << arg << " => " << res << '\n';
458  }
459 
461  const std::vector<casadi_int>& arg,
462  const std::vector<casadi_int>& res,
463  const std::vector<bool>& arg_is_ref,
464  std::vector<bool>& res_is_ref,
465  casadi_int i) const {
466  res_is_ref[i] = arg_is_ref[i];
467  if (arg[i]==res[i]) return;
468  if (nnz()==1) {
469  g << g.workel(res[i]) << " = " << g.workel(arg[i]) << ";\n";
470  } else if (arg_is_ref[i]) {
471  g << g.work(res[i], nnz(), true) << " = " << g.work(arg[i], nnz(), true) << ";\n";
472  } else {
473  g << g.copy(g.work(arg[i], nnz(), false), nnz(), g.work(res[i], nnz(), false)) << "\n";
474  }
475  }
476 
477 
478 
479  double MXNode::to_double() const {
480  casadi_error("'to_double' not defined for class " + class_name());
481  }
482 
483  casadi_int MXNode::to_int() const {
484  casadi_error("'to_int' not defined for class " + class_name());
485  }
486 
487  DM MXNode::get_DM() const {
488  casadi_error("'get_DM' not defined for class " + class_name());
489  }
490 
492  if (sparsity().is_scalar()) {
493  return shared_from_this<MX>();
494  } else if (sparsity().is_vector()) {
495  return get_reshape(sparsity().T());
496  } else if (sparsity().is_dense()) {
497  return MX::create(new DenseTranspose(shared_from_this<MX>()));
498  } else {
499  return MX::create(new Transpose(shared_from_this<MX>()));
500  }
501  }
502 
503  MX MXNode::get_reshape(const Sparsity& sp) const {
504  casadi_assert_dev(sp.is_reshape(sparsity()));
505  if (sp==sparsity()) {
506  return shared_from_this<MX>();
507  } else {
508  return MX::create(new Reshape(shared_from_this<MX>(), sp));
509  }
510  }
511 
513  casadi_assert_dev(sp.nnz()==nnz());
514  if (sp==sparsity()) {
515  return shared_from_this<MX>();
516  } else {
517  return MX::create(new SparsityCast(shared_from_this<MX>(), sp));
518  }
519  }
520 
521  Dict MXNode::info() const {
522  return Dict();
523  }
524 
526  serialize_type(s);
527  serialize_body(s);
528  }
529 
531  s.pack("MXNode::deps", dep_);
532  s.pack("MXNode::sp", sparsity_);
533  }
534 
536  s.pack("MXNode::op", static_cast<int>(op()));
537  }
538 
540  temp = 0;
541 
542  s.unpack("MXNode::deps", dep_);
543  s.unpack("MXNode::sp", sparsity_);
544  }
545 
546 
548  int op;
549  s.unpack("MXNode::op", op);
550 
553  } else if (casadi_math<MX>::is_unary(op)) {
554  return UnaryMX::deserialize(s);
555  }
556 
557  auto it = MXNode::deserialize_map.find(op);
558  if (it==MXNode::deserialize_map.end()) {
559  casadi_error("Not implemented op " + str(casadi_int(op)) + ":" + str(OP_GETNONZEROS));
560  } else {
561  return it->second(s);
562  }
563  }
564 
565 
566  MX MXNode::get_mac(const MX& y, const MX& z, const std::string& blas) const {
567  if (sparsity().is_orthonormal() && y.is_column() && y.is_dense()
568  && y.sparsity()==z.sparsity() && z.is_zero()) {
569  std::vector<casadi_int> perm = sparsity().permutation_vector();
570  MX nz = sparsity_cast(shared_from_this<MX>(), Sparsity::dense(nnz()));
571  return (nz*y)(perm);
572  }
573  // Get reference to transposed first argument
574  MX x = shared_from_this<MX>();
575 
576  casadi_assert(y.size2()==z.size2(),
577  "Dimension error x.mac(z). Got y=" + str(y.size2()) + " and z=" + z.dim() + ".");
578  casadi_assert(x.size1()==z.size1(),
579  "Dimension error x.mac(z). Got x=" + x.dim() + " and z=" + z.dim() + ".");
580  casadi_assert(y.size1()==x.size2(),
581  "Dimension error x.mac(z). Got y=" + str(y.size1()) + " and x" + x.dim() + ".");
582  return Multiplication::create(z, x, y, blas);
583  }
584 
585  MX MXNode::get_einstein(const MX& A, const MX& B,
586  const std::vector<casadi_int>& dim_c, const std::vector<casadi_int>& dim_a,
587  const std::vector<casadi_int>& dim_b,
588  const std::vector<casadi_int>& c, const std::vector<casadi_int>& a,
589  const std::vector<casadi_int>& b) const {
590 
591  if (A.is_zero() || B.is_zero())
592  return shared_from_this<MX>();
593 
594  MX C = densify(shared_from_this<MX>());
595 
596  if (A.is_constant() && B.is_constant() && C.is_constant()) {
597  // Constant folding
598  DM Ac = A->get_DM();
599  DM Bc = B->get_DM();
600  DM Cc = C->get_DM();
601  return einstein(vec(densify(Ac)), vec(densify(Bc)), vec(densify(Cc)),
602  dim_a, dim_b, dim_c, a, b, c);
603  }
604 
605  return MX::create(new Einstein(C, densify(A), densify(B), dim_c, dim_a, dim_b, c, a, b));
606  }
607 
608  MX MXNode::get_bilin(const MX& x, const MX& y) const {
609  return MX::create(new Bilin(shared_from_this<MX>(), x, y));
610  }
611 
612  MX MXNode::get_rank1(const MX& alpha, const MX& x, const MX& y) const {
613  return MX::create(new Rank1(shared_from_this<MX>(), alpha, x, y));
614  }
615 
617  return MX::create(new LogSumExp(shared_from_this<MX>()));
618  }
619 
620  MX MXNode::get_solve_triu(const MX& r, bool tr) const {
621  if (tr) {
622  return MX::create(new TriuSolve<true>(densify(r), shared_from_this<MX>()));
623  } else {
624  return MX::create(new TriuSolve<false>(densify(r), shared_from_this<MX>()));
625  }
626  }
627 
628  MX MXNode::get_solve_tril(const MX& r, bool tr) const {
629  if (tr) {
630  return MX::create(new TrilSolve<true>(densify(r), shared_from_this<MX>()));
631  } else {
632  return MX::create(new TrilSolve<false>(densify(r), shared_from_this<MX>()));
633  }
634  }
635 
636  MX MXNode::get_solve_triu_unity(const MX& r, bool tr) const {
637  if (tr) {
638  return MX::create(new TriuSolveUnity<true>(densify(r), shared_from_this<MX>()));
639  } else {
640  return MX::create(new TriuSolveUnity<false>(densify(r), shared_from_this<MX>()));
641  }
642  }
643 
644  MX MXNode::get_solve_tril_unity(const MX& r, bool tr) const {
645  if (tr) {
646  return MX::create(new TrilSolveUnity<true>(densify(r), shared_from_this<MX>()));
647  } else {
648  return MX::create(new TrilSolveUnity<false>(densify(r), shared_from_this<MX>()));
649  }
650  }
651 
652  MX MXNode::get_solve(const MX& r, bool tr, const Linsol& linear_solver) const {
653  if (tr) {
654  return MX::create(new LinsolCall<true>(densify(r), shared_from_this<MX>(), linear_solver));
655  } else {
656  return MX::create(new LinsolCall<false>(densify(r), shared_from_this<MX>(), linear_solver));
657  }
658  }
659 
660  MX MXNode::get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz, bool unique) const {
661  if (sparsity().is_dense() && is_range(nz, 0, nnz())) {
662  return sparsity_cast(shared_from_this<MX>(), sp);
663  }
664  return GetNonzeros::create(sp, shared_from_this<MX>(), nz);
665  }
666 
667  MX MXNode::get_nz_ref(const MX& nz) const {
668  return GetNonzerosParam::create(shared_from_this<MX>(), nz);
669  }
670 
671  MX MXNode::get_nz_ref(const MX& inner, const Slice& outer) const {
672  if (outer.all()==std::vector<casadi_int>{0}) {
673  return get_nz_ref(inner);
674  } else {
675  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
676  }
677  }
678 
679  MX MXNode::get_nz_ref(const Slice& inner, const MX& outer) const {
680  if (inner.all()==std::vector<casadi_int>{0}) {
681  return get_nz_ref(outer);
682  } else {
683  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
684  }
685  }
686 
687  MX MXNode::get_nz_ref(const MX& inner, const MX& outer) const {
688  return GetNonzerosParam::create(shared_from_this<MX>(), inner, outer);
689  }
690 
691  MX MXNode::get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const {
692  // Check if any element needs to be set at all
693  bool set_any = false;
694  for (auto i=nz.begin(); i!=nz.end() && !set_any; ++i) {
695  set_any = *i >= 0;
696  }
697  if (!set_any) return y;
698 
699  return SetNonzeros<false>::create(y, shared_from_this<MX>(), nz);
700  }
701 
702 
703  MX MXNode::get_nzadd(const MX& y, const std::vector<casadi_int>& nz) const {
704  if (nz.empty() || is_zero()) {
705  return y;
706  } else {
707  return SetNonzeros<true>::create(y, shared_from_this<MX>(), nz);
708  }
709  }
710 
711  MX MXNode::get_nzassign(const MX& y, const MX& nz) const {
712  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), nz);
713  }
714 
715  MX MXNode::get_nzassign(const MX& y, const MX& inner, const Slice& outer) const {
716  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
717  }
718 
719  MX MXNode::get_nzassign(const MX& y, const Slice& inner, const MX& outer) const {
720  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
721  }
722 
723  MX MXNode::get_nzassign(const MX& y, const MX& inner, const MX& outer) const {
724  return SetNonzerosParam<false>::create(y, shared_from_this<MX>(), inner, outer);
725  }
726 
727  MX MXNode::get_nzadd(const MX& y, const MX& nz) const {
728  if (nz.is_empty() || is_zero()) {
729  return y;
730  } else {
731  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), nz);
732  }
733  }
734 
735  MX MXNode::get_nzadd(const MX& y, const MX& inner, const Slice& outer) const {
736  if (inner.is_empty() || outer.is_empty() || is_zero()) {
737  return y;
738  } else {
739  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
740  }
741  }
742 
743  MX MXNode::get_nzadd(const MX& y, const Slice& inner, const MX& outer) const {
744  if (outer.is_empty() || outer.is_empty() || is_zero()) {
745  return y;
746  } else {
747  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
748  }
749  }
750 
751  MX MXNode::get_nzadd(const MX& y, const MX& inner, const MX& outer) const {
752  if (inner.is_empty() || outer.is_empty() || is_zero()) {
753  return y;
754  } else {
755  return SetNonzerosParam<true>::create(y, shared_from_this<MX>(), inner, outer);
756  }
757  }
758 
759  MX MXNode::get_project(const Sparsity& sp, bool unique) const {
760  if (sp==sparsity()) {
761  return shared_from_this<MX>();
762  } else if (sp.nnz()==0) {
763  return MX::zeros(sp);
764  } else if (sp.is_dense()) {
765  return MX::create(new Densify(shared_from_this<MX>(), sp));
766  } else if (sparsity().is_dense()) {
767  return MX::create(new Sparsify(shared_from_this<MX>(), sp));
768  } else {
769  return MX::create(new Project(shared_from_this<MX>(), sp));
770  }
771  }
772 
773  MX MXNode::get_subref(const Slice& i, const Slice& j) const {
774  return MX::create(new SubRef(shared_from_this<MX>(), i, j));
775  }
776 
777  MX MXNode::get_subassign(const MX& y, const Slice& i, const Slice& j) const {
778  return MX::create(new SubAssign(shared_from_this<MX>(), y, i, j));
779  }
780 
781  MX MXNode::get_unary(casadi_int op, bool unique) const {
782  if (operation_checker<F0XChecker>(op) && is_zero()) {
783  // If identically zero
784  return MX::zeros(sparsity());
785  } else {
786  bool hit;
787  MX ret = common_simp_unary(op, shared_from_this<MX>(), maxDepth(),
788  [](casadi_int op, const MX& a) { return a->get_unary(op);},
789  unique,
790  hit);
791  if (hit) return ret;
792  // Create a new node
793  return MX::create(new UnaryMX(Operation(op), shared_from_this<MX>()));
794  }
795  }
796 
797  MX MXNode::get_binary(casadi_int op, const MX& y, bool unique_x, bool unique_y) const {
798  // If-else-zero nodes are always simplified at top level to avoid NaN propagation
799  if (y.op() == OP_IF_ELSE_ZERO) {
800  if (op == OP_MUL) {
801  // (Rule 1.) x * if_else_zero(c, y), simplified to if_else_zero(c, x * y)
802  // Background: x is often a partial derivative and may evaluate to INF or NAN.
803  // The simplification ensures that the zero seed corresponding to an inactive branch does
804  // not give rise to any NaN contribution to the derivative due to NaN * 0 == NaN.
805  return if_else_zero(y.dep(0), shared_from_this<MX>() * y.dep(1));
806  } else if (op == OP_ADD && this->op() == OP_IF_ELSE_ZERO && MX::is_equal(dep(0), y.dep(0))) {
807  // (Rule 2.) if_else_zero(c, x) + if_else_zero(c, y) is simplified to if_else_zero(c, x + y)
808  // Background: During the backward propagation, seeds are added together. Without this rule,
809  // the addition node can prevent rule (1.) from working in subsequent steps.
810  return if_else_zero(y.dep(0), dep(1) + y.dep(1));
811  }
812  } else if (this->op() == OP_IF_ELSE_ZERO && op == OP_MUL) {
813  // Same as Rule 1. above, but with factors swapped. For symmetry.
814  return if_else_zero(dep(0), dep(1) * y);
815  }
816  // Create binary node
817  if (sparsity().is_scalar(false)) {
818  if (nnz()==0) {
819  if (operation_checker<F0XChecker>(op)) return MX::zeros(Sparsity(y.size()));
820  return to_matrix(MX(0)->_get_binary(op, y, true, false, unique_x, unique_y), y.sparsity());
821  } else {
822  return to_matrix(_get_binary(op, y, true, false, unique_x, unique_y), y.sparsity());
823  }
824  } else if (y.is_scalar()) {
825  if (y.nnz()==0) {
826  if (operation_checker<FX0Checker>(op)) return MX::zeros(Sparsity(size()));
827  return to_matrix(_get_binary(op, MX(0), false, true, unique_x, unique_y), sparsity());
828  } else {
829  return to_matrix(_get_binary(op, y, false, true, unique_x, unique_y), sparsity());
830  }
831  } else {
832  casadi_assert(sparsity().size() == y.sparsity().size(), "Dimension mismatch.");
833  if (sparsity()==y.sparsity()) {
834  // Matching sparsities
835  return _get_binary(op, y, false, false, unique_x, unique_y);
836  } else {
837  // Get the sparsity pattern of the result
838  // (ignoring structural zeros giving rise to nonzero result)
839  const Sparsity& x_sp = sparsity();
840  const Sparsity& y_sp = y.sparsity();
841  Sparsity r_sp = x_sp.combine(y_sp, operation_checker<F0XChecker>(op),
842  operation_checker<FX0Checker>(op));
843 
844  // Project the arguments to this sparsity
845  MX xx = project(shared_from_this<MX>(), r_sp);
846  MX yy = project(y, r_sp);
847  return xx->_get_binary(op, yy, false, false, unique_x, unique_y);
848  }
849  }
850  }
851 
852  MX MXNode::_get_binary(casadi_int op, const MX& y, bool scX, bool scY,
853  bool unique_x, bool unique_y) const {
854  casadi_assert_dev(sparsity()==y.sparsity() || scX || scY);
855 
857 
858  // If identically zero due to one argument being zero
859  if ((operation_checker<F0XChecker>(op) && nnz()==0) ||
860  (operation_checker<FX0Checker>(op) && y->nnz()==0)) {
861  return MX::zeros(Sparsity(size()));
862  }
863 
864  if ((operation_checker<F0XChecker>(op) && is_zero()) ||
865  (operation_checker<FX0Checker>(op) && y->is_zero())) {
866  return MX::zeros(sparsity());
867  }
868 
869  if (sparsity().is_scalar(true) && y.is_scalar(true)) {
870  bool hit;
871  MX ret = common_simp_binary(op, shared_from_this<MX>(), y, maxDepth(),
872  [](casadi_int op, const MX& a) { return a->get_unary(op);},
873  [](casadi_int op, const MX& a, const MX& b) {
874  return a->_get_binary(op, b, true, true);
875  },
876  unique_x,
877  unique_y,
878  hit);
879  if (hit) return ret;
880  }
881 
882  // Handle special operations (independent of type)
883  switch (op) {
884  case OP_ADD:
885  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_TWICE);
886  break;
887  case OP_SUB:
888  case OP_NE:
889  case OP_LT:
890  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::zeros(sparsity());
891  break;
892  case OP_DIV:
893  if (y->is_zero()) return MX::nan(sparsity());
894  // fall-through
895  case OP_EQ:
896  case OP_LE:
897  if (MXNode::is_equal(y.get(), this, maxDepth())) return MX::ones(sparsity());
898  break;
899  case OP_MUL:
900  if (MXNode::is_equal(y.get(), this, maxDepth())) return get_unary(OP_SQ);
901  break;
902  default: break; // no rule
903  }
904 
905  // Handle special cases for the second argument
906  switch (y->op()) {
907  case OP_CONST:
908  // Make the constant the first argument, if possible
909  if (this->op()!=OP_CONST && operation_checker<CommChecker>(op)) {
910  return y->_get_binary(op, shared_from_this<MX>(), scY, scX);
911  } else {
912  switch (op) {
913  case OP_POW:
914  return _get_binary(OP_CONSTPOW, y, scX, scY);
915  case OP_CONSTPOW:
916  if (y->is_value(-1)) return get_unary(OP_INV);
917  else if (y->is_value(0)) return MX::ones(size());
918  else if (y->is_value(1)) return shared_from_this<MX>();
919  else if (y->is_value(2)) return get_unary(OP_SQ);
920  break;
921  case OP_ADD:
922  case OP_SUB:
923  if (y->is_zero())
924  return scX ? repmat(shared_from_this<MX>(), y.size()) : shared_from_this<MX>();
925  break;
926  case OP_MUL:
927  if (y->is_value(1)) return shared_from_this<MX>();
928  break;
929  case OP_DIV:
930  if (y->is_value(1)) return shared_from_this<MX>();
931  else if (y->is_value(0.5)) return get_unary(OP_TWICE);
932  break;
933  default: break; // no rule
934  }
935  }
936  break;
937  case OP_NEG:
938  if (op==OP_ADD) {
939  return _get_binary(OP_SUB, y->dep(), scX, scY);
940  } else if (op==OP_SUB) {
941  return _get_binary(OP_ADD, y->dep(), scX, scY);
942  } else if (op==OP_MUL) {
943  return -_get_binary(OP_MUL, y->dep(), scX, scY);
944  } else if (op==OP_DIV) {
945  return -_get_binary(OP_DIV, y->dep(), scX, scY);
946  }
947  break;
948  case OP_INV:
949  if (op==OP_MUL) {
950  return _get_binary(OP_DIV, y->dep(), scX, scY);
951  } else if (op==OP_DIV) {
952  return _get_binary(OP_MUL, y->dep(), scX, scY);
953  }
954  break;
955  default: break; // no rule
956  }
957 
958  }
959 
960  if (scX) {
961  // Check if it is ok to loop over nonzeros only
962  if (y.is_dense() || operation_checker<FX0Checker>(op) ||
963  (is_zero() && operation_checker<F00Checker>(op))) {
964  // Loop over nonzeros
965  return MX::create(new BinaryMX<true, false>(Operation(op), shared_from_this<MX>(), y));
966  } else {
967  // Put a densification node in between
968  return _get_binary(op, densify(y), true, false);
969  }
970  } else if (scY) {
971  // Check if it is ok to loop over nonzeros only
972  if (sparsity().is_dense() || operation_checker<F0XChecker>(op) ||
973  (y.is_zero() && operation_checker<F00Checker>(op)) ||
974  (y.is_constant() && static_cast<double>(y)>0 && (op==OP_CONSTPOW || op==OP_POW))) {
975  // Loop over nonzeros
976  return MX::create(new BinaryMX<false, true>(Operation(op), shared_from_this<MX>(), y));
977  } else {
978  // Put a densification node in between
979  return densify(shared_from_this<MX>())->_get_binary(op, y, false, true);
980  }
981  } else {
982  // Loop over nonzeros only
983  MX rr = MX::create(new BinaryMX<false, false>(Operation(op), shared_from_this<MX>(), y));
984 
985  // Handle structural zeros giving rise to nonzero result, e.g. cos(0) == 1
986  if (!rr.is_dense() && !operation_checker<F00Checker>(op)) {
987  // Get the value for the structural zeros
988  double fcn_0(0);
989  casadi_math<double>::fun(op, 0, 0, fcn_0);
990  rr = densify(rr, fcn_0);
991  }
992  return rr;
993  }
994  }
995 
997  casadi_error("'mapping' not defined for class " + class_name());
998  }
999 
1000  bool MXNode::sameOpAndDeps(const MXNode* node, casadi_int depth) const {
1001  if (op()!=node->op() || n_dep()!=node->n_dep())
1002  return false;
1003  for (casadi_int i=0; i<n_dep(); ++i) {
1004  if (!MX::is_equal(dep(i), node->dep(i), depth-1))
1005  return false;
1006  }
1007  return true;
1008  }
1009 
1010  MX MXNode::get_assert(const MX& y, const std::string& fail_message) const {
1011  return MX::create(new Assertion(shared_from_this<MX>(), y, fail_message));
1012  }
1013 
1014  MX MXNode::get_monitor(const std::string& comment) const {
1015  if (nnz()==0) {
1016  return shared_from_this<MX>();
1017  } else {
1018  return MX::create(new Monitor(shared_from_this<MX>(), comment));
1019  }
1020  }
1021 
1022  MX MXNode::get_dump(const std::string& base_filename, const Dict& opts) const {
1023  if (nnz()==0) {
1024  return shared_from_this<MX>();
1025  } else {
1026  std::string dir = ".";
1027  std::string format = "mtx";
1028  bool verbose = false;
1029  for (auto&& op : opts) {
1030  if (op.first=="dir") {
1031  dir = op.second.to_string();
1032  } else if (op.first=="format") {
1033  format = op.second.to_string();
1034  } else if (op.first=="verbose") {
1035  verbose = op.second.to_bool();
1036  } else {
1037  casadi_error("Unknown option '" + op.first + "' for dump. "
1038  "Allowed options: 'dir', 'format', 'verbose'.");
1039  }
1040  }
1041  return MX::create(new Dump(shared_from_this<MX>(), base_filename,
1042  dir, format, verbose));
1043  }
1044  }
1045 
1047  MX x = shared_from_this<MX>();
1048  casadi_assert(x.is_vector(), "Argument must be vector, got " + x.dim() + ".");
1049  if (x.is_column()) {
1050  return MX::create(new Find(shared_from_this<MX>()));
1051  } else {
1052  return find(x.T());
1053  }
1054  }
1055 
1056  MX MXNode::get_low(const MX& v, const Dict& options) const {
1057  return MX::create(new Low(v, shared_from_this<MX>(), options));
1058  }
1059 
1060  MX MXNode::get_bspline(const std::vector<double>& knots,
1061  const std::vector<casadi_int>& offset,
1062  const std::vector<double>& coeffs,
1063  const std::vector<casadi_int>& degree,
1064  casadi_int m,
1065  const std::vector<casadi_int>& lookup_mode) const {
1066  MX x = shared_from_this<MX>();
1067  return MX::create(new BSpline(x, knots, offset, coeffs, degree, m, lookup_mode));
1068  }
1069 
1070  MX MXNode::get_bspline(const MX& coeffs,
1071  const std::vector<double>& knots,
1072  const std::vector<casadi_int>& offset,
1073  const std::vector<casadi_int>& degree,
1074  casadi_int m,
1075  const std::vector<casadi_int>& lookup_mode) const {
1076  MX x = shared_from_this<MX>();
1077  return MX::create(new BSplineParametric(x, coeffs, knots, offset, degree, m, lookup_mode));
1078  }
1079 
1080  MX MXNode::get_convexify(const Dict& opts) const {
1081  return MX::create(new Convexify(shared_from_this<MX>(), opts));
1082  }
1083 
1084  MX MXNode::get_det(const Linsol& linear_solver) const {
1085  return MX::create(new Determinant(shared_from_this<MX>(), linear_solver));
1086  }
1087 
1089  return MX::create(new Inverse(shared_from_this<MX>()));
1090  }
1091 
1092 
1093  MX MXNode::get_dot(const MX& y) const {
1094  casadi_assert(
1095  size2()==y.size2() && size1()==y.size1(),
1096  "MXNode::dot: Dimension mismatch. dot requires its "
1097  "two arguments to have equal shapes, but got ("
1098  + str(size2()) + ", " + str(size1()) + ") and ("
1099  + str(y.size2()) + ", " + str(y.size1()) + ").");
1100  if (sparsity()==y.sparsity()) {
1101  if (sparsity().nnz()==0) {
1102  return 0;
1103  } else if (sparsity().is_scalar()) {
1104  return get_binary(OP_MUL, y);
1105  } else {
1106  if (shared_from_this<MX>().is_zero() || y.is_zero()) return 0;
1107  return MX::create(new Dot(shared_from_this<MX>(), y));
1108  }
1109  } else {
1110  // Project to pattern intersection
1111  Sparsity sp = sparsity().intersect(y.sparsity());
1112  MX xx = project(shared_from_this<MX>(), sp);
1113  MX yy = project(y, sp);
1114  return xx->get_dot(yy);
1115  }
1116  }
1117 
1119  return MX::create(new NormF(shared_from_this<MX>()));
1120  }
1121 
1123  return MX::create(new Norm2(shared_from_this<MX>()));
1124  }
1125 
1127  return MX::create(new NormInf(shared_from_this<MX>()));
1128  }
1129 
1131  return MX::create(new Norm1(shared_from_this<MX>()));
1132  }
1133 
1135  if (sparsity_.is_empty()) return MX();
1136  return MX::create(new MMin(shared_from_this<MX>()));
1137  }
1138 
1140  if (sparsity_.is_empty()) return MX();
1141  return MX::create(new MMax(shared_from_this<MX>()));
1142  }
1143 
1144  MX MXNode::get_horzcat(const std::vector<MX>& x) const {
1145  // Check if there is any existing horzcat operation
1146  for (auto i=x.begin(); i!=x.end(); ++i) {
1147  if (i->op()==OP_HORZCAT) {
1148  // Split up
1149  std::vector<MX> x_split(x.begin(), i);
1150  for (; i!=x.end(); ++i) {
1151  if (i->op()==OP_HORZCAT) {
1152  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1153  } else {
1154  x_split.push_back(*i);
1155  }
1156  }
1157  return horzcat(x_split);
1158  }
1159  }
1160 
1161  // Create a Horzcat node
1162  return MX::create(new Horzcat(x));
1163  }
1164 
1165  MX MXNode::get_diagcat(const std::vector<MX>& x) const {
1166  // Create a Horzcat node
1167  return MX::create(new Diagcat(x));
1168  }
1169 
1170  MX MXNode::get_vertcat(const std::vector<MX>& x) const {
1171  // Check if there is any existing vertcat operation
1172  for (auto i=x.begin(); i!=x.end(); ++i) {
1173  if (i->op()==OP_VERTCAT) {
1174  // Split up
1175  std::vector<MX> x_split(x.begin(), i);
1176  for (; i!=x.end(); ++i) {
1177  if (i->op()==OP_VERTCAT) {
1178  x_split.insert(x_split.end(), (*i)->dep_.begin(), (*i)->dep_.end());
1179  } else {
1180  x_split.push_back(*i);
1181  }
1182  }
1183  return vertcat(x_split);
1184  }
1185  }
1186 
1187  return MX::create(new Vertcat(x));
1188  }
1189 
1190  std::vector<MX> MXNode::get_horzsplit(const std::vector<casadi_int>& output_offset) const {
1191  if (is_zero()) {
1192  std::vector<MX> ret =
1193  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1194  for (casadi_int i=0;i<ret.size();++i) {
1195  ret[i]=MX::zeros(ret[i].sparsity());
1196  }
1197  return ret;
1198  }
1199  std::vector<MX> ret =
1200  MX::createMultipleOutput(new Horzsplit(shared_from_this<MX>(), output_offset));
1201 
1203  // Simplify horzsplit(horzcat)
1204  if (op()==OP_HORZCAT) {
1205  casadi_int offset_deps = 0;
1206  casadi_int j = 0;
1207  for (casadi_int i=0;i<output_offset.size();++i) {
1208  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size2();++j; }
1209  if (j>=n_dep()) j = n_dep()-1;
1210  if (output_offset[i]==offset_deps &&
1211  (i+1<output_offset.size()?output_offset[i+1]:size2()) ==
1212  offset_deps +dep(j).size2()) {
1213  // Aligned with vertcat dependency
1214  ret[i] = dep(j);
1215  }
1216  }
1217  }
1218  }
1219  return ret;
1220  }
1221 
1222  MX MXNode::get_repmat(casadi_int n, casadi_int m) const {
1223  if (n==1) {
1224  return MX::create(new HorzRepmat(shared_from_this<MX>(), m));
1225  } else {
1226  // Fallback to generic_matrix impl
1227  return GenericMatrix<MX>::repmat(shared_from_this<MX>(), n, m);
1228  }
1229  }
1230 
1231  MX MXNode::get_repsum(casadi_int n, casadi_int m) const {
1232  if (n==1) {
1233  return MX::create(new HorzRepsum(shared_from_this<MX>(), m));
1234  } else {
1235  // Fallback to generic_matrix impl
1236  return GenericMatrix<MX>::repsum(shared_from_this<MX>(), n, m);
1237  }
1238  }
1239 
1240  MX MXNode::get_kron(const MX& b) const {
1241  if (nnz() == 0 || b.nnz() == 0) {
1242  return MX::zeros(Sparsity::kron(sparsity(), b.sparsity()));
1243  }
1244  return Kron::create(shared_from_this<MX>(), b);
1245  }
1246 
1247  MX MXNode::get_kron_contract(const MX& x, bool inner) const {
1248  if (nnz() == 0 || x.nnz() == 0) {
1249  return MX::zeros(Sparsity::kron_contract(sparsity(), x.sparsity(), inner));
1250  }
1251  return KronContract::create(shared_from_this<MX>(), x, inner);
1252  }
1253 
1254  std::vector<MX> MXNode::get_diagsplit(const std::vector<casadi_int>& offset1,
1255  const std::vector<casadi_int>& offset2) const {
1256  if (is_zero()) {
1257  std::vector<MX> ret =
1258  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1259  for (casadi_int i=0;i<ret.size();++i) {
1260  ret[i]=MX::zeros(ret[i].sparsity());
1261  }
1262  return ret;
1263  }
1264  std::vector<MX> ret =
1265  MX::createMultipleOutput(new Diagsplit(shared_from_this<MX>(), offset1, offset2));
1266 
1267  return ret;
1268  }
1269 
1270  std::vector<MX> MXNode::get_vertsplit(const std::vector<casadi_int>& output_offset) const {
1271  if (is_zero()) {
1272  std::vector<MX> ret =
1273  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1274  for (casadi_int i=0;i<ret.size();++i) {
1275  ret[i]=MX::zeros(ret[i].sparsity());
1276  }
1277  return ret;
1278  }
1279  std::vector<MX> ret =
1280  MX::createMultipleOutput(new Vertsplit(shared_from_this<MX>(), output_offset));
1281 
1283  // Simplify vertsplit(vertcat)
1284  if (op()==OP_VERTCAT) {
1285  casadi_int offset_deps = 0;
1286  casadi_int j = 0;
1287  for (casadi_int i=0;i<output_offset.size();++i) {
1288  while (offset_deps<output_offset[i]) { offset_deps+=dep(j).size1();++j; }
1289  if (j>=n_dep()) j = n_dep()-1;
1290  if (output_offset[i]==offset_deps &&
1291  (i+1<output_offset.size()?output_offset[i+1]:size1()) ==
1292  offset_deps +dep(j).size1()) {
1293  // Aligned with vertcat dependency
1294  ret[i] = dep(j);
1295  }
1296  }
1297  }
1298  }
1299  return ret;
1300  }
1301 
1302  void MXNode::copy_fwd(const bvec_t* arg, bvec_t* res, casadi_int len) {
1303  if (arg!=res) {
1304  std::copy(arg, arg+len, res);
1305  }
1306  }
1307 
1308  void MXNode::copy_rev(bvec_t* arg, bvec_t* res, casadi_int len) {
1309  if (arg!=res) {
1310  for (casadi_int k=0; k<len; ++k) {
1311  *arg++ |= *res;
1312  *res++ = 0;
1313  }
1314  }
1315  }
1316 
1317  bool MXNode::is_equal(const MXNode* x, const MXNode* y, casadi_int depth) {
1318  if (x==y) {
1319  return true;
1320  } else if (depth>0) {
1321  return x->is_equal(y, depth);
1322  } else {
1323  return false;
1324  }
1325  }
1326 
1327 
1328  // Note: binary/unary operations are omitted here
1329  std::map<casadi_int, MXNode* (*)(DeserializingStream&)> MXNode::deserialize_map = {
1337  //{OP_MAP, Map::deserialize}, Map is a function
1354  // OP_SUBREF
1355  // OP_SUBASSIGN,
1374  //OP_ERFINV,
1375  //OP_PRINTME,
1376  //OP_LIFT,
1384  };
1385 
1386 
1387 } // 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:60
bool is_dense() const
Check if the matrix expression is dense.
bool is_column() const
Check if the matrix is a column vector (i.e. size2()==1)
bool is_empty(bool both=false) const
Check if the sparsity is empty, i.e. if one of the dimensions is zero.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
bool is_vector() const
Check if the matrix is a row or column vector.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
casadi_int 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 expression is scalar.
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:134
Horizontal repsum.
Definition: repmat.hpp:149
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
Definition: repmat.hpp:225
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:55
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:660
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:350
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:535
virtual MX get_logsumexp() const
Logsumexp.
Definition: mx_node.cpp:616
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:199
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:691
virtual const std::string & name() const
Get the name.
Definition: mx_node.cpp:195
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:1122
~MXNode() override=0
Destructor.
Definition: mx_node.cpp:84
virtual MX get_output(casadi_int oind) const
Get an output.
Definition: mx_node.cpp:444
virtual casadi_int offset() const
Definition: mx_node.cpp:220
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:512
virtual MX get_mmax() const
Max.
Definition: mx_node.cpp:1139
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:1317
virtual MX get_unary(casadi_int op, bool unique=false) const
Get a unary operation.
Definition: mx_node.cpp:781
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:1302
virtual int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const
Evaluate symbolically (SX)
Definition: mx_node.cpp:345
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:399
virtual Matrix< casadi_int > mapping() const
Get an IM representation of a GetNonzeros or SetNonzeros node.
Definition: mx_node.cpp:996
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:585
virtual DM get_DM() const
Get the value (only for constant nodes)
Definition: mx_node.cpp:487
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:394
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:449
virtual casadi_int ind() const
Definition: mx_node.cpp:212
virtual MX get_solve(const MX &r, bool tr, const Linsol &linear_solver) const
Solve a system of linear equations.
Definition: mx_node.cpp:652
virtual MX get_solve_triu(const MX &r, bool tr) const
Solve a system of linear equations, upper triangular A.
Definition: mx_node.cpp:620
void can_inline(std::map< const MXNode *, casadi_int > &nodeind) const
Find out which nodes can be inlined.
Definition: mx_node.cpp:286
friend class MX
Definition: mx_node.hpp:52
MX get_find() const
Find.
Definition: mx_node.cpp:1046
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:644
virtual MX get_kron(const MX &b) const
Create a Kronecker-product node.
Definition: mx_node.cpp:1240
virtual Dict info() const
Definition: mx_node.cpp:521
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:183
virtual MX get_dot(const MX &y) const
Inner product.
Definition: mx_node.cpp:1093
virtual MX get_repmat(casadi_int m, casadi_int n) const
Create a repeated matrix node.
Definition: mx_node.cpp:1222
virtual int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate sparsity backwards.
Definition: mx_node.cpp:421
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:1060
static void copy_rev(bvec_t *arg, bvec_t *res, casadi_int len)
Propagate sparsities backwards through a copy operation.
Definition: mx_node.cpp:1308
virtual MX get_diagcat(const std::vector< MX > &x) const
Create a diagonal concatenation node.
Definition: mx_node.cpp:1165
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:389
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:852
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:628
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:460
casadi_int temp
Definition: mx_node.hpp:819
void check_dep() const
Check validatity of dependencies.
Definition: mx_node.cpp:254
virtual casadi_int to_int() const
Get the value (only for scalar constant nodes)
Definition: mx_node.cpp:483
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:547
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:636
virtual const Function & which_function() const
Get called function.
Definition: mx_node.cpp:332
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:336
virtual MX get_subref(const Slice &i, const Slice &j) const
Get submatrix reference.
Definition: mx_node.cpp:773
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:797
MX get_dump(const std::string &base_filename, const Dict &opts) const
Dump.
Definition: mx_node.cpp:1022
virtual MX get_norm_1() const
1-norm
Definition: mx_node.cpp:1130
virtual MX get_nz_ref(const MX &nz) const
Get the nonzeros of matrix, parametrically.
Definition: mx_node.cpp:667
virtual MX get_subassign(const MX &y, const Slice &i, const Slice &j) const
Get submatrix assignment.
Definition: mx_node.cpp:777
MX get_monitor(const std::string &comment) const
Monitor.
Definition: mx_node.cpp:1014
virtual MX get_det(const Linsol &linear_solver) const
Determinant.
Definition: mx_node.cpp:1084
casadi_int n_dep() const
Number of dependencies.
Definition: mx_node.cpp:208
virtual MX get_reshape(const Sparsity &sp) const
Reshape.
Definition: mx_node.cpp:503
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:530
virtual casadi_int segment() const
Definition: mx_node.cpp:216
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:1080
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:224
virtual MX get_horzcat(const std::vector< MX > &x) const
Create a horizontal concatenation node.
Definition: mx_node.cpp:1144
virtual MX get_project(const Sparsity &sp, bool unique=false) const
Create set sparse.
Definition: mx_node.cpp:759
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:566
virtual MX get_transpose() const
Transpose.
Definition: mx_node.cpp:491
virtual MX get_norm_fro() const
Frobenius norm.
Definition: mx_node.cpp:1118
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:1254
virtual std::vector< MX > get_horzsplit(const std::vector< casadi_int > &output_offset) const
Create a horizontal split node.
Definition: mx_node.cpp:1190
virtual MX get_vertcat(const std::vector< MX > &x) const
Create a vertical concatenation node (vectors only)
Definition: mx_node.cpp:1170
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:1231
virtual MX get_mmin() const
Min.
Definition: mx_node.cpp:1134
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:703
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w) const
Evaluate numerically.
Definition: mx_node.cpp:340
virtual MX get_norm_inf() const
Infinity norm.
Definition: mx_node.cpp:1126
MX get_low(const MX &v, const Dict &options) const
Find.
Definition: mx_node.cpp:1056
virtual MX get_inv() const
Inverse.
Definition: mx_node.cpp:1088
bool sameOpAndDeps(const MXNode *node, casadi_int depth) const
Checks if two nodes have the same operation and have.
Definition: mx_node.cpp:1000
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:1270
virtual bool __nonzero__() const
Check the truth value of this node.
Definition: mx_node.cpp:204
virtual MX get_bilin(const MX &x, const MX &y) const
Bilinear form.
Definition: mx_node.cpp:608
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:228
MX get_assert(const MX &y, const std::string &fail_message) const
Assertion.
Definition: mx_node.cpp:1010
virtual MX get_kron_contract(const MX &x, bool inner) const
Create a Kronecker-contraction node.
Definition: mx_node.cpp:1247
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:612
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:370
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:525
virtual double to_double() const
Get the value (only for scalar constant nodes)
Definition: mx_node.cpp:479
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:355
std::string print_compact(std::map< const MXNode *, casadi_int > &nodeind, std::vector< std::string > &intermed) const
Print compact.
Definition: mx_node.cpp:303
MX - Matrix expression.
Definition: mx.hpp:92
static MX create(MXNode *node)
Create from node.
Definition: mx.cpp:69
const Sparsity & sparsity() const
Get the sparsity pattern.
Definition: mx.cpp:612
bool is_constant() const
Check if constant.
Definition: mx.cpp:799
MXNode * get() const
Get a const pointer to the node.
Definition: mx.cpp:564
static bool is_equal(const MX &x, const MX &y, casadi_int depth=0)
Definition: mx.cpp:867
MX T() const
Transpose the matrix.
Definition: mx.cpp:1095
static std::vector< MX > createMultipleOutput(MXNode *node)
Create from node (multiple-outputs)
Definition: mx.cpp:130
static MX nan(const Sparsity &sp)
create a matrix with all nan
Definition: mx.cpp:596
MX dep(casadi_int ch=0) const
Get the nth dependency as MX.
Definition: mx.cpp:783
bool is_zero() const
check if zero (note that false negative answers are possible)
Definition: mx.cpp:1030
casadi_int op() const
Get operation type.
Definition: mx.cpp:851
Sparse matrix class. SX and DM are specializations.
Definition: matrix_decl.hpp:99
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:106
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns.
Definition: sparsity.cpp:417
const std::vector< casadi_int > permutation_vector(bool invert=false) const
Construct permutation vector from permutation matrix.
Definition: sparsity.cpp:1391
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Definition: sparsity.cpp:1028
bool is_reshape(const Sparsity &y) const
Check if the sparsity is a reshape of another.
Definition: sparsity.cpp:802
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
Combine two sparsity patterns.
Definition: sparsity.cpp:398
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
std::pair< casadi_int, casadi_int > size() const
Get the shape.
Definition: sparsity.cpp:152
bool is_empty(bool both=false) const
Check if the sparsity is empty.
Definition: sparsity.cpp:144
static Sparsity kron(const Sparsity &a, const Sparsity &b)
Enlarge matrix.
Definition: sparsity.cpp:1450
static Sparsity kron_contract(const Sparsity &sp_m, const Sparsity &sp_x, bool inner)
Output sparsity of casadi::KronContract.
Definition: sparsity.cpp:1494
bool is_dense() const
Is dense?
Definition: sparsity.cpp:273
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:1871
T common_simp_unary(casadi_int op, const T &x, casadi_int depth, SU &&gen_unary, bool unique, bool &hit)
Definition: calculus.hpp:1813
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:1135
static void fun(unsigned char op, const T &x, const T &y, T &f)
Evaluate a built in function (scalar-scalar)
Definition: calculus.hpp:1299