getnonzeros.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 "getnonzeros.hpp"
27 #include "casadi_misc.hpp"
28 #include "serializing_stream.hpp"
29 
30 namespace casadi {
31 
32  MX GetNonzeros::create(const Sparsity& sp, const MX& x, const std::vector<casadi_int>& nz) {
33  // No elements at all
34  if (nz.empty()) return MX::zeros(sp);
35  // Simplify to slice
36  if (is_slice(nz)) return create(sp, x, to_slice(nz));
37  // Simplify to slice2
38  if (is_slice2(nz)) {
39  std::pair<Slice, Slice> sl = to_slice2(nz);
40  return create(sp, x, sl.first, sl.second);
41  }
42  return MX::create(new GetNonzerosVector(sp, x, nz));
43  }
44 
45  MX GetNonzeros::create(const Sparsity& sp, const MX& x, const Slice& s) {
46  // Simplify identity assignments
47  if (sp==x.sparsity() && s.start==0 && s.step==1 && s.stop==x.nnz()) return x;
48  return MX::create(new GetNonzerosSlice(sp, x, s));
49  }
50 
51  MX GetNonzeros::create(const Sparsity& sp, const MX& x,
52  const Slice& inner, const Slice& outer) {
53  return MX::create(new GetNonzerosSlice2(sp, x, inner, outer));
54  }
55 
56  GetNonzeros::GetNonzeros(const Sparsity& sp, const MX& y) {
57  set_sparsity(sp);
58  set_dep(y);
59  }
60 
61  void GetNonzerosVector::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
62  const std::vector<bool>& unique) const {
63  if (!matches_sparsity(arg)) {
64  GetNonzeros::eval_mx(arg, res, unique);
65  return;
66  }
67  bool unique_arg0 = !unique.empty() && unique[0];
68  res[0] = arg[0]->get_nzref(sparsity(), nz_, unique_arg0);
69  }
70 
72  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
73  return eval_gen<double>(arg, res, iw, w);
74  }
75 
77  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
78  return eval_gen<SXElem>(arg, res, iw, w);
79  }
80 
81  template<typename T>
83  eval_gen(const T* const* arg, T* const* res, casadi_int* iw, T* w) const {
84  const T* idata = arg[0];
85  T* odata = res[0];
86  for (auto&& k : nz_) {
87  *odata++ = k>=0 ? idata[k] : 0;
88  }
89  return 0;
90  }
91 
93  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
94  return eval_gen<double>(arg, res, iw, w);
95  }
96 
98  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
99  return eval_gen<SXElem>(arg, res, iw, w);
100  }
101 
102  template<typename T>
103  int GetNonzerosSlice::eval_gen(const T* const* arg, T* const* res,
104  casadi_int* iw, T* w) const {
105  const T* idata = arg[0] + s_.start;
106  const T* idata_stop = arg[0] + s_.stop;
107  T* odata = res[0];
108  for (; idata != idata_stop; idata += s_.step) {
109  *odata++ = *idata;
110  }
111  return 0;
112  }
113 
115  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
116  return eval_gen<double>(arg, res, iw, w);
117  }
118 
120  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
121  return eval_gen<SXElem>(arg, res, iw, w);
122  }
123 
124  template<typename T>
126  eval_gen(const T* const* arg, T* const* res, casadi_int* iw, T* w) const {
127  const T* outer = arg[0] + outer_.start;
128  const T* outer_stop = arg[0] + outer_.stop;
129  T* odata = res[0];
130  for (; outer != outer_stop; outer += outer_.step) {
131  for (const T* inner = outer+inner_.start;
132  inner != outer+inner_.stop;
133  inner += inner_.step) {
134  *odata++ = *inner;
135  }
136  }
137  return 0;
138  }
139 
141  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
142  const bvec_t *a = arg[0];
143  bvec_t *r = res[0];
144  for (auto&& k : nz_) *r++ = k>=0 ? a[k] : 0;
145  return 0;
146  }
147 
149  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
150  bvec_t *a = arg[0];
151  bvec_t *r = res[0];
152  for (auto&& k : nz_) {
153  if (k>=0) a[k] |= *r;
154  *r++ = 0;
155  }
156  return 0;
157  }
158 
160  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
161  const bvec_t *a = arg[0];
162  bvec_t *r = res[0];
163  for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
164  *r++ = a[k];
165  }
166  return 0;
167  }
168 
170  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
171  bvec_t *a = arg[0];
172  bvec_t *r = res[0];
173  for (casadi_int k=s_.start; k!=s_.stop; k+=s_.step) {
174  a[k] |= *r;
175  *r++ = 0;
176  }
177  return 0;
178  }
179 
181  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
182  const bvec_t *a = arg[0];
183  bvec_t *r = res[0];
184  for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
185  for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
186  *r++ = a[k2];
187  }
188  }
189  return 0;
190  }
191 
193  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
194  bvec_t *a = arg[0];
195  bvec_t *r = res[0];
196  for (casadi_int k1=outer_.start; k1!=outer_.stop; k1+=outer_.step) {
197  for (casadi_int k2=k1+inner_.start; k2!=k1+inner_.stop; k2+=inner_.step) {
198  a[k2] |= *r;
199  *r++ = 0;
200  }
201  }
202  return 0;
203  }
204 
205  std::string GetNonzerosVector::disp(const std::vector<std::string>& arg) const {
206  std::stringstream ss;
207  ss << arg.at(0) << nz_;
208  return ss.str();
209  }
210 
211  std::string GetNonzerosSlice::disp(const std::vector<std::string>& arg) const {
212  std::stringstream ss;
213  ss << arg.at(0) << "[" << s_ << "]";
214  return ss.str();
215  }
216 
217  std::string GetNonzerosSlice2::disp(const std::vector<std::string>& arg) const {
218  std::stringstream ss;
219  ss << arg.at(0) << "[" << outer_ << ";" << inner_ << "]";
220  return ss.str();
221  }
222 
223  void GetNonzeros::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res,
224  const std::vector<bool>& unique) const {
225  // Get all the nonzeros
226  std::vector<casadi_int> nz = all();
227 
228  // Output sparsity
229  const Sparsity& osp = sparsity();
230  const casadi_int* orow = osp.row();
231  std::vector<casadi_int> ocol = osp.get_col();
232 
233  // Input sparsity
234  const Sparsity& isp = dep().sparsity();
235  //const std::vector<casadi_int>& irow = isp.row();
236  std::vector<casadi_int> icol = isp.get_col();
237 
238  // Get all input elements
239  std::vector<casadi_int> el_input;
240  isp.find(el_input);
241 
242  // Sparsity pattern being formed and corresponding nonzero mapping
243  std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
244 
245  // Get the matching nonzeros
246  r_ind.resize(el_input.size());
247  std::copy(el_input.begin(), el_input.end(), r_ind.begin());
248  arg[0].sparsity().get_nz(r_ind);
249 
250  // Sparsity pattern for the result
251  r_colind.resize(osp.size2()+1); // Col count
252  std::fill(r_colind.begin(), r_colind.end(), 0);
253  r_row.clear();
254 
255  // Perform the assignments
256  r_nz.clear();
257  for (casadi_int k=0; k<nz.size(); ++k) {
258 
259  // Get the corresponding nonzero for the input
260  casadi_int el = nz[k];
261 
262  // Skip if zero assignment
263  if (el==-1) continue;
264 
265  // Get the corresponding nonzero in the argument
266  casadi_int el_arg = r_ind[el];
267 
268  // Skip if no argument
269  if (el_arg==-1) continue;
270 
271  // Save the assignment
272  r_nz.push_back(el_arg);
273 
274  // Get the corresponding element
275  casadi_int i=ocol[k], j=orow[k];
276 
277  // Add to sparsity pattern
278  r_row.push_back(j);
279  r_colind[1+i]++;
280  }
281 
282  // col count -> col offset
283  for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
284 
285  // Create a sparsity pattern from vectors
286  if (r_nz.empty()) {
287  res[0] = MX(osp.size());
288  } else {
289  Sparsity f_sp(osp.size1(), osp.size2(), r_colind, r_row);
290  bool unique_arg0 = !unique.empty() && unique[0];
291  res[0] = arg[0]->get_nzref(f_sp, r_nz, unique_arg0);
292  }
293  }
294 
295  void GetNonzeros::eval_linear(const std::vector<std::array<MX, 3> >& arg,
296  std::vector<std::array<MX, 3> >& res) const {
297  eval_linear_rearrange(arg, res);
298  }
299 
300  void GetNonzeros::ad_forward(const std::vector<std::vector<MX> >& fseed,
301  std::vector<std::vector<MX> >& fsens) const {
302 
303  // Get all the nonzeros
304  std::vector<casadi_int> nz = all();
305 
306  // Number of derivative directions
307  casadi_int nfwd = fsens.size();
308 
309  // Output sparsity
310  const Sparsity& osp = sparsity();
311  const casadi_int* orow = osp.row();
312  std::vector<casadi_int> ocol = osp.get_col();
313 
314  // Input sparsity
315  const Sparsity& isp = dep().sparsity();
316  //const std::vector<casadi_int>& irow = isp.row();
317  std::vector<casadi_int> icol;
318 
319  // Get all input elements
320  std::vector<casadi_int> el_input;
321 
322  // Sparsity pattern being formed and corresponding nonzero mapping
323  std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
324 
325  // Nondifferentiated function and forward sensitivities
326  for (casadi_int d=0; d<nfwd; ++d) {
327 
328  // Get references to arguments and results
329  const MX& arg = fseed[d][0];
330  MX& res = fsens[d][0];
331 
332  if (arg.sparsity()==isp) { // Matching sparsity
333  if (nz.empty()) {
334  res = MX(osp.size());
335  } else {
336  res = arg->get_nzref(osp, nz);
337  }
338  } else {
339  // Expensive operations
340  if (el_input.empty()) isp.find(el_input);
341  if (icol.empty()) icol = isp.get_col();
342 
343  // Get the matching nonzeros
344  r_ind.resize(el_input.size());
345  std::copy(el_input.begin(), el_input.end(), r_ind.begin());
346  arg.sparsity().get_nz(r_ind);
347 
348  // Sparsity pattern for the result
349  r_colind.resize(osp.size2()+1); // Col count
350  std::fill(r_colind.begin(), r_colind.end(), 0);
351  r_row.clear();
352 
353  // Perform the assignments
354  r_nz.clear();
355  for (casadi_int k=0; k<nz.size(); ++k) {
356 
357  // Get the corresponding nonzero for the input
358  casadi_int el = nz[k];
359 
360  // Skip if zero assignment
361  if (el==-1) continue;
362 
363  // Get the corresponding nonzero in the argument
364  casadi_int el_arg = r_ind[el];
365 
366  // Skip if no argument
367  if (el_arg==-1) continue;
368 
369  // Save the assignment
370  r_nz.push_back(el_arg);
371 
372  // Get the corresponding element
373  casadi_int i=ocol[k], j=orow[k];
374 
375  // Add to sparsity pattern
376  r_row.push_back(j);
377  r_colind[1+i]++;
378  }
379 
380  // col count -> col offset
381  for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
382 
383  // Create a sparsity pattern from vectors
384  if (r_nz.empty()) {
385  res = MX(osp.size());
386  } else {
387  Sparsity f_sp(osp.size1(), osp.size2(), r_colind, r_row);
388  res = arg->get_nzref(f_sp, r_nz);
389  }
390  }
391  }
392  }
393 
394  void GetNonzeros::ad_reverse(const std::vector<std::vector<MX> >& aseed,
395  std::vector<std::vector<MX> >& asens) const {
396  // Get all the nonzeros
397  std::vector<casadi_int> nz = all();
398 
399  // Number of derivative directions
400  casadi_int nadj = aseed.size();
401 
402  // Output sparsity
403  const Sparsity& osp = sparsity();
404  std::vector<casadi_int> ocol;
405 
406  // Input sparsity
407  const Sparsity& isp = dep().sparsity();
408  //const std::vector<casadi_int>& irow = isp.row();
409  std::vector<casadi_int> icol;
410 
411  // Get all input elements
412  std::vector<casadi_int> el_input;
413 
414  // Sparsity pattern being formed and corresponding nonzero mapping
415  std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
416 
417  // Adjoint sensitivities
418  for (casadi_int d=0; d<nadj; ++d) {
419 
420  // Get an owning references to the seeds and sensitivities
421  // and clear the seeds for the next run
422  MX aseed0 = aseed[d][0];
423  MX asens0 = asens[d][0]; // Sensitivity before addition
424 
425  if (aseed0.sparsity()==osp && asens0.sparsity().nnz()==0) { // Matching sparsity
426  asens[d][0] = aseed0->get_nzadd(DM::zeros(isp), nz);
427  } else {
428  // Expensive operations
429  if (el_input.empty()) isp.find(el_input);
430  if (icol.empty()) icol = isp.get_col();
431  if (ocol.empty()) ocol = osp.get_col();
432 
433  // Get the corresponding nz locations in the output sparsity pattern
434  aseed0.sparsity().find(r_nz);
435  osp.get_nz(r_nz);
436 
437  // Filter out ignored entries and check if there is anything to add at all
438  bool elements_to_add = false;
439  for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
440  if (*k>=0) {
441  if (nz[*k]>=0) {
442  elements_to_add = true;
443  } else {
444  *k = -1;
445  }
446  }
447  }
448 
449  // Quick continue of no elements to add
450  if (!elements_to_add) continue;
451 
452  // Get the nz locations in the adjoint sensitivity corresponding to the inputs
453  r_ind.resize(el_input.size());
454  std::copy(el_input.begin(), el_input.end(), r_ind.begin());
455  asens0.sparsity().get_nz(r_ind);
456 
457  // Enlarge the sparsity pattern of the sensitivity if not all additions fit
458  for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
459  if (*k>=0 && r_ind[nz[*k]]<0) {
460 
461  // Create a new pattern which includes both the the previous seed and the addition
462  Sparsity sp = asens0.sparsity().unite(dep().sparsity());
463  asens0 = asens0->get_project(sp);
464 
465  // Recalculate the nz locations in the adjoint sensitivity corresponding to the inputs
466  std::copy(el_input.begin(), el_input.end(), r_ind.begin());
467  asens0.sparsity().get_nz(r_ind);
468 
469  break;
470  }
471  }
472 
473  // Have r_nz point to locations in the sensitivity instead of the output
474  for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
475  if (*k>=0) {
476  *k = r_ind[nz[*k]];
477  }
478  }
479 
480  asens[d][0] = aseed0->get_nzadd(asens0, r_nz);
481  }
482  }
483  }
484 
486  std::vector<casadi_int> nz = all();
487  return Matrix<casadi_int>(sparsity(), nz, false);
488  }
489 
491  const std::vector<casadi_int>& arg,
492  const std::vector<casadi_int>& res,
493  const std::vector<bool>& arg_is_ref,
494  std::vector<bool>& res_is_ref) const {
495  // Codegen the indices
496  std::string ind = g.constant(nz_);
497 
498  // Codegen the assignments
499  g.local("cii", "const casadi_int", "*");
500  g.local("rr", "casadi_real", "*");
501  g.local("cs", "const casadi_real", "*");
502  g << "for (cii=" << ind << ", rr=" << g.work(res[0], nnz(), false)
503  << ", cs=" << g.work(arg[0], dep(0).nnz(), arg_is_ref[0])
504  << "; cii!=" << ind << "+" << nz_.size()
505  << "; ++cii) *rr++ = ";
506  if (has_negative(nz_)) {
507  g << "*cii>=0 ? cs[*cii] : 0;\n";
508  } else {
509  g << "cs[*cii];\n";
510  }
511  }
512 
513  MX GetNonzeros::get_nzref(const Sparsity& sp, const std::vector<casadi_int>& nz,
514  bool unique) const {
515  // Get all the nonzeros
516  std::vector<casadi_int> nz_all = all();
517 
518  // Eliminate recursive calls
519  std::vector<casadi_int> nz_new(nz);
520  for (std::vector<casadi_int>::iterator i=nz_new.begin(); i!=nz_new.end(); ++i) {
521  if (*i>=0) *i = nz_all[*i];
522  }
523  return dep()->get_nzref(sp, nz_new, unique);
524  }
525 
527  const std::vector<casadi_int>& arg,
528  const std::vector<casadi_int>& res,
529  const std::vector<bool>& arg_is_ref,
530  std::vector<bool>& res_is_ref) const {
531  if (s_.step==1 && arg_is_ref[0]) {
532  if (nnz()==1) {
533  g << g.workel(res[0]) << " = " << g.work(arg[0], nnz(), arg_is_ref[0])
534  << "[" << s_.start << "];\n";
535  } else {
536  // Copy elided version
537  g << g.work(res[0], nnz(), true) << " = "
538  << g.work(arg[0], dep(0).nnz(), true) << "+" << s_.start << ";\n";
539  res_is_ref[0] = true;
540  }
541  } else {
542  g.local("rr", "casadi_real", "*");
543  g.local("cs", "const casadi_real", "*");
544  std::string a0 = g.work(arg[0], dep(0).nnz(), arg_is_ref[0]);
545  g << "for (rr=" << g.work(res[0], nnz(), false) << ", cs=" << a0
546  << "+" << s_.start << "; cs!=" << a0 << "+" << s_.stop
547  << "; cs+=" << s_.step << ") *rr++ = *cs;\n";
548  }
549  }
550 
552  const std::vector<casadi_int>& arg,
553  const std::vector<casadi_int>& res,
554  const std::vector<bool>& arg_is_ref,
555  std::vector<bool>& res_is_ref) const {
556  g.local("rr", "casadi_real", "*");
557  g.local("cs", "const casadi_real", "*");
558  g.local("ct", "const casadi_real", "*");
559 
560  std::string a0 = g.work(arg[0], dep(0).nnz(), arg_is_ref[0]);
561  g << "for (rr=" << g.work(res[0], nnz(), false) << ", cs="
562  << a0 << "+" << outer_.start << "; cs!=" << a0 << "+"
563  << outer_.stop << "; cs+=" << outer_.step << ") "
564  << "for (ct=cs+" << inner_.start << "; ct!=cs+" << inner_.stop
565  << "; ct+=" << inner_.step << ") *rr++ = *ct;\n";
566  }
567 
568  bool GetNonzerosVector::is_equal(const MXNode* node, casadi_int depth) const {
569  // Check dependencies
570  if (!sameOpAndDeps(node, depth)) return false;
571 
572  // Check if same node
573  const GetNonzerosVector* n = dynamic_cast<const GetNonzerosVector*>(node);
574  if (n==nullptr) return false;
575 
576  // Check sparsity
577  if (this->sparsity()!=node->sparsity()) return false;
578 
579  // Check indices
580  if (this->nz_.size()!=n->nz_.size()) return false;
581  if (!std::equal(this->nz_.begin(), this->nz_.end(), n->nz_.begin())) return false;
582 
583  return true;
584  }
585 
586  bool GetNonzerosSlice::is_equal(const MXNode* node, casadi_int depth) const {
587  // Check dependencies
588  if (!sameOpAndDeps(node, depth)) return false;
589 
590  // Check if same node
591  const GetNonzerosSlice* n = dynamic_cast<const GetNonzerosSlice*>(node);
592  if (n==nullptr) return false;
593 
594  // Check sparsity
595  if (this->sparsity()!=node->sparsity()) return false;
596 
597  // Check indices
598  if (this->s_ != n->s_) return false;
599 
600  return true;
601  }
602 
603  bool GetNonzerosSlice2::is_equal(const MXNode* node, casadi_int depth) const {
604  // Check dependencies
605  if (!sameOpAndDeps(node, depth)) return false;
606 
607  // Check if same node
608  const GetNonzerosSlice2* n = dynamic_cast<const GetNonzerosSlice2*>(node);
609  if (n==nullptr) return false;
610 
611  // Check sparsity
612  if (this->sparsity()!=node->sparsity()) return false;
613 
614  // Check indices
615  if (this->inner_ != n->inner_ || this->outer_!=n->outer_) return false;
616 
617  return true;
618  }
619 
622  s.pack("GetNonzerosVector::nonzeros", nz_);
623  }
624 
627  s.pack("GetNonzeros::type", 'a');
628  }
629 
631  s.unpack("GetNonzerosVector::nonzeros", nz_);
632  }
633 
636  s.pack("GetNonzerosSlice::slice", s_);
637  }
638 
641  s.pack("GetNonzeros::type", 'b');
642  }
643 
645  s.unpack("GetNonzerosSlice::slice", s_);
646  }
647 
650  s.pack("GetNonzerosSlice2::inner", inner_);
651  s.pack("GetNonzerosSlice2::outer", outer_);
652  }
653 
656  s.pack("GetNonzeros::type", 'c');
657  }
658 
660  s.unpack("GetNonzerosSlice2::inner", inner_);
661  s.unpack("GetNonzerosSlice2::outer", outer_);
662  }
663 
665  char t;
666  s.unpack("GetNonzeros::type", t);
667  switch (t) {
668  case 'a': return new GetNonzerosVector(s);
669  case 'b': return new GetNonzerosSlice(s);
670  case 'c': return new GetNonzerosSlice2(s);
671  default: casadi_assert_dev(false);
672  }
673  }
674 
675 } // namespace casadi
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string workel(casadi_int n) const
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
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.
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
bool is_equal(const MXNode *node, casadi_int depth) const override
Check if two nodes are equivalent up to a given depth.
GetNonzerosSlice2(const Sparsity &sp, const MX &x, const Slice &inner, const Slice &outer)
Constructor.
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 override
Generate code for the operation.
int eval_gen(const T *const *arg, T *const *res, casadi_int *iw, T *w) const
Evaluate the function (template)
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
void serialize_type(SerializingStream &s) const override
Serialize type information.
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: getnonzeros.cpp:93
int eval_gen(const T *const *arg, T *const *res, casadi_int *iw, T *w) const
Evaluate the function (template)
void serialize_type(SerializingStream &s) const override
Serialize type information.
GetNonzerosSlice(const Sparsity &sp, const MX &x, const Slice &s)
Constructor.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Definition: getnonzeros.cpp:98
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
bool is_equal(const MXNode *node, casadi_int depth) const override
Check if two nodes are equivalent up to a given depth.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
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 override
Generate code for the operation.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
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 override
Generate code for the operation.
bool is_equal(const MXNode *node, casadi_int depth) const override
Check if two nodes are equivalent up to a given depth.
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Definition: getnonzeros.cpp:77
void serialize_type(SerializingStream &s) const override
Serialize type information.
int eval_gen(const T *const *arg, T *const *res, casadi_int *iw, T *w) const
Evaluate the function (template)
Definition: getnonzeros.cpp:83
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
Definition: getnonzeros.cpp:61
std::vector< casadi_int > nz_
Operation sequence.
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: getnonzeros.cpp:72
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
GetNonzerosVector(const Sparsity &sp, const MX &x, const std::vector< casadi_int > &nz)
Constructor.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Get nonzeros of a matrix.
Definition: getnonzeros.hpp:42
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
void eval_linear(const std::vector< std::array< MX, 3 > > &arg, std::vector< std::array< MX, 3 > > &res) const override
Evaluate the MX node on a const/linear/nonlinear partition.
MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz, bool unique=false) const override
Get the nonzeros of matrix.
static MXNode * deserialize(DeserializingStream &s)
Deserialize without type information.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
Matrix< casadi_int > mapping() const override
Get an IM representation of a GetNonzeros or SetNonzeros node.
GetNonzeros(const Sparsity &sp, const MX &y)
Constructor.
Definition: getnonzeros.cpp:56
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
static MX create(const Sparsity &sp, const MX &x, const std::vector< casadi_int > &nz)
Definition: getnonzeros.cpp:32
virtual std::vector< casadi_int > all() const =0
Get all the nonzeros.
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 serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:535
virtual casadi_int ind() const
Definition: mx_node.cpp:212
friend class MX
Definition: mx_node.hpp:52
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:410
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
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:392
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
Definition: mx_node.cpp:530
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:224
virtual MX get_project(const Sparsity &sp, bool unique=false) const
Create set sparse.
Definition: mx_node.cpp:759
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
bool sameOpAndDeps(const MXNode *node, casadi_int depth) const
Checks if two nodes have the same operation and have.
Definition: mx_node.cpp:1000
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:228
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
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
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.
Class representing a Slice.
Definition: slice.hpp:48
casadi_int step
Definition: slice.hpp:54
casadi_int stop
stop value: use std::numeric_limits<casadi_int>::max() to indicate unboundedness
Definition: slice.hpp:53
casadi_int start
start value: negative values will get added to length
Definition: slice.hpp:51
General sparsity class.
Definition: sparsity.hpp:106
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Get the index of an existing non-zero element.
Definition: sparsity.cpp:246
casadi_int size1() const
Get the number of rows.
Definition: sparsity.cpp:124
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Get the location of all non-zero elements as they would appear in a Dense matrix.
Definition: sparsity.cpp:737
Sparsity unite(const Sparsity &y, std::vector< unsigned char > &mapping) const
Union of two sparsity patterns.
Definition: sparsity.cpp:409
std::vector< casadi_int > get_col() const
Get the column for each non-zero entry.
Definition: sparsity.cpp:368
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
const casadi_int * row() const
Get a reference to row-vector,.
Definition: sparsity.cpp:164
std::pair< casadi_int, casadi_int > size() const
Get the shape.
Definition: sparsity.cpp:152
The casadi namespace.
Definition: archiver.cpp:28
template class CASADI_EXPORT Matrix< casadi_int >
unsigned long long bvec_t
bool has_negative(const std::vector< T > &v)
Check if the vector has negative entries.
bool CASADI_EXPORT is_slice(const IM &x, bool ind1=false)
Is the IM a Slice.
bool CASADI_EXPORT is_slice2(const std::vector< casadi_int > &v)
Check if an index vector can be represented more efficiently as two nested slices.
Definition: slice.cpp:202
std::pair< Slice, Slice > CASADI_EXPORT to_slice2(const std::vector< casadi_int > &v)
Construct nested slices from an index vector (requires is_slice2(v) to be true)
Definition: slice.cpp:254
Slice CASADI_EXPORT to_slice(const IM &x, bool ind1=false)
Convert IM to Slice.