onnx_function.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 #include "onnx_function_impl.hpp"
26 #include "graph_builder_internal.hpp"
27 #include "casadi_misc.hpp"
28 
29 namespace casadi {
30 
31  bool has_onnxbackend(const std::string& solver) {
32  return OnnxFunction::has_plugin(solver);
33  }
34 
35  void load_onnxbackend(const std::string& solver) {
37  }
38 
39  std::vector<std::string> onnxbackend_solvers() {
40  std::vector<std::string> ret;
41  for (auto&& s : OnnxFunction::solvers_) ret.push_back(s.first);
42  return ret;
43  }
44 
45  std::string onnxbackend_doc(const std::string& solver) {
46  return OnnxFunction::getPlugin(solver).doc;
47  }
48 
49  std::map<std::string, OnnxFunction::Plugin> OnnxFunction::solvers_;
50 
51 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
52  std::mutex OnnxFunction::mutex_solvers_;
53 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
54 
55  const std::string OnnxFunction::infix_ = "onnx";
56 
57  std::string OnnxFunction::meta_doc = "";
58 
59  const Options OnnxFunction::options_
61  {{"provider",
62  {OT_STRING, "Execution provider for the ONNX runtime backend"}},
63  {"dim_bindings",
64  {OT_DICT, "Sizes for symbolic/dynamic tensor dimensions (name -> size)"}},
65  {"input_shapes",
66  {OT_DICT, "Explicit shapes for inputs (name -> shape), overriding the model's"}},
67  {"input_values",
68  {OT_DICT, "Baked-in input values (name -> value); these inputs are not exposed"}},
69  {"fwd_dim",
70  {OT_STRING, "Symbolic dimension naming the forward seed count [nfwd]"}},
71  {"adj_dim",
72  {OT_STRING, "Symbolic dimension naming the adjoint seed count [nadj]"}}
73  }
74  };
75 
76  std::string onnx_dtype_name(casadi_int t) {
77  switch (t) {
78  case 1: return "FLOAT"; case 2: return "UINT8"; case 3: return "INT8";
79  case 4: return "UINT16"; case 5: return "INT16"; case 6: return "INT32";
80  case 7: return "INT64"; case 8: return "STRING"; case 9: return "BOOL";
81  case 10: return "FLOAT16"; case 11: return "DOUBLE"; case 12: return "UINT32";
82  case 13: return "UINT64"; case 16: return "BFLOAT16";
83  default: return "TYPE" + str(t);
84  }
85  }
86 
87  casadi_int onnx_dtype_enum(const std::string& name) {
88  static const std::map<std::string, casadi_int> m = {
89  {"FLOAT", 1}, {"UINT8", 2}, {"INT8", 3}, {"UINT16", 4}, {"INT16", 5},
90  {"INT32", 6}, {"INT64", 7}, {"STRING", 8}, {"BOOL", 9}, {"FLOAT16", 10},
91  {"DOUBLE", 11}, {"UINT32", 12}, {"UINT64", 13}, {"BFLOAT16", 16}};
92  auto it = m.find(name);
93  return it != m.end() ? it->second : 0;
94  }
95 
96  // Select a subset of tensors by name, preserving the requested order (empty request => all)
97  static std::vector<OnnxTensorInfo> select_tensors(const std::vector<OnnxTensorInfo>& all,
98  const std::vector<std::string>& req) {
99  if (req.empty()) return all;
100  std::vector<OnnxTensorInfo> sel;
101  for (const std::string& name : req) {
102  bool found = false;
103  for (const OnnxTensorInfo& t : all)
104  if (t.name == name) { sel.push_back(t); found = true; break; }
105  casadi_assert(found, "ONNX tensor '" + name + "' not found in model");
106  }
107  return sel;
108  }
109 
110  OnnxFunction::OnnxFunction(const std::string& name, const GraphBuilderInternal* gb,
111  const std::vector<std::string>& inputs,
112  const std::vector<std::string>& outputs)
113  : FunctionInternal(name) {
114  // Freeze a snapshot: the builder may mutate afterwards without affecting this function.
115  // Shapes are resolved by the builder (dim bindings + input-shape overrides applied).
116  model_data_ = gb->model_data_;
118  std::vector<OnnxTensorInfo> all_out;
119  for (const Node& n : gb->node_list()) {
120  OnnxTensorInfo t;
121  t.name = n.name;
122  t.elem_type = onnx_dtype_enum(n.dtype);
123  t.shape = gb->resolved_shape(n);
124  t.numel = 1;
125  for (casadi_int d : t.shape) t.numel *= d;
126  if (n.io == "input") {
127  all_in_.push_back(t);
128  model_inputs_.insert(t.name);
129  } else {
130  all_out.push_back(t);
131  model_outputs_.insert(t.name);
132  }
133  }
134  in_ = select_tensors(all_in_, inputs); // exposed CasADi inputs (selection)
135  out_ = select_tensors(all_out, outputs); // exposed CasADi outputs (selection)
136  }
137 
139  clear_mem();
140  }
141 
142  // Pack/unpack a vector<OnnxTensorInfo> as parallel arrays
143  static void pack_tensors(SerializingStream& s, const std::string& d,
144  const std::vector<OnnxTensorInfo>& v) {
145  std::vector<std::string> names;
146  std::vector<std::vector<casadi_int>> shapes;
147  std::vector<casadi_int> elem_types, numels;
148  for (const OnnxTensorInfo& t : v) {
149  names.push_back(t.name);
150  shapes.push_back(t.shape);
151  elem_types.push_back(t.elem_type);
152  numels.push_back(t.numel);
153  }
154  s.pack(d + "::names", names);
155  s.pack(d + "::shapes", shapes);
156  s.pack(d + "::elem_types", elem_types);
157  s.pack(d + "::numels", numels);
158  }
159  static void unpack_tensors(DeserializingStream& s, const std::string& d,
160  std::vector<OnnxTensorInfo>& v) {
161  std::vector<std::string> names;
162  std::vector<std::vector<casadi_int>> shapes;
163  std::vector<casadi_int> elem_types, numels;
164  s.unpack(d + "::names", names);
165  s.unpack(d + "::shapes", shapes);
166  s.unpack(d + "::elem_types", elem_types);
167  s.unpack(d + "::numels", numels);
168  v.clear();
169  for (size_t k = 0; k < names.size(); ++k)
170  v.push_back(OnnxTensorInfo{names[k], shapes[k], elem_types[k], numels[k]});
171  }
172 
176  }
177 
180  s.version("OnnxFunction", 1);
181  s.pack("OnnxFunction::model_data", std::string(model_data_.begin(), model_data_.end()));
182  pack_tensors(s, "OnnxFunction::in", in_);
183  pack_tensors(s, "OnnxFunction::out", out_);
184  pack_tensors(s, "OnnxFunction::all_in", all_in_);
185  s.pack("OnnxFunction::in_src", in_src_);
186  s.pack("OnnxFunction::in_val", in_val_);
187  s.pack("OnnxFunction::model_inputs",
188  std::vector<std::string>(model_inputs_.begin(), model_inputs_.end()));
189  s.pack("OnnxFunction::model_outputs",
190  std::vector<std::string>(model_outputs_.begin(), model_outputs_.end()));
191  s.pack("OnnxFunction::fwd_dim", fwd_dim_);
192  s.pack("OnnxFunction::adj_dim", adj_dim_);
193  s.pack("OnnxFunction::input_values", input_values_);
194  }
195 
197  s.version("OnnxFunction", 1);
198  std::string bytes;
199  s.unpack("OnnxFunction::model_data", bytes);
200  model_data_.assign(bytes.begin(), bytes.end());
201  unpack_tensors(s, "OnnxFunction::in", in_);
202  unpack_tensors(s, "OnnxFunction::out", out_);
203  unpack_tensors(s, "OnnxFunction::all_in", all_in_);
204  s.unpack("OnnxFunction::in_src", in_src_);
205  s.unpack("OnnxFunction::in_val", in_val_);
206  std::vector<std::string> mi, mo;
207  s.unpack("OnnxFunction::model_inputs", mi);
208  model_inputs_ = std::set<std::string>(mi.begin(), mi.end());
209  s.unpack("OnnxFunction::model_outputs", mo);
210  model_outputs_ = std::set<std::string>(mo.begin(), mo.end());
211  s.unpack("OnnxFunction::fwd_dim", fwd_dim_);
212  s.unpack("OnnxFunction::adj_dim", adj_dim_);
213  s.unpack("OnnxFunction::input_values", input_values_);
214  }
215 
218  }
219 
220  void OnnxFunction::init(const Dict& opts) {
221  for (auto&& op : opts) {
222  if (op.first == "fwd_dim") fwd_dim_ = op.second.to_string();
223  else if (op.first == "adj_dim") adj_dim_ = op.second.to_string();
224  }
225  // Baked inputs are fed a fixed value, not exposed as Function inputs
226  std::vector<OnnxTensorInfo> exposed;
227  for (const OnnxTensorInfo& t : in_) if (!input_values_.count(t.name)) exposed.push_back(t);
228  in_ = exposed;
229  build_io_map(); // baked-feed map over all model inputs
231  }
232 
234  // in_src: exposed-arg index (>=0), -2 baked value, or -1 unwired (fed a default later)
235  in_src_.clear();
236  in_val_.clear();
237  for (const OnnxTensorInfo& t : all_in_) {
238  casadi_int src = -1;
239  for (casadi_int j = 0; j < static_cast<casadi_int>(in_.size()); ++j)
240  if (in_[j].name == t.name) { src = j; break; }
241  auto bv = input_values_.find(t.name);
242  if (src < 0 && bv != input_values_.end()) {
243  casadi_assert(static_cast<casadi_int>(bv->second.size()) == t.numel,
244  "Baked value for '" + t.name + "' has " + str(bv->second.size())
245  + " elements, expected " + str(t.numel));
246  src = -2;
247  for (double v : bv->second) in_val_.push_back(v);
248  } else {
249  in_val_.insert(in_val_.end(), t.numel, 0.0); // placeholder block keeps voff aligned
250  }
251  in_src_.push_back(src);
252  }
253  }
254 
255  Sparsity OnnxFunction::tensor_sparsity(const std::vector<casadi_int>& shape) {
256  // CasADi is 2-D: rank-0/1/2 map directly, higher ranks flatten to a column vector
257  if (shape.empty()) return Sparsity::dense(1, 1);
258  if (shape.size() == 1) return Sparsity::dense(shape[0], 1);
259  if (shape.size() == 2) return Sparsity::dense(shape[0], shape[1]);
260  casadi_int numel = 1;
261  for (casadi_int d : shape) numel *= d;
262  return Sparsity::dense(numel, 1);
263  }
264 
265  Function OnnxFunction::wrap_derivative(const std::string& name,
266  const std::vector<std::string>& inames, const std::vector<std::string>& onames,
267  const std::vector<Sparsity>& in_sp, const std::vector<Sparsity>& out_sp,
268  const Dict& dim_bind, const Dict& opts) const {
269  // Re-create from the same model using only the derivative tensors it actually has
270  std::vector<std::string> cin, con;
271  for (const std::string& nm : inames) if (model_inputs_.count(nm)) cin.push_back(nm);
272  for (const std::string& nm : onames) if (model_outputs_.count(nm)) con.push_back(nm);
273  Dict o;
274  if (!dim_bind.empty()) o["dim_bindings"] = dim_bind;
275  Function g = from_model_data(plugin_name(), name + "_core", model_data_, cin, con, o);
276  // Present CasADi's full derivative signature: feed present inputs, zero-fill absent outputs
277  std::map<std::string, MX> m;
278  std::vector<MX> args(inames.size());
279  for (size_t i = 0; i < inames.size(); ++i) {
280  args[i] = MX::sym(inames[i], in_sp[i]);
281  m[inames[i]] = args[i];
282  }
283  std::vector<MX> gin;
284  for (const std::string& nm : cin) gin.push_back(m[nm]);
285  std::vector<MX> gout = g(gin);
286  std::map<std::string, MX> mo;
287  for (size_t k = 0; k < con.size(); ++k) mo[con[k]] = gout[k];
288  std::vector<MX> outs(onames.size());
289  for (size_t j = 0; j < onames.size(); ++j) {
290  auto it = mo.find(onames[j]);
291  outs[j] = it != mo.end() ? it->second : MX::zeros(out_sp[j]);
292  }
293  Dict wopts;
294  auto it = opts.find("derivative_of");
295  if (it != opts.end()) wopts["derivative_of"] = it->second;
296  return Function(name, args, outs, inames, onames, wopts);
297  }
298 
299  bool OnnxFunction::has_forward(casadi_int nfwd) const {
300  // Need a fwd_<tensor> for every DIFFERENTIABLE input (seed) and output (sensitivity)
301  if (in_.empty() || out_.empty()) return false;
302  std::string pref = diff_prefix("fwd");
303  bool any_in = false, any_out = false;
304  for (size_t i = 0; i < in_.size(); ++i) {
305  if (!diff_in(i)) continue;
306  any_in = true;
307  if (!model_inputs_.count(pref + in_[i].name)) return false;
308  }
309  for (size_t j = 0; j < out_.size(); ++j) {
310  if (!diff_out(j)) continue;
311  any_out = true;
312  if (!model_outputs_.count(pref + out_[j].name)) return false;
313  }
314  return any_in && any_out;
315  }
316 
317  Function OnnxFunction::get_forward(casadi_int nfwd, const std::string& name,
318  const std::vector<std::string>& inames,
319  const std::vector<std::string>& onames,
320  const Dict& opts) const {
321  std::vector<Sparsity> isp, osp;
322  for (const OnnxTensorInfo& x : in_) isp.push_back(tensor_sparsity(x.shape));
323  for (const OnnxTensorInfo& y : out_) isp.push_back(tensor_sparsity(y.shape));
324  for (const OnnxTensorInfo& x : in_) {
325  Sparsity s = tensor_sparsity(x.shape);
326  isp.push_back(Sparsity::dense(s.size1(), nfwd * s.size2()));
327  }
328  for (const OnnxTensorInfo& y : out_) {
329  Sparsity s = tensor_sparsity(y.shape);
330  osp.push_back(Sparsity::dense(s.size1(), nfwd * s.size2()));
331  }
332  Dict db; db[fwd_dim_] = nfwd;
333  return wrap_derivative(name, inames, onames, isp, osp, db, opts);
334  }
335 
336  bool OnnxFunction::has_reverse(casadi_int nadj) const {
337  // Need an adj_<tensor> output for every differentiable input and seed input per output
338  if (in_.empty() || out_.empty()) return false;
339  std::string pref = diff_prefix("adj");
340  bool any_in = false, any_out = false;
341  for (size_t i = 0; i < in_.size(); ++i) {
342  if (!diff_in(i)) continue;
343  any_in = true;
344  if (!model_outputs_.count(pref + in_[i].name)) return false;
345  }
346  for (size_t j = 0; j < out_.size(); ++j) {
347  if (!diff_out(j)) continue;
348  any_out = true;
349  if (!model_inputs_.count(pref + out_[j].name)) return false;
350  }
351  return any_in && any_out;
352  }
353 
354  Function OnnxFunction::get_reverse(casadi_int nadj, const std::string& name,
355  const std::vector<std::string>& inames,
356  const std::vector<std::string>& onames,
357  const Dict& opts) const {
358  std::vector<Sparsity> isp, osp;
359  for (const OnnxTensorInfo& x : in_) isp.push_back(tensor_sparsity(x.shape));
360  for (const OnnxTensorInfo& y : out_) isp.push_back(tensor_sparsity(y.shape));
361  for (const OnnxTensorInfo& y : out_) {
362  Sparsity s = tensor_sparsity(y.shape);
363  isp.push_back(Sparsity::dense(s.size1(), nadj * s.size2()));
364  }
365  for (const OnnxTensorInfo& x : in_) {
366  Sparsity s = tensor_sparsity(x.shape);
367  osp.push_back(Sparsity::dense(s.size1(), nadj * s.size2()));
368  }
369  Dict db; db[adj_dim_] = nadj;
370  return wrap_derivative(name, inames, onames, isp, osp, db, opts);
371  }
372 
374  // Need a jac_<out>_<in> output for every differentiable output/input pair
375  if (in_.empty() || out_.empty()) return false;
376  bool any = false;
377  for (size_t j = 0; j < out_.size(); ++j) {
378  if (!diff_out(j)) continue;
379  for (size_t i = 0; i < in_.size(); ++i) {
380  if (!diff_in(i)) continue;
381  any = true;
382  if (!model_outputs_.count("jac_" + out_[j].name + "_" + in_[i].name)) return false;
383  }
384  }
385  return any;
386  }
387 
388  Function OnnxFunction::get_jacobian(const std::string& name,
389  const std::vector<std::string>& inames,
390  const std::vector<std::string>& onames,
391  const Dict& opts) const {
392  std::vector<Sparsity> isp, osp;
393  for (const OnnxTensorInfo& x : in_) isp.push_back(tensor_sparsity(x.shape));
394  for (const OnnxTensorInfo& y : out_) isp.push_back(tensor_sparsity(y.shape));
395  for (const OnnxTensorInfo& y : out_) {
396  Sparsity so = tensor_sparsity(y.shape);
397  for (const OnnxTensorInfo& x : in_) {
398  Sparsity si = tensor_sparsity(x.shape);
399  osp.push_back(Sparsity::dense(so.size1() * so.size2(), si.size1() * si.size2()));
400  }
401  }
402  return wrap_derivative(name, inames, onames, isp, osp, Dict(), opts);
403  }
404 
405  Function OnnxFunction::create(const std::string& solver, const std::string& name,
406  const GraphBuilderInternal* gb,
407  const std::vector<std::string>& inputs,
408  const std::vector<std::string>& outputs,
409  const Dict& opts) {
410  return Function::create(getPlugin(solver).creator(name, gb, inputs, outputs, opts), opts);
411  }
412 
413  Function OnnxFunction::from_model_data(const std::string& solver, const std::string& name,
414  const std::vector<uint8_t>& model_data,
415  const std::vector<std::string>& inputs,
416  const std::vector<std::string>& outputs,
417  const Dict& opts) {
418  // Stage the model + configuration in a GraphBuilder, then freeze an OnnxFunction snapshot
419  GraphBuilder b(name, model_data, "onnx");
420  GraphBuilderInternal* bi = b.get();
421  Dict fopts;
422  for (auto&& op : opts) {
423  if (op.first == "dim_bindings") {
424  for (auto&& d : static_cast<Dict>(op.second)) bi->dim_bindings_[d.first] = d.second;
425  } else if (op.first == "input_shapes") {
426  for (auto&& d : static_cast<Dict>(op.second))
427  bi->input_shapes_[d.first] = d.second.to_int_vector();
428  } else if (op.first == "input_values") {
429  for (auto&& d : static_cast<Dict>(op.second))
430  bi->input_values_[d.first] = d.second.to_double_vector();
431  } else {
432  fopts[op.first] = op.second;
433  }
434  }
435  return OnnxFunction::create(solver, name, bi, inputs, outputs, fopts);
436  }
437 
438 } // namespace casadi
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
Internal class for Function.
std::string diff_prefix(const std::string &prefix) const
Determine prefix for differentiated functions.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static const Options options_
Options.
void serialize_type(SerializingStream &s) const override
Serialize type information.
Function object.
Definition: function.hpp:60
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:488
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
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.
Internal class for GraphBuilder.
std::map< std::string, std::vector< double > > input_values_
const std::vector< Node > & node_list() const
std::vector< casadi_int > resolved_shape(const Node &n) const
std::map< std::string, casadi_int > dim_bindings_
Pending configuration carried into create()
std::map< std::string, std::vector< casadi_int > > input_shapes_
A mutable, format-neutral interface to a computational-graph model.
GraphBuilderInternal * get() const
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Return function that calculates forward derivatives.
static Sparsity tensor_sparsity(const std::vector< casadi_int > &shape)
Map an ONNX N-D shape to a 2-D CasADi sparsity (rank<=2 direct, rank>2 flattened column)
std::string fwd_dim_
Symbolic dimensions naming the forward/adjoint seed counts (bound in get_forward/reverse)
static const std::string infix_
static std::map< std::string, Plugin > solvers_
Plugin registry.
Function get_jacobian(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Return Jacobian of all input elements with respect to all output elements.
Function wrap_derivative(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const std::vector< Sparsity > &in_sp, const std::vector< Sparsity > &out_sp, const Dict &dim_bind, const Dict &opts) const
std::set< std::string > model_outputs_
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Return function that calculates adjoint derivatives.
std::vector< casadi_int > in_src_
Per all_in_ entry: exposed-arg index (>=0), -2 baked value, or -1 unwired (default)
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
std::vector< OnnxTensorInfo > in_
Metadata for the exposed inputs/outputs (the selection)
bool has_jacobian() const override
Return Jacobian of all input elements with respect to all output elements.
void serialize_type(SerializingStream &s) const override
Serialize type information.
std::map< std::string, std::vector< double > > input_values_
Baked input values: input name -> value; such inputs are not exposed as Function inputs.
bool diff_out(casadi_int i) const
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into a plugin instance (dispatches on the plugin name)
void build_io_map()
Compute the per-model-input feed map: in_src_ (arg index / -2 baked / -1 default) + in_val_.
bool has_forward(casadi_int nfwd) const override
Return function that calculates forward derivatives.
static Function create(const std::string &solver, const std::string &name, const GraphBuilderInternal *gb, const std::vector< std::string > &inputs, const std::vector< std::string > &outputs, const Dict &opts)
Plugin factory.
static const Options options_
Options.
static std::string meta_doc
Documentation string.
std::vector< OnnxTensorInfo > out_
std::vector< OnnxTensorInfo > all_in_
Metadata for every model input (a runtime backend must feed all of them)
std::vector< uint8_t > model_data_
Serialized ONNX model.
static Function from_model_data(const std::string &solver, const std::string &name, const std::vector< uint8_t > &model_data, const std::vector< std::string > &inputs, const std::vector< std::string > &outputs, const Dict &opts)
Freeze a function from raw model bytes: stage a transient GraphBuilder, then create()
std::set< std::string > model_inputs_
Names of every input/output tensor in the model (for derivative detection)
bool diff_in(casadi_int i) const
True if input/output index is differentiable (is_diff_in/out, default true)
OnnxFunction(const std::string &name, const GraphBuilderInternal *gb, const std::vector< std::string > &inputs, const std::vector< std::string > &outputs)
Construct by freezing a snapshot of a builder's metadata + config (exposed selection)
std::vector< double > in_val_
Baked input values, flat over all_in_ (numel each; placeholder block when not baked)
bool has_reverse(casadi_int nadj) const override
Return function that calculates adjoint derivatives.
void init(const Dict &opts) override
Initialize.
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
void serialize_type(SerializingStream &s) const
Serialize type information.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
virtual const char * plugin_name() const=0
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.
Base class for FunctionInternal and LinsolInternal.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
General sparsity class.
Definition: sparsity.hpp:106
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Definition: sparsity.cpp:1028
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
std::string onnxbackend_doc(const std::string &solver)
Get documentation for an ONNX runtime backend.
void load_onnxbackend(const std::string &solver)
Load an ONNX runtime backend.
bool has_onnxbackend(const std::string &solver)
Check if a given ONNX runtime backend is available.
std::vector< std::string > onnxbackend_solvers()
List available ONNX runtime backends.
The casadi namespace.
Definition: archiver.cpp:28
std::string onnx_dtype_name(casadi_int t)
Human-readable name of an ONNX element-type enum (1=FLOAT, 11=DOUBLE, 7=INT64, ......
casadi_int onnx_dtype_enum(const std::string &name)
ONNX element-type enum for a human-readable name (inverse of onnx_dtype_name; 0 if unknown)
static std::vector< OnnxTensorInfo > select_tensors(const std::vector< OnnxTensorInfo > &all, const std::vector< std::string > &req)
static void unpack_tensors(DeserializingStream &s, const std::string &d, std::vector< OnnxTensorInfo > &v)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
bool any(const std::vector< bool > &v)
Check if any arguments are true.
Definition: casadi_misc.cpp:88
bool all(const std::vector< bool > &v)
Check if all arguments are true.
Definition: casadi_misc.cpp:81
static void pack_tensors(SerializingStream &s, const std::string &d, const std::vector< OnnxTensorInfo > &v)
Metadata for one graph tensor (graph input or output)
Metadata for a single ONNX tensor (input or output); shape is resolved by the builder.
casadi_int elem_type
ONNX element type enum (1=float, 11=double, 7=int64)
std::vector< casadi_int > shape
Resolved shape (dynamic dims bound or set to 1)
std::string name
ONNX tensor name.
casadi_int numel
Number of elements in the resolved shape.