mx_node.hpp
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 #ifndef CASADI_MX_NODE_HPP
27 #define CASADI_MX_NODE_HPP
28 
29 #include "mx.hpp"
30 #include "shared_object.hpp"
31 #include "sx_elem.hpp"
32 #include "calculus.hpp"
33 #include "code_generator.hpp"
34 #include "linsol.hpp"
35 #include <vector>
36 #include <stack>
37 #include <array>
38 
39 namespace casadi {
40 
41  class SerializingStream;
42  class DeserializingStream;
43 
51  class CASADI_EXPORT MXNode : public SharedObjectInternal {
52  friend class MX;
53 
54  public:
56  MXNode();
57 
61  ~MXNode() override=0;
62 
66  virtual bool __nonzero__() const;
67 
71  virtual bool is_zero() const { return false;}
72 
76  virtual bool is_one() const { return false;}
77 
81  virtual bool is_minus_one() const { return false;}
82 
86  virtual bool is_half() const { return false;}
87 
91  virtual bool is_inf() const { return false;}
92 
96  virtual bool is_minus_inf() const { return false;}
97 
101  virtual bool is_integer() const { return false;}
102 
106  virtual bool is_nonnegative() const { return false;}
107 
111  virtual bool is_value(double val) const { return false;}
112 
116  virtual bool is_eye() const { return false;}
117 
121  virtual bool is_unary() const { return false;}
122 
126  virtual bool is_binary() const { return false;}
127 
131  void can_inline(std::map<const MXNode*, casadi_int>& nodeind) const;
132 
136  std::string print_compact(std::map<const MXNode*, casadi_int>& nodeind,
137  std::vector<std::string>& intermed) const;
138 
142  virtual std::string disp(const std::vector<std::string>& arg) const = 0;
143 
147  virtual void add_dependency(CodeGenerator& g) const {}
148 
152  virtual bool has_refcount() const { return false;}
153 
157  virtual void codegen_incref(CodeGenerator& g, std::set<void*>& added) const {}
158 
162  virtual void codegen_decref(CodeGenerator& g, std::set<void*>& added) const {}
163 
167  virtual void generate(CodeGenerator& g,
168  const std::vector<casadi_int>& arg,
169  const std::vector<casadi_int>& res,
170  const std::vector<bool>& arg_is_ref,
171  std::vector<bool>& res_is_ref) const;
172 
173  void generate_copy(CodeGenerator& g,
174  const std::vector<casadi_int>& arg,
175  const std::vector<casadi_int>& res,
176  const std::vector<bool>& arg_is_ref,
177  std::vector<bool>& res_is_ref,
178  casadi_int i) const;
179 
183  virtual int eval(const double** arg, double** res, casadi_int* iw, double* w) const;
184 
188  virtual int eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const;
189 
193  virtual void eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
194  const std::vector<bool>& unique={}) const;
195 
199  virtual void eval_linear(const std::vector<std::array<MX, 3> >& arg,
200  std::vector<std::array<MX, 3> >& res) const;
201 
205  void eval_linear_unary(const std::vector<std::array<MX, 3> >& arg,
206  std::vector<std::array<MX, 3> >& res) const;
207 
214  void eval_linear_rearrange(const std::vector<std::array<MX, 3> >& arg,
215  std::vector<std::array<MX, 3> >& res) const;
216 
220  virtual void ad_forward(const std::vector<std::vector<MX> >& fseed,
221  std::vector<std::vector<MX> >& fsens) const;
222 
226  virtual void ad_reverse(const std::vector<std::vector<MX> >& aseed,
227  std::vector<std::vector<MX> >& asens) const;
228 
232  virtual int sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const;
233 
237  virtual int eval_activity(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
238  for (casadi_int k=0; k<nout(); ++k) {
239  bvec_t* v = res[k];
240  if (!v) continue;
241  for (casadi_int i=0; i<sparsity(k).nnz(); ++i) v[i] = ~static_cast<bvec_t>(0);
242  }
243  return 0;
244  }
245 
249  virtual int sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const;
250 
254  virtual const std::string& name() const;
255 
259  std::string class_name() const override;
260 
264  void disp(std::ostream& stream, bool more) const override;
265 
269  virtual bool is_valid_input() const { return false;}
270 
274  virtual casadi_int n_primitives() const;
275 
279  virtual void primitives(std::vector<MX>::iterator& it) const;
280 
282 
285  virtual void split_primitives(const MX& x, std::vector<MX>::iterator& it) const;
286  virtual void split_primitives(const SX& x, std::vector<SX>::iterator& it) const;
287  virtual void split_primitives(const DM& x, std::vector<DM>::iterator& it) const;
289 
291  template<typename T>
292  T join_primitives_gen(typename std::vector<T>::const_iterator& it) const;
293 
295 
298  virtual MX join_primitives(std::vector<MX>::const_iterator& it) const;
299  virtual SX join_primitives(std::vector<SX>::const_iterator& it) const;
300  virtual DM join_primitives(std::vector<DM>::const_iterator& it) const;
302 
308  virtual bool has_duplicates() const;
309 
315  virtual void reset_input() const;
316 
320  virtual bool is_output() const {return false;}
321 
325  virtual bool has_output() const {return false;}
326 
330  virtual casadi_int which_output() const;
331 
335  virtual const Function& which_function() const;
336 
340  virtual casadi_int op() const = 0;
341 
343  virtual Dict info() const;
344 
348  void serialize(SerializingStream& s) const;
349 
353  virtual void serialize_body(SerializingStream& s) const;
354 
361  virtual void serialize_type(SerializingStream& s) const;
362 
369  static MXNode* deserialize(DeserializingStream& s);
370 
374  static bool is_equal(const MXNode* x, const MXNode* y, casadi_int depth);
375  virtual bool is_equal(const MXNode* node, casadi_int depth) const { return false;}
376 
380  inline static bool maxDepth() { return MX::get_max_depth();}
381 
387  bool sameOpAndDeps(const MXNode* node, casadi_int depth) const;
388 
392  const MX& dep(casadi_int ind=0) const { return dep_.at(ind);}
393 
397  casadi_int n_dep() const;
398 
402  virtual casadi_int nout() const { return 1;}
403 
407  virtual MX get_output(casadi_int oind) const;
408 
410  const Sparsity& sparsity() const { return sparsity_;}
411 
413  virtual const Sparsity& sparsity(casadi_int oind) const;
414 
415  template<class T>
416  bool matches_sparsity(const std::vector<T>& arg) const {
417  for (casadi_int i=0;i<dep_.size();++i) {
418  if (dep_[i].sparsity()!=arg[i].sparsity()) {
419  return false;
420  }
421  }
422  return true;
423  }
424 
426  casadi_int numel() const { return sparsity().numel(); }
427  casadi_int nnz(casadi_int i=0) const { return sparsity(i).nnz(); }
428  casadi_int size1() const { return sparsity().size1(); }
429  casadi_int size2() const { return sparsity().size2(); }
430  std::pair<casadi_int, casadi_int> size() const { return sparsity().size();}
431 
432  // Get IO index
433  virtual casadi_int ind() const;
434 
435  // Get IO segment
436  virtual casadi_int segment() const;
437 
438  // Get IO offset
439  virtual casadi_int offset() const;
440 
442  void set_sparsity(const Sparsity& sparsity);
443 
447  virtual size_t sz_arg() const { return n_dep();}
448 
452  virtual size_t sz_res() const { return nout();}
453 
457  virtual size_t sz_iw() const { return 0;}
458 
462  virtual size_t sz_w() const { return 0;}
463 
471  virtual size_t codegen_sz_w() const { return sz_w();}
472 
474  void set_dep(const MX& dep);
475 
477  void set_dep(const MX& dep1, const MX& dep2);
478 
480  void set_dep(const MX& dep1, const MX& dep2, const MX& dep3);
481 
483  void set_dep(const std::vector<MX>& dep);
484 
486  void check_dep() const;
487 
489  inline static MX to_matrix(const MX& x, const Sparsity& sp) {
490  if (x.size()==sp.size()) {
491  return x;
492  } else {
493  return MX(sp, x);
494  }
495  }
496 
498  virtual double to_double() const;
499 
501  virtual casadi_int to_int() const;
502 
504  virtual DM get_DM() const;
505 
507  virtual casadi_int n_inplace() const { return 0;}
508 
510  virtual Matrix<casadi_int> mapping() const;
511 
513  virtual MX get_horzcat(const std::vector<MX>& x) const;
514 
516  virtual std::vector<MX> get_horzsplit(const std::vector<casadi_int>& output_offset) const;
517 
519  virtual MX get_repmat(casadi_int m, casadi_int n) const;
520 
522  virtual MX get_repsum(casadi_int m, casadi_int n) const;
523 
525  virtual MX get_kron(const MX& b) const;
526 
528  virtual MX get_kron_contract(const MX& x, bool inner) const;
529 
531  virtual MX get_vertcat(const std::vector<MX>& x) const;
532 
534  virtual std::vector<MX> get_vertsplit(const std::vector<casadi_int>& output_offset) const;
535 
537  virtual MX get_diagcat(const std::vector<MX>& x) const;
538 
540  virtual std::vector<MX> get_diagsplit(const std::vector<casadi_int>& offset1,
541  const std::vector<casadi_int>& offset2) const;
542 
544  virtual MX get_transpose() const;
545 
547  virtual MX get_reshape(const Sparsity& sp) const;
548 
550  virtual MX get_sparsity_cast(const Sparsity& sp) const;
551 
555  virtual MX get_mac(const MX& y, const MX& z,
556  const std::string& blas = "reference") const;
557 
561  virtual MX get_einstein(const MX& A, const MX& B,
562  const std::vector<casadi_int>& dim_c, const std::vector<casadi_int>& dim_a,
563  const std::vector<casadi_int>& dim_b,
564  const std::vector<casadi_int>& c, const std::vector<casadi_int>& a,
565  const std::vector<casadi_int>& b) const;
566 
570  virtual MX get_bilin(const MX& x, const MX& y) const;
571 
575  virtual MX get_rank1(const MX& alpha, const MX& x, const MX& y) const;
576 
580  virtual MX get_logsumexp() const;
581 
589  virtual MX get_solve(const MX& r, bool tr, const Linsol& linear_solver) const;
590 
598  virtual MX get_solve_triu(const MX& r, bool tr) const;
599 
607  virtual MX get_solve_tril(const MX& r, bool tr) const;
608 
616  virtual MX get_solve_triu_unity(const MX& r, bool tr) const;
617 
625  virtual MX get_solve_tril_unity(const MX& r, bool tr) const;
626 
634  virtual MX get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz,
635  bool unique=false) const;
636 
640  virtual MX get_nz_ref(const MX& nz) const;
641 
645  virtual MX get_nz_ref(const MX& inner, const Slice& outer) const;
646 
650  virtual MX get_nz_ref(const Slice& inner, const MX& outer) const;
651 
655  virtual MX get_nz_ref(const MX& inner, const MX& outer) const;
656 
663  virtual MX get_nzassign(const MX& y, const std::vector<casadi_int>& nz) const;
664 
671  virtual MX get_nzadd(const MX& y, const std::vector<casadi_int>& nz) const;
672 
679  virtual MX get_nzassign(const MX& y, const MX& nz) const;
680 
687  virtual MX get_nzassign(const MX& y, const MX& inner, const Slice& outer) const;
688 
695  virtual MX get_nzassign(const MX& y, const Slice& inner, const MX& outer) const;
696 
703  virtual MX get_nzassign(const MX& y, const MX& inner, const MX& outer) const;
704 
711  virtual MX get_nzadd(const MX& y, const MX& nz) const;
712 
719  virtual MX get_nzadd(const MX& y, const MX& inner, const Slice& outer) const;
720 
727  virtual MX get_nzadd(const MX& y, const Slice& inner, const MX& outer) const;
728 
735  virtual MX get_nzadd(const MX& y, const MX& inner, const MX& outer) const;
736 
738  virtual MX get_subref(const Slice& i, const Slice& j) const;
739 
741  virtual MX get_subassign(const MX& y, const Slice& i, const Slice& j) const;
742 
744  virtual MX get_project(const Sparsity& sp, bool unique=false) const;
745 
747  virtual MX get_unary(casadi_int op, bool unique=false) const;
748 
750  MX get_binary(casadi_int op, const MX& y, bool unique_x=false, bool unique_y=false) const;
751 
753  virtual MX _get_binary(casadi_int op, const MX& y, bool scX, bool scY,
754  bool unique_x=false, bool unique_y=false) const;
755 
757  virtual MX get_det(const Linsol& linear_solver) const;
758 
760  virtual MX get_inv() const;
761 
763  virtual MX get_dot(const MX& y) const;
764 
766  virtual MX get_norm_fro() const;
767 
769  virtual MX get_norm_2() const;
770 
772  virtual MX get_norm_inf() const;
773 
775  virtual MX get_norm_1() const;
776 
778  virtual MX get_mmin() const;
779 
781  virtual MX get_mmax() const;
782 
784  MX get_assert(const MX& y, const std::string& fail_message) const;
785 
787  MX get_monitor(const std::string& comment) const;
788 
790  MX get_dump(const std::string& base_filename, const Dict& opts) const;
791 
793  MX get_find() const;
794 
796  MX get_low(const MX& v, const Dict& options) const;
797 
799  MX get_bspline(const std::vector<double>& knots,
800  const std::vector<casadi_int>& offset,
801  const std::vector<double>& coeffs,
802  const std::vector<casadi_int>& degree,
803  casadi_int m,
804  const std::vector<casadi_int>& lookup_mode) const;
806  MX get_bspline(const MX& coeffs, const std::vector<double>& knots,
807  const std::vector<casadi_int>& offset,
808  const std::vector<casadi_int>& degree,
809  casadi_int m,
810  const std::vector<casadi_int>& lookup_mode) const;
811 
813  MX get_convexify(const Dict& opts) const;
814 
819  mutable casadi_int temp;
820 
824  std::vector<MX> dep_;
825 
830 
834  static void copy_fwd(const bvec_t* arg, bvec_t* res, casadi_int len);
835 
839  static void copy_rev(bvec_t* arg, bvec_t* res, casadi_int len);
840 
841  static std::map<casadi_int, MXNode* (*)(DeserializingStream&)> deserialize_map;
842 
843  protected:
847  explicit MXNode(DeserializingStream& s);
848  };
849 
851 } // namespace casadi
852 
853 #endif // CASADI_MX_NODE_HPP
Helper class for C code generation.
Helper class for Serialization.
Function object.
Definition: function.hpp:60
std::pair< casadi_int, casadi_int > size() const
Get the shape.
Linear solver.
Definition: linsol.hpp:55
Node class for MX objects.
Definition: mx_node.hpp:51
virtual bool has_output() const
Check if a multiple output node.
Definition: mx_node.hpp:325
void eval_linear_unary(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.
virtual bool is_zero() const
Check if identically zero.
Definition: mx_node.hpp:71
virtual size_t sz_arg() const
Get required length of arg field.
Definition: mx_node.hpp:447
virtual int eval_activity(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const
Propagate signal activity forward (bit set = active)
Definition: mx_node.hpp:237
virtual size_t codegen_sz_w() const
Length of w the node's GENERATED code needs (may exceed sz_w)
Definition: mx_node.hpp:471
virtual bool is_valid_input() const
Check if valid function input.
Definition: mx_node.hpp:269
static bool maxDepth()
Get equality checking depth.
Definition: mx_node.hpp:380
virtual bool is_minus_inf() const
Check if identically -inf.
Definition: mx_node.hpp:96
virtual size_t sz_w() const
Get required length of w field.
Definition: mx_node.hpp:462
virtual bool is_one() const
Check if identically one.
Definition: mx_node.hpp:76
virtual bool is_binary() const
Check if binary operation.
Definition: mx_node.hpp:126
virtual void add_dependency(CodeGenerator &g) const
Add a dependent function.
Definition: mx_node.hpp:147
virtual casadi_int n_inplace() const
Can the operation be performed inplace (i.e. overwrite the result)
Definition: mx_node.hpp:507
std::pair< casadi_int, casadi_int > size() const
Definition: mx_node.hpp:430
Sparsity sparsity_
The sparsity pattern.
Definition: mx_node.hpp:829
casadi_int temp
Definition: mx_node.hpp:819
casadi_int numel() const
Get shape.
Definition: mx_node.hpp:426
static std::map< casadi_int, MXNode *(*)(DeserializingStream &)> deserialize_map
Definition: mx_node.hpp:841
virtual bool is_nonnegative() const
Check if not negative.
Definition: mx_node.hpp:106
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:410
virtual size_t sz_res() const
Get required length of res field.
Definition: mx_node.hpp:452
casadi_int size2() const
Definition: mx_node.hpp:429
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:427
bool matches_sparsity(const std::vector< T > &arg) const
Definition: mx_node.hpp:416
virtual void codegen_incref(CodeGenerator &g, std::set< void * > &added) const
Codegen incref.
Definition: mx_node.hpp:157
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
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
virtual bool is_unary() const
Check if unary operation.
Definition: mx_node.hpp:121
virtual void codegen_decref(CodeGenerator &g, std::set< void * > &added) const
Codegen decref.
Definition: mx_node.hpp:162
virtual casadi_int op() const =0
Get the operation.
virtual bool is_inf() const
Check if identically inf.
Definition: mx_node.hpp:91
casadi_int size1() const
Definition: mx_node.hpp:428
virtual bool has_refcount() const
Is reference counting needed in codegen?
Definition: mx_node.hpp:152
virtual bool is_minus_one() const
Check if identically minus one.
Definition: mx_node.hpp:81
virtual bool is_integer() const
Check if integer.
Definition: mx_node.hpp:101
virtual std::string disp(const std::vector< std::string > &arg) const =0
Print expression.
virtual bool is_output() const
Check if evaluation output.
Definition: mx_node.hpp:320
virtual bool is_equal(const MXNode *node, casadi_int depth) const
Definition: mx_node.hpp:375
virtual size_t sz_iw() const
Get required length of iw field.
Definition: mx_node.hpp:457
virtual bool is_eye() const
Check if identity matrix.
Definition: mx_node.hpp:116
static MX to_matrix(const MX &x, const Sparsity &sp)
Convert scalar to matrix.
Definition: mx_node.hpp:489
virtual bool is_half() const
Check if identically 0.5.
Definition: mx_node.hpp:86
MX - Matrix expression.
Definition: mx.hpp:92
static casadi_int get_max_depth()
Get the depth to which equalities are being checked for simplifications.
Definition: mx.cpp:942
Sparse matrix class. SX and DM are specializations.
Definition: matrix_decl.hpp:99
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
Class representing a Slice.
Definition: slice.hpp:48
General sparsity class.
Definition: sparsity.hpp:106
std::pair< casadi_int, casadi_int > size() const
Get the shape.
Definition: sparsity.cpp:152
The casadi namespace.
Definition: archiver.cpp:28
bool is_equal(double x, double y, casadi_int depth=0)
Definition: calculus.hpp:287
unsigned long long bvec_t
int to_int(casadi_int rhs)
Definition: casadi_misc.cpp:60
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.