26 #include "getnonzeros.hpp"
27 #include "casadi_misc.hpp"
28 #include "serializing_stream.hpp"
39 std::pair<Slice, Slice> sl =
to_slice2(nz);
40 return create(sp, x, sl.first, sl.second);
62 const std::vector<bool>& unique)
const {
67 bool unique_arg0 = !unique.empty() && unique[0];
68 res[0] = arg[0]->get_nzref(
sparsity(),
nz_, unique_arg0);
72 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
73 return eval_gen<double>(arg, res, iw, w);
78 return eval_gen<SXElem>(arg, res, iw, w);
83 eval_gen(
const T*
const* arg, T*
const* res, casadi_int* iw, T* w)
const {
84 const T* idata = arg[0];
86 for (
auto&& k :
nz_) {
87 *odata++ = k>=0 ? idata[k] : 0;
93 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
94 return eval_gen<double>(arg, res, iw, w);
99 return eval_gen<SXElem>(arg, res, iw, w);
104 casadi_int* iw, T* w)
const {
106 const T* idata_stop = arg[0] +
s_.
stop;
108 for (; idata != idata_stop; idata +=
s_.
step) {
115 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
116 return eval_gen<double>(arg, res, iw, w);
121 return eval_gen<SXElem>(arg, res, iw, w);
126 eval_gen(
const T*
const* arg, T*
const* res, casadi_int* iw, T* w)
const {
130 for (; outer != outer_stop; outer +=
outer_.
step) {
144 for (
auto&& k :
nz_) *r++ = k>=0 ? a[k] : 0;
152 for (
auto&& k :
nz_) {
153 if (k>=0) a[k] |= *r;
206 std::stringstream ss;
207 ss << arg.at(0) <<
nz_;
212 std::stringstream ss;
213 ss << arg.at(0) <<
"[" <<
s_ <<
"]";
218 std::stringstream ss;
219 ss << arg.at(0) <<
"[" <<
outer_ <<
";" <<
inner_ <<
"]";
224 const std::vector<bool>& unique)
const {
226 std::vector<casadi_int> nz =
all();
230 const casadi_int* orow = osp.
row();
231 std::vector<casadi_int> ocol = osp.
get_col();
236 std::vector<casadi_int> icol = isp.
get_col();
239 std::vector<casadi_int> el_input;
243 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
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);
251 r_colind.resize(osp.
size2()+1);
252 std::fill(r_colind.begin(), r_colind.end(), 0);
257 for (casadi_int k=0; k<nz.size(); ++k) {
260 casadi_int el = nz[k];
263 if (el==-1)
continue;
266 casadi_int el_arg = r_ind[el];
269 if (el_arg==-1)
continue;
272 r_nz.push_back(el_arg);
275 casadi_int i=ocol[k], j=orow[k];
283 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
290 bool unique_arg0 = !unique.empty() && unique[0];
291 res[0] = arg[0]->get_nzref(f_sp, r_nz, unique_arg0);
296 std::vector<std::array<MX, 3> >& res)
const {
301 std::vector<std::vector<MX> >& fsens)
const {
304 std::vector<casadi_int> nz =
all();
307 casadi_int nfwd = fsens.size();
311 const casadi_int* orow = osp.
row();
312 std::vector<casadi_int> ocol = osp.
get_col();
317 std::vector<casadi_int> icol;
320 std::vector<casadi_int> el_input;
323 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
326 for (casadi_int d=0; d<nfwd; ++d) {
329 const MX& arg = fseed[d][0];
330 MX& res = fsens[d][0];
340 if (el_input.empty()) isp.
find(el_input);
341 if (icol.empty()) icol = isp.
get_col();
344 r_ind.resize(el_input.size());
345 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
349 r_colind.resize(osp.
size2()+1);
350 std::fill(r_colind.begin(), r_colind.end(), 0);
355 for (casadi_int k=0; k<nz.size(); ++k) {
358 casadi_int el = nz[k];
361 if (el==-1)
continue;
364 casadi_int el_arg = r_ind[el];
367 if (el_arg==-1)
continue;
370 r_nz.push_back(el_arg);
373 casadi_int i=ocol[k], j=orow[k];
381 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
395 std::vector<std::vector<MX> >& asens)
const {
397 std::vector<casadi_int> nz =
all();
400 casadi_int nadj = aseed.size();
404 std::vector<casadi_int> ocol;
409 std::vector<casadi_int> icol;
412 std::vector<casadi_int> el_input;
415 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
418 for (casadi_int d=0; d<nadj; ++d) {
422 MX aseed0 = aseed[d][0];
423 MX asens0 = asens[d][0];
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();
438 bool elements_to_add =
false;
439 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
442 elements_to_add =
true;
450 if (!elements_to_add)
continue;
453 r_ind.resize(el_input.size());
454 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
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) {
466 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
474 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
480 asens[d][0] = aseed0->
get_nzadd(asens0, r_nz);
486 std::vector<casadi_int> nz =
all();
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 {
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++ = ";
507 g <<
"*cii>=0 ? cs[*cii] : 0;\n";
516 std::vector<casadi_int> nz_all =
all();
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];
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]) {
533 g << g.
workel(res[0]) <<
" = " << g.
work(arg[0],
nnz(), arg_is_ref[0])
537 g << g.
work(res[0],
nnz(),
true) <<
" = "
539 res_is_ref[0] =
true;
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
547 <<
"; cs+=" <<
s_.
step <<
") *rr++ = *cs;\n";
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",
"*");
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 <<
"+"
565 <<
"; ct+=" <<
inner_.
step <<
") *rr++ = *ct;\n";
574 if (n==
nullptr)
return false;
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;
592 if (n==
nullptr)
return false;
598 if (this->
s_ != n->
s_)
return false;
609 if (n==
nullptr)
return false;
622 s.
pack(
"GetNonzerosVector::nonzeros",
nz_);
627 s.
pack(
"GetNonzeros::type",
'a');
631 s.
unpack(
"GetNonzerosVector::nonzeros",
nz_);
636 s.
pack(
"GetNonzerosSlice::slice",
s_);
641 s.
pack(
"GetNonzeros::type",
'b');
645 s.
unpack(
"GetNonzerosSlice::slice",
s_);
656 s.
pack(
"GetNonzeros::type",
'c');
666 s.
unpack(
"GetNonzeros::type", t);
671 default: casadi_assert_dev(
false);
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.
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)
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)
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)
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res, const std::vector< bool > &unique={}) const override
Evaluate symbolically (MX)
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.
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.
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.
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)
virtual std::vector< casadi_int > all() const =0
Get all the nonzeros.
Node class for MX objects.
virtual MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz, bool unique=false) const
Get the nonzeros of matrix.
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
virtual casadi_int ind() const
const Sparsity & sparsity() const
Get the sparsity.
casadi_int nnz(casadi_int i=0) const
bool matches_sparsity(const std::vector< T > &arg) const
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
virtual MX get_project(const Sparsity &sp, bool unique=false) const
Create set sparse.
virtual MX get_nzadd(const MX &y, const std::vector< casadi_int > &nz) const
Add the nonzeros of a matrix to another matrix.
bool sameOpAndDeps(const MXNode *node, casadi_int depth) const
Checks if two nodes have the same operation and have.
void set_dep(const MX &dep)
Set unary dependency.
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.
static MX create(MXNode *node)
Create from node.
const Sparsity & sparsity() const
Get the sparsity pattern.
The basic scalar symbolic class of CasADi.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
casadi_int stop
stop value: use std::numeric_limits<casadi_int>::max() to indicate unboundedness
casadi_int start
start value: negative values will get added to length
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Get the index of an existing non-zero element.
casadi_int size1() const
Get the number of rows.
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.
Sparsity unite(const Sparsity &y, std::vector< unsigned char > &mapping) const
Union of two sparsity patterns.
std::vector< casadi_int > get_col() const
Get the column for each non-zero entry.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
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.
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)
Slice CASADI_EXPORT to_slice(const IM &x, bool ind1=false)
Convert IM to Slice.