call_sx.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * K.U. 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_CALL_SX_HPP
27 #define CASADI_CALL_SX_HPP
28 
29 #include "sx_node.hpp"
30 #include "output_sx.hpp"
31 #include "function.hpp"
32 #include <deque>
33 #include <stack>
34 
35 // Caching of outputs requires a map
36 #include <unordered_map>
37 #define CACHING_MAP std::unordered_map
38 
40 namespace casadi {
41 
42 class CASADI_EXPORT CallSX : public SXNode {
43  private:
44 
48  CallSX(const Function& f, const std::vector<SXElem>& dep) :
49  f_(f), dep_(dep) {}
50 
52  public:
53 
57  inline static SXElem create(const Function& f, const std::vector<SXElem>& dep) {
58  casadi_assert(f.nnz_in()==dep.size(),
59  "CallSX::create(f,dep): dimension mismatch: " + str(f.nnz_in()) + " vs " + str(dep.size()));
60  return SXElem::create(new CallSX(f, dep));
61  }
62 
63  inline static int eval_sx(const Function& f, const SXElem** arg, SXElem** res) {
64  // Collect dep from arg
65  std::vector<SXElem> dep;
66  for (casadi_int i=0;i<f.n_in();++i) {
67  dep.insert(dep.end(), arg[i], arg[i]+f.nnz_in(i));
68  }
69 
70  std::vector<SXElem> ret = SXElem::call(f, dep);
71 
72  // Copy ret to res
73  casadi_int offset = 0;
74  for (casadi_int i=0;i<f.n_out();++i) {
75  casadi_copy(get_ptr(ret)+offset, f.nnz_out(i), res[i]);
76  offset += f.nnz_out(i);
77  }
78 
79  return 0;
80  }
81 
88  ~CallSX() override {
89  for (auto & d : dep_)
90  safe_delete(d.assignNoDelete(casadi_limits<SXElem>::nan));
91  }
92 
93  // Class name
94  std::string class_name() const override {return "CallSX";}
95 
96  bool is_op(casadi_int op) const override { return OP_CALL==op; }
97 
101  casadi_int n_dep() const override { return dep_.size();}
102 
106  SXElem get_output(casadi_int oind) const override {
107  SharedSXElem ret;
108  // If not found, add it,
109  if (!cache_.incache(oind, ret)) {
110  ret.own(new OutputSX(SXNode::shared_from_this(), oind));
111  cache_.tocache_if_missing(oind, ret);
112  }
113  return SXElem::create(ret.get());
114  }
115 
116  std::vector<SXElem> get_output(const std::vector<casadi_int>& oind) const override {
117  std::vector<SXElem> ret;
118  ret.reserve(oind.size());
119  for (casadi_int i : oind) {
120  SharedSXElem output;
121  if (!cache_.incache(i, output)) {
122  output.own(new OutputSX(SXNode::shared_from_this(), i));
123  // Avoid scanning the growing cache for each output in a batch.
124  cache_.tocache_if_missing(i, output, false);
125  }
126  ret.push_back(SXElem::create(output.get()));
127  }
128  cache_.prune();
129  return ret;
130  }
131 
135  const SXElem& dep(casadi_int i) const override { return dep_[i];}
136  SXElem& dep(casadi_int i) override { return dep_[i];}
137 
141  casadi_int op() const override { return OP_CALL; }
142 
146  bool is_call() const override { return true; }
147 
151  bool has_output() const override { return true; }
152 
156  Function which_function() const override { return f_; }
157 
161  std::string print(const std::string& arg1, const std::string& arg2) const override {
162  return f_.name();
163  }
164 
166 
170  std::vector<SXElem> dep_;
171 
172  void serialize_node(SerializingStream& s) const override {
173  s.pack("CallSX::f", f_);
174  s.pack("CallSX::dep", dep_);
175  }
176 
178  std::vector<SXElem> dep;
179  Function f;
180  s.unpack("CallSX::f", f);
181  s.unpack("CallSX::dep", dep);
182  return new CallSX(f, dep);
183  }
184 
185 };
186 
187 
188 } // namespace casadi
190 
191 #endif // CASADI_CALL_SX_HPP
casadi_int n_dep() const override
Number of dependencies.
Definition: call_sx.hpp:101
std::vector< SXElem > get_output(const std::vector< casadi_int > &oind) const override
Get a batch of outputs.
Definition: call_sx.hpp:116
static SXNode * deserialize(DeserializingStream &s)
Definition: call_sx.hpp:177
SXElem & dep(casadi_int i) override
get the reference of a child
Definition: call_sx.hpp:136
bool has_output() const override
Check if a multiple output node.
Definition: call_sx.hpp:151
bool is_op(casadi_int op) const override
check properties of a node
Definition: call_sx.hpp:96
SXElem get_output(casadi_int oind) const override
Get an output.
Definition: call_sx.hpp:106
std::vector< SXElem > dep_
The dependencies of the node.
Definition: call_sx.hpp:170
bool is_call() const override
Check if call node.
Definition: call_sx.hpp:146
Function which_function() const override
Get function.
Definition: call_sx.hpp:156
const SXElem & dep(casadi_int i) const override
get the reference of a dependency
Definition: call_sx.hpp:135
static SXElem create(const Function &f, const std::vector< SXElem > &dep)
Create a binary expression.
Definition: call_sx.hpp:57
void serialize_node(SerializingStream &s) const override
Definition: call_sx.hpp:172
casadi_int op() const override
Get the operation.
Definition: call_sx.hpp:141
std::string print(const std::string &arg1, const std::string &arg2) const override
Print expression.
Definition: call_sx.hpp:161
Function f_
Definition: call_sx.hpp:165
static int eval_sx(const Function &f, const SXElem **arg, SXElem **res)
Definition: call_sx.hpp:63
~CallSX() override
Destructor.
Definition: call_sx.hpp:88
std::string class_name() const override
Get type name.
Definition: call_sx.hpp:94
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Function object.
Definition: function.hpp:60
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:1007
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:975
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:1003
Internal * get() const
Get a const pointer to the node.
void own(Internal *node)
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
static std::vector< SXElem > call(const Function &f, const std::vector< SXElem > &deps)
Definition: sx_elem.cpp:232
static SXElem create(SXNode *node)
Definition: sx_elem.cpp:62
Internal node class for SX.
Definition: sx_node.hpp:49
SXElem shared_from_this()
Get a shared object from the current internal object.
Definition: sx_node.cpp:268
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
bool incache(const K &key, T &f, bool needs_lock=true) const
void tocache_if_missing(const K &key, T &f, bool prune=true)
casadi_limits class
The casadi namespace.
Definition: archiver.cpp:28
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
@ OP_CALL
Definition: calculus.hpp:88