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);
70 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
71 return eval_gen<double>(arg, res, iw, w);
76 return eval_gen<SXElem>(arg, res, iw, w);
81 eval_gen(
const T*
const* arg, T*
const* res, casadi_int* iw, T* w)
const {
82 const T* idata = arg[0];
84 for (
auto&& k :
nz_) {
85 *odata++ = k>=0 ? idata[k] : 0;
91 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
92 return eval_gen<double>(arg, res, iw, w);
97 return eval_gen<SXElem>(arg, res, iw, w);
102 casadi_int* iw, T* w)
const {
104 const T* idata_stop = arg[0] +
s_.
stop;
106 for (; idata != idata_stop; idata +=
s_.
step) {
113 eval(
const double** arg,
double** res, casadi_int* iw,
double* w)
const {
114 return eval_gen<double>(arg, res, iw, w);
119 return eval_gen<SXElem>(arg, res, iw, w);
124 eval_gen(
const T*
const* arg, T*
const* res, casadi_int* iw, T* w)
const {
128 for (; outer != outer_stop; outer +=
outer_.
step) {
142 for (
auto&& k :
nz_) *r++ = k>=0 ? a[k] : 0;
150 for (
auto&& k :
nz_) {
151 if (k>=0) a[k] |= *r;
204 std::stringstream ss;
205 ss << arg.at(0) <<
nz_;
210 std::stringstream ss;
211 ss << arg.at(0) <<
"[" <<
s_ <<
"]";
216 std::stringstream ss;
217 ss << arg.at(0) <<
"[" <<
outer_ <<
";" <<
inner_ <<
"]";
223 std::vector<casadi_int> nz =
all();
227 const casadi_int* orow = osp.
row();
228 std::vector<casadi_int> ocol = osp.
get_col();
233 std::vector<casadi_int> icol = isp.
get_col();
236 std::vector<casadi_int> el_input;
240 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
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);
248 r_colind.resize(osp.
size2()+1);
249 std::fill(r_colind.begin(), r_colind.end(), 0);
254 for (casadi_int k=0; k<nz.size(); ++k) {
257 casadi_int el = nz[k];
260 if (el==-1)
continue;
263 casadi_int el_arg = r_ind[el];
266 if (el_arg==-1)
continue;
269 r_nz.push_back(el_arg);
272 casadi_int i=ocol[k], j=orow[k];
280 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
287 res[0] = arg[0]->get_nzref(f_sp, r_nz);
292 std::vector<std::array<MX, 3> >& res)
const {
297 std::vector<std::vector<MX> >& fsens)
const {
300 std::vector<casadi_int> nz =
all();
303 casadi_int nfwd = fsens.size();
307 const casadi_int* orow = osp.
row();
308 std::vector<casadi_int> ocol = osp.
get_col();
313 std::vector<casadi_int> icol;
316 std::vector<casadi_int> el_input;
319 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
322 for (casadi_int d=0; d<nfwd; ++d) {
325 const MX& arg = fseed[d][0];
326 MX& res = fsens[d][0];
336 if (el_input.empty()) isp.
find(el_input);
337 if (icol.empty()) icol = isp.
get_col();
340 r_ind.resize(el_input.size());
341 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
345 r_colind.resize(osp.
size2()+1);
346 std::fill(r_colind.begin(), r_colind.end(), 0);
351 for (casadi_int k=0; k<nz.size(); ++k) {
354 casadi_int el = nz[k];
357 if (el==-1)
continue;
360 casadi_int el_arg = r_ind[el];
363 if (el_arg==-1)
continue;
366 r_nz.push_back(el_arg);
369 casadi_int i=ocol[k], j=orow[k];
377 for (casadi_int i=1; i<r_colind.size(); ++i) r_colind[i] += r_colind[i-1];
391 std::vector<std::vector<MX> >& asens)
const {
393 std::vector<casadi_int> nz =
all();
396 casadi_int nadj = aseed.size();
400 std::vector<casadi_int> ocol;
405 std::vector<casadi_int> icol;
408 std::vector<casadi_int> el_input;
411 std::vector<casadi_int> r_colind, r_row, r_nz, r_ind;
414 for (casadi_int d=0; d<nadj; ++d) {
418 MX aseed0 = aseed[d][0];
419 MX asens0 = asens[d][0];
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();
434 bool elements_to_add =
false;
435 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
438 elements_to_add =
true;
446 if (!elements_to_add)
continue;
449 r_ind.resize(el_input.size());
450 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
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) {
462 std::copy(el_input.begin(), el_input.end(), r_ind.begin());
470 for (std::vector<casadi_int>::iterator k=r_nz.begin(); k!=r_nz.end(); ++k) {
476 asens[d][0] = aseed0->
get_nzadd(asens0, r_nz);
482 std::vector<casadi_int> nz =
all();
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 {
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++ = ";
503 g <<
"*cii>=0 ? cs[*cii] : 0;\n";
511 std::vector<casadi_int> nz_all =
all();
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];
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]) {
528 g << g.
workel(res[0]) <<
" = " << g.
work(arg[0],
nnz(), arg_is_ref[0])
532 g << g.
work(res[0],
nnz(),
true) <<
" = "
534 res_is_ref[0] =
true;
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
542 <<
"; cs+=" <<
s_.
step <<
") *rr++ = *cs;\n";
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",
"*");
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 <<
"+"
560 <<
"; ct+=" <<
inner_.
step <<
") *rr++ = *ct;\n";
569 if (n==
nullptr)
return false;
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;
587 if (n==
nullptr)
return false;
593 if (this->
s_ != n->
s_)
return false;
604 if (n==
nullptr)
return false;
617 s.
pack(
"GetNonzerosVector::nonzeros",
nz_);
622 s.
pack(
"GetNonzeros::type",
'a');
626 s.
unpack(
"GetNonzerosVector::nonzeros",
nz_);
631 s.
pack(
"GetNonzerosSlice::slice",
s_);
636 s.
pack(
"GetNonzeros::type",
'b');
640 s.
unpack(
"GetNonzerosSlice::slice",
s_);
651 s.
pack(
"GetNonzeros::type",
'c');
661 s.
unpack(
"GetNonzeros::type", t);
666 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.
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res) const override
Evaluate symbolically (MX)
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)
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.
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.
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.
MX get_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz) const override
Get the nonzeros of matrix.
Node class for MX objects.
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
virtual casadi_int ind() const
const Sparsity & sparsity() const
Get the sparsity.
virtual MX get_project(const Sparsity &sp) const
Create set sparse.
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_nzref(const Sparsity &sp, const std::vector< casadi_int > &nz) const
Get the nonzeros of matrix.
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.