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