27 #include "sparsity_internal.hpp"
28 #include "casadi_misc.hpp"
29 #include "global_options.hpp"
36 casadi_int *w, casadi_int ata) {
42 casadi_int r, c, k, rnext;
44 casadi_int nrow = *
sp++, ncol = *
sp++;
47 casadi_int *ancestor=w;
52 for (r=0; r<nrow; ++r) prev[r] = -1;
55 for (c=0; c<ncol; ++c) {
63 while (r!=-1 && r<c) {
66 if (rnext==-1) parent[r] = c;
69 if (ata) prev[
row[k]] = c;
75 casadi_int* head,
const casadi_int* next,
76 casadi_int* post, casadi_int* stack) {
81 casadi_int i, p, top=0;
100 casadi_int* post, casadi_int* w) {
107 casadi_int *head, *next, *stack;
112 for (j=0; j<n; ++j) head[j] = -1;
114 for (j=n-1; j>=0; --j) {
116 next[j] = head[parent[j]];
120 for (j=0; j<n; j++) {
128 leaf(casadi_int i, casadi_int j,
const casadi_int* first, casadi_int* maxfirst,
129 casadi_int* prevleaf, casadi_int* ancestor, casadi_int* jleaf) {
134 casadi_int q, s, sparent, jprev;
137 if (i<=j || first[j]<=maxfirst[i])
return -1;
139 maxfirst[i] = first[j];
144 *jleaf = (jprev == -1) ? 1 : 2;
146 if (*jleaf==1)
return i;
148 for (q=jprev; q!=ancestor[q]; q=ancestor[q]) {}
149 for (s=jprev; s!=q; s=sparent) {
150 sparent = ancestor[s];
158 qr_counts(
const casadi_int* tr_sp,
const casadi_int* parent,
159 const casadi_int* post, casadi_int* counts, casadi_int* w) {
164 casadi_int ncol = *tr_sp++, nrow = *tr_sp++;
165 const casadi_int *rowind=tr_sp, *col=tr_sp+nrow+1;
166 casadi_int i, j, k, J, p, q, jleaf, *maxfirst, *prevleaf,
167 *ancestor, *head=
nullptr, *next=
nullptr, *first;
176 for (k=0; k<ncol; ++k) first[k]=-1;
177 for (k=0; k<ncol; ++k) {
180 counts[j] = (first[j]==-1) ? 1 : 0;
181 for (; j!=-1 && first[j]==-1; j=parent[j]) first[j]=k;
184 for (k=0; k<ncol; ++k) ancestor[post[k]] = k;
185 for (k=0; k<ncol+1; ++k) head[k]=-1;
186 for (i=0; i<nrow; ++i) {
187 for (k=ncol, p=rowind[i]; p<rowind[i+1]; ++p) {
188 k = std::min(k, ancestor[col[p]]);
196 for (k=0; k<ncol; ++k) maxfirst[k]=-1;
197 for (k=0; k<ncol; ++k) prevleaf[k]=-1;
199 for (i=0; i<ncol; ++i) ancestor[i]=i;
200 for (k=0; k<ncol; ++k) {
203 if (parent[j]!=-1) counts[parent[j]]--;
206 for (p=rowind[J]; p<rowind[J+1]; ++p) {
208 q =
leaf(i, j, first, maxfirst, prevleaf, ancestor, &jleaf);
209 if (jleaf>=1) counts[j]++;
210 if (jleaf==2) counts[q]--;
214 if (parent[j]!=-1) ancestor[j]=parent[j];
217 for (j=0; j<ncol; ++j) {
218 if (parent[j]!=-1) counts[parent[j]] += counts[j];
222 casadi_int sum_counts = 0;
223 for (j=0; j<ncol; ++j) sum_counts += counts[j];
228 qr_nnz(
const casadi_int* sp, casadi_int* pinv, casadi_int* leftmost,
229 const casadi_int* parent, casadi_int* nrow_ext, casadi_int* w) {
235 casadi_int nrow =
sp[0], ncol =
sp[1];
238 casadi_int *next=w; w+=nrow;
239 casadi_int *head=w; w+=ncol;
240 casadi_int *tail=w; w+=ncol;
241 casadi_int *nque=w; w+=ncol;
243 casadi_int r, c, k, pa;
245 for (c=0; c<ncol; ++c) head[c] = -1;
246 for (c=0; c<ncol; ++c) tail[c] = -1;
247 for (c=0; c<ncol; ++c) nque[c] = 0;
248 for (r=0; r<nrow; ++r) leftmost[r] = -1;
250 for (c=ncol-1; c>=0; --c) {
252 leftmost[
row[k]] = c;
256 for (r=nrow-1; r>=0; --r) {
261 if (nque[c]++ == 0) tail[c]=r;
266 casadi_int v_nnz = 0;
267 casadi_int nrow_new = nrow;
268 for (c=0; c<ncol; ++c) {
271 if (r<0) r=nrow_new++;
273 if (--nque[c]<=0)
continue;
278 if (nque[pa]==0) tail[pa] = tail[c];
279 next[tail[c]] = head[pa];
284 for (r=0; r<nrow; ++r)
if (pinv[r]<0) pinv[r] = c++;
285 if (nrow_ext) *nrow_ext = nrow_new;
290 qr_init(
const casadi_int* sp,
const casadi_int* sp_tr,
291 casadi_int* leftmost, casadi_int* parent, casadi_int* pinv,
292 casadi_int* nrow_ext, casadi_int* v_nnz, casadi_int* r_nnz, casadi_int* w) {
294 casadi_int ncol =
sp[1];
298 casadi_int* post = w; w += ncol;
301 *r_nnz =
qr_counts(sp_tr, parent, post, w, w+ncol);
303 *v_nnz =
qr_nnz(
sp, pinv, leftmost, parent, nrow_ext, w);
307 qr_sparsities(
const casadi_int* sp_a, casadi_int nrow_ext, casadi_int* sp_v, casadi_int* sp_r,
308 const casadi_int* leftmost,
const casadi_int* parent,
const casadi_int* pinv,
315 casadi_int ncol = sp_a[1];
316 const casadi_int *
colind=sp_a+2, *
row=sp_a+2+ncol+1;
317 casadi_int *v_colind=sp_v+2, *v_row=sp_v+2+ncol+1;
318 casadi_int *r_colind=sp_r+2, *r_row=sp_r+2+ncol+1;
320 sp_v[0] = sp_r[0] = nrow_ext;
321 sp_v[1] = sp_r[1] = ncol;
323 casadi_int* s = iw; iw += ncol;
325 casadi_int r, c, k, k1, top, len, k2, r2;
327 for (r=0; r<nrow_ext; ++r) iw[r] = -1;
329 casadi_int nnz_r=0, nnz_v=0;
331 for (c=0; c<ncol; ++c) {
335 v_colind[c] = k1 = nnz_v;
341 r = leftmost[
row[k]];
343 for (len=0; iw[r]!=c; r=parent[r]) {
347 while (len>0) s[--top] = s[--len];
349 if (r>c && iw[r]<c) {
355 for (k = top; k<ncol; ++k) {
361 for (k2=v_colind[r]; k2<v_colind[r+1]; ++k2) {
374 r_colind[ncol] = nnz_r;
375 v_colind[ncol] = nnz_v;
379 ldl_colind(
const casadi_int* sp, casadi_int* parent, casadi_int* l_colind, casadi_int* w) {
384 casadi_int n =
sp[0];
389 casadi_int* visited=w; w+=n;
391 for (c=0; c<n; ++c) {
399 while (visited[r]!=c) {
401 if (parent[r]==-1) parent[r]=c;
410 for (c=0; c<n; ++c) l_colind[c+1] += l_colind[c];
414 ldl_row(
const casadi_int* sp,
const casadi_int* parent, casadi_int* l_colind,
415 casadi_int* l_row, casadi_int *w) {
421 casadi_int n =
sp[0];
424 casadi_int *visited=w; w+=n;
428 for (c=0; c<n; ++c) {
434 while (visited[r]!=c) {
435 l_row[l_colind[r]++] = c;
443 for (c=0; c<n; ++c) {
452 const casadi_int* colind,
const casadi_int* row) :
453 sp_(2 + ncol+1 + colind[ncol]), btf_(nullptr) {
465 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
467 std::lock_guard<std::mutex> lock(btf_mtx_);
470 btf_ =
new SparsityInternal::Btf();
471 btf_->nb =
btf(btf_->rowperm, btf_->colperm, btf_->rowblock, btf_->colblock,
472 btf_->coarse_rowblock, btf_->coarse_colblock);
486 stream <<
"colind: " <<
get_colind() << std::endl;
487 stream <<
"row: " <<
get_row() << std::endl;
493 std::vector<casadi_int> col(
nnz());
494 for (casadi_int r=0; r<
size2(); ++r) {
495 for (casadi_int el =
colind[r]; el <
colind[r+1]; ++el) {
504 std::vector<casadi_int> mapping;
510 std::vector<casadi_int>& mapping,
bool invert_mapping)
const {
512 std::vector<casadi_int> trans_col =
get_row();
513 std::vector<casadi_int> trans_row =
get_col();
520 std::vector<casadi_int>& pstack,
521 const std::vector<casadi_int>& pinv,
522 std::vector<bool>& marked)
const {
530 const casadi_int*
row = this->
row();
538 casadi_int jnew = !pinv.empty() ? (pinv[j]) : j;
543 pstack[head] = (jnew < 0) ? 0 :
colind[jnew];
548 casadi_int p2 = (jnew < 0) ? 0 :
colind[jnew+1];
551 for (casadi_int p = pstack[head]; p< p2; ++p) {
554 casadi_int i =
row[p];
557 if (marked[i]) continue ;
585 std::vector<casadi_int>& r)
const {
591 std::vector<casadi_int> tmp;
595 std::vector<casadi_int> xi(2*
size2()+1);
596 std::vector<casadi_int>& Blk = xi;
598 std::vector<casadi_int> pstack(
size2()+1);
603 std::vector<bool> marked(
size2(),
false);
605 casadi_int top =
size2();
608 for (casadi_int i = 0; i<
size2(); ++i) {
610 top =
dfs(i, top, xi, pstack, tmp, marked);
614 std::fill(marked.begin(), marked.end(),
false);
617 casadi_int nb =
size2();
620 for (casadi_int k=0 ; k <
size2() ; ++k) {
622 casadi_int i = xi[k];
625 if (marked[i])
continue;
629 top = AT.
dfs(i, top, p, pstack, tmp, marked);
634 for (casadi_int k = nb ; k <=
size2() ; ++k)
641 for (casadi_int b = 0 ; b < nb ; b++) {
642 for (casadi_int k = r[b]; k<r[b+1] ; ++k)
647 for (casadi_int i=0; i<
size2(); ++i) {
653 for (casadi_int i=nb; i>0; --i) {
667 casadi_assert(
is_symmetric(),
"AMD requires a symmetric matrix");
669 casadi_int n=
size2();
674 casadi_int col_begin, col_end=0;
675 for (casadi_int c=0; c<n; ++c) {
680 for (casadi_int k=col_begin; k<col_end; ++k) {
688 casadi_int dense =
static_cast<casadi_int
>(10*sqrt(
static_cast<double>(n)));
689 dense = std::max(casadi_int(16), dense);
690 dense = std::min(n-2, dense);
692 std::vector<casadi_int>
P(n+1);
694 std::vector<casadi_int> len(n+1), nv(n+1), next(n+1), head(n+1), elen(n+1), degree(n+1),
699 casadi_int mindeg = 0;
701 casadi_int lemax = 0;
707 #define FLIP(i) (-(i)-2)
711 for (casadi_int k = 0; k<n; ++k) len[k] =
colind[k+1] -
colind[k];
713 casadi_int nzmax =
row.size();
714 for (casadi_int i=0; i<=n; ++i) {
729 for (casadi_int i = 0; i < n; ++i) {
736 }
else if (d > dense) {
743 if (head[d] != -1)
P[head[d]] = i;
751 for (k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {}
752 if (next[k] != -1)
P[next[k]] = -1;
753 head[mindeg] = next[k];
754 casadi_int elenk = elen[k];
755 casadi_int nvk = nv[k];
758 if (elenk > 0 &&
nnz + mindeg >= nzmax) {
759 for (casadi_int j = 0; j < n; j++) {
768 for (q = 0, p = 0; p <
nnz; ) {
774 for (casadi_int k3 = 0; k3 < len[j]-1; k3++)
row[q++] =
row[p++];
783 casadi_int pk1 = (elenk == 0) ? p :
nnz;
784 casadi_int pk2 = pk1;
785 casadi_int e, pj, ln;
786 for (casadi_int k1 = 1; k1 <= elenk + 1; k1++) {
796 for (casadi_int k2 = 1; k2 <= ln; k2++) {
797 casadi_int i =
row[pj++];
800 if (nvi <= 0)
continue;
804 if (next[i] != -1)
P[next[i]] =
P[i];
806 next[
P[i]] = next[i];
808 head[degree[i]] = next[i];
816 if (elenk != 0)
nnz = pk2;
823 for (casadi_int pk = pk1; pk < pk2; pk++) {
824 casadi_int i =
row[pk];
827 if (eln <= 0)
continue;
828 casadi_int nvi = -nv[i];
829 casadi_int wnvi = mark - nvi;
834 }
else if (w[e] != 0) {
835 w[e] = degree[e] + wnvi;
840 for (casadi_int pk = pk1; pk < pk2; pk++) {
841 casadi_int i =
row[pk];
842 casadi_int p1 =
colind[i];
843 casadi_int p2 = p1 + elen[i] - 1;
845 for (h = 0, d = 0, p = p1; p <= p2; p++) {
848 casadi_int dext = w[e] - mark;
859 elen[i] = pn - p1 + 1;
861 casadi_int p4 = p1 + len[i];
862 for (p = p2 + 1; p < p4; p++) {
863 casadi_int j =
row[p];
866 if (nvj <= 0)
continue;
873 casadi_int nvi = -nv[i];
880 degree[i] = std::min(degree[i], d);
884 len[i] = pn - p1 + 1;
892 lemax = std::max(lemax, dk);
895 for (casadi_int pk = pk1; pk < pk2; pk++) {
896 casadi_int i =
row[pk];
897 if (nv[i] >= 0)
continue;
901 for (; i != -1 && next[i] != -1; i = next[i], mark++) {
903 casadi_int eln = elen[i];
905 casadi_int jlast = i;
906 for (casadi_int j = next[i]; j != -1; ) {
907 casadi_int ok = (len[j] == ln) && (elen[j] == eln);
908 for (p =
colind[j] + 1; ok && p <=
colind[j] + ln - 1; p++) {
909 if (w[
row[p]] != mark) ok = 0;
927 for (p = pk1, pk = pk1; pk < pk2; pk++) {
928 casadi_int i =
row[pk];
931 if (nvi <= 0)
continue;
933 d = degree[i] + dk - nvi;
934 d = std::min(d, n - nel - nvi);
935 if (head[d] != -1)
P[head[d]] = i;
939 mindeg = std::min(mindeg, d);
949 if (elenk != 0)
nnz = p;
952 for (casadi_int i = 0; i < n; i++)
colind[i] = FLIP(
colind[i]);
953 for (casadi_int j = 0; j <= n; j++) head[j] = -1;
954 for (casadi_int j = n; j >= 0; j--) {
955 if (nv[j] > 0)
continue;
956 next[j] = head[
colind[j]];
959 for (casadi_int e = n; e >= 0; e--) {
960 if (nv[e] <= 0)
continue;
962 next[e] = head[
colind[e]];
966 for (casadi_int k = 0, i = 0; i <= n; i++) {
976 std::vector<casadi_int>& queue,
const std::vector<casadi_int>& imatch,
977 const std::vector<casadi_int>& jmatch, casadi_int mark)
const {
983 casadi_int head = 0, tail = 0, j, i, p, j2 ;
986 for (j=0; j<n; ++j) {
988 if (imatch[j] >= 0)
continue;
998 if (tail == 0)
return;
1001 const casadi_int *C_row, *C_colind;
1007 C_row = trans.
row();
1008 C_colind = trans.
colind();
1012 while (head < tail) {
1016 for (p = C_colind[j] ; p < C_colind[j+1] ; p++) {
1020 if (wi[i] >= 0)
continue;
1029 if (wj[j2] >= 0)
continue;
1041 const std::vector<casadi_int>& imatch, std::vector<casadi_int>& p,
1042 std::vector<casadi_int>& q, std::vector<casadi_int>& cc, std::vector<casadi_int>& rr,
1043 casadi_int set, casadi_int mark) {
1049 casadi_int kc = cc[set];
1050 casadi_int kr = rr[set-1] ;
1051 for (casadi_int j=0; j<n; ++j) {
1053 if (wj[j] != mark)
continue;
1055 p[kr++] = imatch[j] ;
1064 std::vector<casadi_int>& p, std::vector<casadi_int>& rr, casadi_int set) {
1070 casadi_int i, kr = rr[set] ;
1084 std::vector<casadi_int> &rr = *
static_cast<std::vector<casadi_int> *
>(other);
1085 return (i >= rr[1] && i < rr[2]) ;
1089 std::vector<casadi_int>& w, casadi_int *js, casadi_int *is, casadi_int *ps)
const {
1096 const casadi_int*
row = this->
row();
1098 casadi_int found = 0, p, i = -1, head = 0, j ;
1114 for (p = cheap[j] ; p <
colind[j+1] && !found; ++p) {
1116 found = (jmatch[i] == -1) ;
1134 for (p = ps[head]; p<
colind[j+1]; ++p) {
1140 if (w[jmatch[i]] == k)
continue;
1149 js[++head] = jmatch[i];
1154 if (p ==
colind[j+1]) head--;
1158 for (p = head; p>=0; --p)
1159 jmatch[is[p]] = js[p];
1163 Sparsity& trans, casadi_int seed)
const {
1170 const casadi_int*
row = this->
row();
1172 casadi_int n2 = 0, m2 = 0;
1175 jmatch.resize(
size1());
1176 imatch.resize(
size2());
1181 for (casadi_int j=0; j<
size2(); ++j) {
1194 for (i=0; i<k; ++i) jmatch[i] = i;
1195 for (; i<
size1(); ++i) jmatch[i] = -1;
1198 for (j=0; j<k; ++j) imatch[j] = j;
1199 for (; j<
size2(); ++j) imatch[j] = -1;
1202 for (casadi_int i=0; i<
size1(); ++i) m2 += w[i];
1205 if (m2 < n2 && trans.
is_null())
1209 const SparsityInternal*
C = m2 < n2 ? static_cast<const SparsityInternal*>(trans.
get()) :
this;
1210 const casadi_int* C_colind =
C->colind();
1212 std::vector<casadi_int>& Cjmatch = m2 < n2 ? imatch : jmatch;
1213 std::vector<casadi_int>& Cimatch = m2 < n2 ? jmatch : imatch;
1216 w.resize(5 *
C->size2());
1218 casadi_int *cheap = &w.front() +
C->size2();
1219 casadi_int *js = &w.front() + 2*
C->size2();
1220 casadi_int *is = &w.front() + 3*
C->size2();
1221 casadi_int *ps = &w.front() + 4*
C->size2();
1224 for (casadi_int j=0; j<
C->size2(); ++j)
1225 cheap[j] = C_colind[j];
1228 for (casadi_int j=0; j<
C->size2(); ++j)
1232 for (casadi_int i=0; i<
C->size1(); ++i)
1236 std::vector<casadi_int> q =
randperm(
C->size2(), seed);
1239 for (k=0; k<
C->size2(); ++k) {
1240 C->augment(!q.empty() ? q[k]: k, Cjmatch, cheap, w, js, is, ps);
1244 for (casadi_int j=0; j<
C->size2(); ++j)
1247 for (casadi_int i = 0; i<
C->size1(); ++i)
1248 if (Cjmatch[i] >= 0)
1249 Cimatch[Cjmatch[i]] = i;
1253 std::vector<casadi_int>& colperm,
1254 std::vector<casadi_int>& rowblock,
1255 std::vector<casadi_int>& colblock,
1256 std::vector<casadi_int>& coarse_rowblock,
1257 std::vector<casadi_int>& coarse_colblock)
const {
1263 casadi_int seed = 0;
1274 colperm.resize(
size2());
1277 rowblock.resize(
size1()+6);
1280 colblock.resize(
size2()+6);
1283 coarse_rowblock.resize(5);
1284 std::fill(coarse_rowblock.begin(), coarse_rowblock.end(), 0);
1287 coarse_colblock.resize(5);
1288 std::fill(coarse_colblock.begin(), coarse_colblock.end(), 0);
1291 std::vector<casadi_int> imatch, jmatch;
1292 maxtrans(imatch, jmatch, trans, seed);
1297 std::vector<casadi_int>& wi = rowblock;
1298 std::vector<casadi_int>& wj = colblock;
1301 for (casadi_int j=0; j<
size2(); ++j)
1305 for (casadi_int i=0; i<
size1(); ++i)
1309 bfs(
size2(), wi, wj, colperm, imatch, jmatch, 1);
1312 bfs(
size1(), wj, wi, rowperm, jmatch, imatch, 3);
1318 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 1, 1);
1321 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 2, -1);
1324 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 3, 3);
1334 std::vector<casadi_int> colind_C, row_C;
1335 permute(pinv, colperm, 0, colind_C, row_C);
1338 casadi_int nc = coarse_colblock[3] - coarse_colblock[2];
1339 if (coarse_colblock[2] > 0) {
1340 for (casadi_int j = coarse_colblock[2]; j <= coarse_colblock[3]; ++j)
1341 colind_C[j-coarse_colblock[2]] = colind_C[j];
1343 casadi_int ncol_C = nc;
1345 colind_C.resize(nc+1);
1347 if (coarse_rowblock[2] - coarse_rowblock[1] <
size1()) {
1349 casadi_int cnz = colind_C[nc];
1350 if (coarse_rowblock[1] > 0)
1351 for (casadi_int k=0; k<cnz; ++k)
1352 row_C[k] -= coarse_rowblock[1];
1354 row_C.resize(colind_C.back());
1355 casadi_int nrow_C = nc ;
1356 Sparsity C(nrow_C, ncol_C, colind_C, row_C,
true);
1359 std::vector<casadi_int> scc_p, scc_r;
1360 casadi_int scc_nb =
C.scc(scc_p, scc_r);
1365 std::vector<casadi_int> ps = scc_p;
1368 std::vector<casadi_int> rs = scc_r;
1371 casadi_int nb1 = scc_nb;
1373 for (casadi_int k=0; k<nc; ++k)
1374 wj[k] = colperm[ps[k] + coarse_colblock[2]];
1376 for (casadi_int k=0; k<nc; ++k)
1377 colperm[k + coarse_colblock[2]] = wj[k];
1379 for (casadi_int k=0; k<nc; ++k)
1380 wi[k] = rowperm[ps[k] + coarse_rowblock[1]];
1382 for (casadi_int k=0; k<nc; ++k)
1383 rowperm[k + coarse_rowblock[1]] = wi[k];
1387 rowblock[0] = colblock[0] = 0;
1390 if (coarse_colblock[2] > 0)
1394 for (casadi_int k=0; k<nb1; ++k) {
1396 rowblock[nb2] = rs[k] + coarse_rowblock[1];
1397 colblock[nb2] = rs[k] + coarse_colblock[2] ;
1401 if (coarse_rowblock[2] <
size1()) {
1403 rowblock[nb2] = coarse_rowblock[2];
1404 colblock[nb2] = coarse_colblock[3];
1408 rowblock[nb2] =
size1();
1409 colblock[nb2] =
size2() ;
1412 rowblock.resize(nb2+1);
1413 colblock.resize(nb2+1);
1423 std::vector<casadi_int> p;
1426 if (seed==0)
return p;
1431 for (casadi_int k=0; k<n; ++k)
1435 if (seed==-1)
return p;
1439 unsigned int seedu =
static_cast<unsigned int>(seed);
1442 for (casadi_int k=0; k<n; ++k) {
1445 casadi_int j = k + (rand() % (n-k));
1447 casadi_int j = k + (rand_r(&seedu) % (n-k));
1450 casadi_int t = p[j];
1459 std::vector<casadi_int> pinv(p.size());
1460 for (casadi_int k=0; k<p.size(); ++k) pinv[p[k]] = k;
1465 const std::vector<casadi_int>& q, casadi_int values)
const {
1466 std::vector<casadi_int> colind_C, row_C;
1467 permute(pinv, q, values, colind_C, row_C);
1472 const std::vector<casadi_int>& q, casadi_int values,
1473 std::vector<casadi_int>& colind_C,
1474 std::vector<casadi_int>& row_C)
const {
1481 const casadi_int*
row = this->
row();
1484 colind_C.resize(
size2()+1);
1487 row_C.resize(
nnz());
1489 for (casadi_int k = 0; k<
size2(); ++k) {
1493 casadi_int j = !q.empty() ? (q[k]) : k;
1496 row_C[nz++] = !pinv.empty() ? (pinv[
row[t]]) :
row[t] ;
1501 colind_C[
size2()] = nz;
1505 void *other, casadi_int nrow, casadi_int ncol,
1506 std::vector<casadi_int>& colind, std::vector<casadi_int>& row) {
1514 for (casadi_int j = 0; j<ncol; ++j) {
1516 casadi_int p =
colind[j];
1520 for ( ; p <
colind[j+1] ; ++p) {
1521 if (fkeep(
row[p], j, 1, other)) {
1534 casadi_int *w, casadi_int n) {
1540 if (mark < 2 || (mark + lemax < 0)) {
1541 for (casadi_int k = 0; k<n; ++k)
if (w[k] != 0) w[k] = 1;
1558 casadi_int mark, casadi_int* Ci, casadi_int nz)
const {
1565 const casadi_int *Ap =
colind();
1566 const casadi_int *Ai =
row();
1568 for (p = Ap[j]; p<Ap[j+1]; ++p) {
1590 casadi_assert(
size2() == B.
size1(),
"Dimension mismatch.");
1591 casadi_int m =
size1();
1592 casadi_int anz =
nnz();
1593 casadi_int n = B.
size2();
1594 const casadi_int* Bp = B.
colind();
1595 const casadi_int* Bi = B.
row();
1596 casadi_int bnz = Bp[n];
1599 std::vector<casadi_int> w(m);
1602 std::vector<casadi_int> C_colind(n+1, 0), C_row;
1604 C_colind.resize(anz + bnz);
1606 casadi_int* Cp = &C_colind.front();
1607 for (casadi_int j=0; j<n; ++j) {
1608 if (nz+m > C_row.size()) {
1609 C_row.resize(2*(C_row.size())+m);
1614 for (casadi_int p = Bp[j] ; p<Bp[j+1] ; ++p) {
1615 nz =
scatter(Bi[p], w, j+1, &C_row.front(), nz);
1624 return Sparsity(m, n, C_colind, C_row);
1628 casadi_int nrow = this->
size1();
1629 casadi_int ncol = this->
size2();
1631 const casadi_int*
row = this->
row();
1638 casadi_int n = nrow * ncol;
1639 std::vector<casadi_int> ret_colind(n+1, 0), ret_row;
1643 for (casadi_int cc=0; cc<ncol; ++cc) {
1645 casadi_int rr=
row[k];
1646 casadi_int el=rr+nrow*cc;
1647 while (ret_i<=el) ret_colind[ret_i++]=ret_row.size();
1648 ret_row.push_back(el);
1649 mapping.push_back(k);
1652 while (ret_i<=n) ret_colind[ret_i++]=ret_row.size();
1655 return Sparsity(n, n, ret_colind, ret_row);
1659 casadi_int n = std::min(nrow, ncol);
1660 std::vector<casadi_int> ret_row, ret_colind(2, 0);
1663 for (casadi_int cc=0; cc<n; ++cc) {
1664 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1666 ret_row.push_back(
row[el]);
1668 mapping.push_back(el);
1674 return Sparsity(n, 1, ret_colind, ret_row);
1679 casadi_int nrow = this->
size1();
1680 casadi_int ncol = this->
size2();
1682 const casadi_int*
row = this->
row();
1683 for (casadi_int c=0; c<ncol && c<nrow; ++c) {
1685 if (
row[k]==c)
return true;
1692 casadi_int nrow = this->
size1();
1693 casadi_int ncol = this->
size2();
1695 const casadi_int*
row = this->
row();
1697 std::vector<casadi_int> ret_colind(ncol+1), ret_row;
1699 ret_row.reserve(
nnz());
1700 for (casadi_int c=0; c<ncol; ++c) {
1703 ret_row.push_back(
row[k]);
1706 ret_colind[c+1] = ret_row.size();
1708 return Sparsity(nrow, ncol, ret_colind, ret_row);
1713 if (with_nz) ret +=
"," +
str(
nnz()) +
"nz";
1719 std::stringstream ss;
1721 ss <<
"nonzero index " << k+start_index <<
" ";
1723 casadi_int r =
row()[k];
1725 ss <<
"(row " << r+start_index <<
", col " << c+start_index <<
")";
1732 casadi_int d1 =
size1();
1733 casadi_int d2 = y.
size2();
1752 if (y.
is_diag())
return shared_from_this<Sparsity>();
1755 const casadi_int* x_row =
row();
1756 const casadi_int* x_colind =
colind();
1757 const casadi_int* y_row = y.
row();
1758 const casadi_int* y_colind = y.
colind();
1761 std::vector<casadi_int>
row, col;
1764 std::vector<casadi_int> tmp(d1, -1);
1767 for (casadi_int cc=0; cc<d2; ++cc) {
1768 for (casadi_int kk=y_colind[cc]; kk<y_colind[cc+1]; ++kk) {
1769 casadi_int rr = y_row[kk];
1772 for (casadi_int kk1=x_colind[rr]; kk1<x_colind[rr+1]; ++kk1) {
1773 casadi_int rr1 = x_row[kk1];
1790 return size2()==1 &&
size1()==1 && (!scalar_and_dense ||
nnz()==1);
1815 const casadi_int*
row = this->
row();
1821 if (
nnz() !=
size2())
return false;
1824 for (casadi_int i=0; i<
nnz(); ++i) {
1830 for (casadi_int i=0; i<
size2(); ++i) {
1858 if (sum2(
sp).
nnz()!=
nnz())
return false;
1859 if (sum1(
sp).
nnz()!=
nnz())
return false;
1870 if (sum2(
sp).
nnz()!=
nnz())
return false;
1871 if (sum1(
sp).
nnz()!=
nnz())
return false;
1882 if (sum2(
sp).
nnz()!=
nnz())
return false;
1883 if (sum1(
sp).
nnz()!=
nnz())
return false;
1893 const casadi_int*
row = this->
row();
1895 for (casadi_int cc=0; cc<
size2(); ++cc) {
1896 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1897 if (cc<
row[el] || (!strictly && cc==
row[el]))
nnz++;
1905 const casadi_int*
row = this->
row();
1907 for (casadi_int cc=0; cc<
size2(); ++cc) {
1908 for (casadi_int el =
colind[cc]; el <
colind[cc+1]; ++el) {
1917 const casadi_int*
row = this->
row();
1919 for (casadi_int cc=0; cc<
size2(); ++cc) {
1920 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1921 if (cc>
row[el] || (!strictly && cc==
row[el]))
nnz++;
1928 return std::pair<casadi_int, casadi_int>(
size1(),
size2());
1932 std::vector<casadi_int>& mapping)
const {
1936 return shared_from_this<Sparsity>();
1938 casadi_assert_in_range(rr, -
numel()+ind1,
numel()+ind1);
1942 std::vector<casadi_int> rr_mod = rr;
1943 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
1945 if (*i<0) *i +=
numel();
1947 return _erase(rr_mod,
false, mapping);
1952 std::vector<casadi_int> rr_sorted = rr;
1953 std::sort(rr_sorted.begin(), rr_sorted.end());
1954 return _erase(rr_sorted,
false, mapping);
1961 if (
numel()==0)
return shared_from_this<Sparsity>();
1964 mapping.reserve(
nnz());
1970 std::vector<casadi_int>::const_iterator next_rr = rr.begin();
1976 casadi_int k_first, k_last=0;
1979 for (casadi_int j=0; j<
size2(); ++j) {
1982 k_last = ret_colind[j+1];
1985 for (casadi_int k=k_first; k<k_last; ++k) {
1987 casadi_int i=ret_row[k];
1990 casadi_int el = i+j*
size1();
1993 while (next_rr!=rr.end() && *next_rr<el) next_rr++;
1996 if (next_rr!=rr.end() && *next_rr==el) {
2002 mapping.push_back(k);
2009 ret_colind[j+1] = nz;
2019 const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
2020 bool ind1, std::vector<casadi_int>& mapping)
const {
2021 casadi_assert_in_range(rr, -
size1()+ind1,
size1()+ind1);
2022 casadi_assert_in_range(cc, -
size2()+ind1,
size2()+ind1);
2028 std::vector<casadi_int> rr_mod = rr;
2029 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2031 if (*i<0) *i +=
size1();
2033 std::sort(rr_mod.begin(), rr_mod.end());
2036 std::vector<casadi_int> cc_mod = cc;
2037 for (std::vector<casadi_int>::iterator i=cc_mod.begin(); i!=cc_mod.end(); ++i) {
2039 if (*i<0) *i +=
size2();
2041 std::sort(cc_mod.begin(), cc_mod.end());
2044 return _erase(rr_mod, cc_mod,
false, mapping);
2051 if (
numel()==0)
return shared_from_this<Sparsity>();
2054 mapping.reserve(
nnz());
2063 std::vector<casadi_int>::const_iterator ie = cc.begin();
2066 casadi_int el_first=0, el_last=0;
2069 for (casadi_int i=0; i<
size2(); ++i) {
2072 el_last = ret_colind[i+1];
2075 bool deletable_col = ie!=cc.end() && *ie==i;
2076 if (deletable_col) {
2080 std::vector<casadi_int>::const_iterator je = rr.begin();
2083 for (casadi_int el=el_first; el<el_last; ++el) {
2085 casadi_int j=ret_row[el];
2088 for (; je!=rr.end() && *je<j; ++je) {}
2091 if (je!=rr.end() && *je==j) {
2097 mapping.push_back(el);
2104 for (casadi_int el=el_first; el<el_last; ++el) {
2106 casadi_int j=ret_row[el];
2109 mapping.push_back(el);
2127 const std::vector<casadi_int>& cc)
const {
2128 casadi_assert_bounded(rr,
size1());
2129 casadi_assert_bounded(cc,
size2());
2131 std::vector<casadi_int> rr_sorted;
2132 std::vector<casadi_int> rr_sorted_index;
2134 sort(rr, rr_sorted, rr_sorted_index);
2136 std::vector<casadi_int> ret(cc.size()*rr.size());
2138 casadi_int stride = rr.size();
2140 const casadi_int*
row = this->
row();
2142 for (casadi_int i=0;i<cc.size();++i) {
2143 casadi_int it = cc[i];
2144 casadi_int el=
colind[it];
2145 for (casadi_int j=0;j<rr_sorted.size();++j) {
2146 casadi_int jt=rr_sorted[j];
2148 for (; el<
colind[it+1] &&
row[el]<jt; ++el) {}
2151 ret[i*stride+rr_sorted_index[j]] = el;
2153 ret[i*stride+rr_sorted_index[j]] = -1;
2161 std::vector<casadi_int>& mapping,
bool ind1)
const {
2162 casadi_assert_dev(rr.size()==
sp.nnz());
2165 casadi_assert_in_range(rr, -
numel()+ind1,
numel()+ind1);
2169 std::vector<casadi_int> rr_mod = rr;
2170 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2171 casadi_assert(!(ind1 && (*i)<=0),
2172 "Matlab is 1-based, but requested index " +
str(*i) +
". "
2173 "Note that negative slices are disabled in the Matlab interface. "
2174 "Possibly you may want to use 'end'.");
2176 if (*i<0) *i +=
numel();
2178 return sub(rr_mod,
sp, mapping,
false);
2182 mapping.resize(rr.size());
2183 std::copy(rr.begin(), rr.end(), mapping.begin());
2187 std::vector<casadi_int> ret_colind(
sp.size2()+1), ret_row;
2189 const casadi_int* sp_colind =
sp.colind();
2190 const casadi_int* sp_row =
sp.row();
2191 for (casadi_int c=0; c<
sp.size2(); ++c) {
2192 for (casadi_int el=sp_colind[c]; el<sp_colind[c+1]; ++el) {
2193 if (mapping[el]>=0) {
2194 mapping[ret_row.size()] = mapping[el];
2195 ret_row.push_back(sp_row[el]);
2198 ret_colind[c+1] = ret_row.size();
2200 mapping.resize(ret_row.size());
2201 return Sparsity(
sp.size1(),
sp.size2(), ret_colind, ret_row);
2205 const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
2206 std::vector<casadi_int>& mapping,
bool ind1)
const {
2207 casadi_assert_in_range(rr, -
size1()+ind1,
size1()+ind1);
2208 casadi_assert_in_range(cc, -
size2()+ind1,
size2()+ind1);
2211 std::vector<casadi_int> tmp = rr;
2212 for (std::vector<casadi_int>::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
2214 if (*i<0) *i +=
size1();
2216 std::vector<casadi_int> rr_sorted, rr_sorted_index;
2217 sort(tmp, rr_sorted, rr_sorted_index,
false);
2221 for (std::vector<casadi_int>::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
2223 if (*i<0) *i +=
size2();
2225 std::vector<casadi_int> cc_sorted, cc_sorted_index;
2226 sort(tmp, cc_sorted, cc_sorted_index,
false);
2227 std::vector<casadi_int> columns, rows;
2230 bool with_lookup =
static_cast<double>(cc.size())*
static_cast<double>(rr.size()) >
nnz();
2231 std::vector<casadi_int> rrlookup;
2249 const casadi_int*
row = this->
row();
2250 for (casadi_int i=0; i<cc.size(); ++i) {
2251 casadi_int it = cc_sorted[i];
2254 for (casadi_int el=
colind[it]; el<
colind[it+1]; ++el) {
2255 casadi_int j =
row[el];
2256 casadi_int ji = rrlookup[j];
2258 casadi_int jv = rr_sorted[ji];
2259 while (ji>=0 && jv == rr_sorted[ji--])
nnz++;
2264 casadi_int el =
colind[it];
2265 for (casadi_int j=0; j<rr_sorted.size(); ++j) {
2266 casadi_int jt=rr_sorted[j];
2268 while (el<
colind[it+1] &&
row[el]<jt) el++;
2275 mapping.resize(
nnz);
2276 columns.resize(
nnz);
2281 for (casadi_int i=0; i<cc.size(); ++i) {
2282 casadi_int it = cc_sorted[i];
2285 for (casadi_int el=
colind[it]; el<
colind[it+1]; ++el) {
2286 casadi_int jt =
row[el];
2287 casadi_int ji = rrlookup[jt];
2289 casadi_int jv = rr_sorted[ji];
2290 while (ji>=0 && jv == rr_sorted[ji]) {
2291 rows[k] = rr_sorted_index[ji];
2292 columns[k] = cc_sorted_index[i];
2301 casadi_int el =
colind[it];
2302 for (casadi_int j=0; j<rr_sorted.size(); ++j) {
2303 casadi_int jt=rr_sorted[j];
2305 while (el<
colind[it+1] &&
row[el]<jt) el++;
2308 rows[k] = rr_sorted_index[j];
2309 columns[k] = cc_sorted_index[i];
2317 std::vector<casadi_int> sp_mapping;
2318 std::vector<casadi_int> mapping_ = mapping;
2321 for (casadi_int i=0; i<mapping.size(); ++i)
2322 mapping[i] = mapping_[sp_mapping[i]];
2329 bool function0_is_zero)
const {
2330 static std::vector<unsigned char> mapping;
2331 return combineGen1<false>(y, f0x_is_zero, function0_is_zero, mapping);
2335 bool function0_is_zero,
2336 std::vector<unsigned char>& mapping)
const {
2337 return combineGen1<true>(y, f0x_is_zero, function0_is_zero, mapping);
2342 std::vector<unsigned char> mapping;
2343 shared_from_this<Sparsity>().unite(rhs, mapping);
2344 for (
auto e : mapping) {
2345 if (e==1)
return false;
2350 template<
bool with_mapping>
2352 bool function0_is_zero,
2353 std::vector<unsigned char>& mapping)
const {
2359 std::fill(mapping.begin(), mapping.end(), 1 | 2);
2365 if (function0_is_zero) {
2366 return combineGen<with_mapping, true, true>(y, mapping);
2368 return combineGen<with_mapping, true, false>(y, mapping);
2370 }
else if (function0_is_zero) {
2371 return combineGen<with_mapping, false, true>(y, mapping);
2373 return combineGen<with_mapping, false, false>(y, mapping);
2377 template<
bool with_mapping,
bool f0x_is_zero,
bool function0_is_zero>
2379 std::vector<unsigned char>& mapping)
const {
2383 "Dimension mismatch : " +
str(
size()) +
" versus " +
str(y.
size()) +
".");
2386 const casadi_int* y_colind = y.
colind();
2387 const casadi_int* y_row = y.
row();
2389 const casadi_int*
row = this->
row();
2392 std::vector<casadi_int> ret_colind(
size2()+1, 0);
2393 std::vector<casadi_int> ret_row;
2396 if (with_mapping) mapping.clear();
2399 for (casadi_int i=0; i<
size2(); ++i) {
2401 casadi_int el1 =
colind[i];
2402 casadi_int el2 = y_colind[i];
2405 casadi_int el1_last =
colind[i+1];
2406 casadi_int el2_last = y_colind[i+1];
2409 while (el1<el1_last || el2<el2_last) {
2411 casadi_int row1 = el1<el1_last ?
row[el1] :
size1();
2412 casadi_int row2 = el2<el2_last ? y_row[el2] :
size1();
2416 ret_row.push_back(row1);
2417 if (with_mapping) mapping.push_back( 1 | 2);
2419 }
else if (row1<row2) {
2420 if (!function0_is_zero) {
2421 ret_row.push_back(row1);
2422 if (with_mapping) mapping.push_back(1);
2424 if (with_mapping) mapping.push_back(1 | 4);
2429 ret_row.push_back(row2);
2430 if (with_mapping) mapping.push_back(2);
2432 if (with_mapping) mapping.push_back(2 | 4);
2439 ret_colind[i+1] = ret_row.size();
2448 if (n==1 &&
is_equal(y))
return true;
2453 const casadi_int*
row = this->
row();
2454 casadi_int y_size1 = y.
size1();
2455 casadi_int y_size2 = y.
size2();
2456 const casadi_int* y_colind = y.
colind();
2457 const casadi_int* y_row = y.
row();
2459 if (
size1!=y_size1 ||
size2!=n*y_size2)
return false;
2462 if (
nnz!=n*y_nnz)
return false;
2464 if (y_nnz==y_size1*y_size2)
return true;
2466 casadi_int offset = 0;
2470 for (
int i=0; i<n; ++i) {
2472 for (
int c=0; c<y_size2; ++c)
if (y_colind[c+1]+offset != *
colind++)
return false;
2474 for (
int k=0; k<y_nnz; ++k)
if (y_row[k] != *
row++)
return false;
2484 if (
this == y.
get())
return true;
2496 std::vector<casadi_int> row_ret;
2497 std::vector<casadi_int> colind_ret=
get_colind();
2499 const casadi_int*
row = this->
row();
2502 for (casadi_int i=0;i<
size2();++i) {
2515 row_ret.push_back(j);
2521 while (j <
size1()) {
2522 row_ret.push_back(j);
2533 const std::vector<casadi_int>& y_colind,
2534 const std::vector<casadi_int>& y_row)
const {
2535 casadi_assert_dev(y_colind.size()==y_ncol+1);
2536 casadi_assert_dev(y_row.size()==y_colind.back());
2541 const casadi_int* y_colind,
const casadi_int* y_row)
const {
2543 const casadi_int*
row = this->
row();
2546 casadi_int nz = y_colind[y_ncol];
2549 if (
nnz()!=nz ||
size2()!=y_ncol ||
size1()!=y_nrow)
return false;
2558 if (!std::equal(
row,
row+nz, y_row))
return false;
2565 casadi_assert(
size2() == 1 &&
sp.size2() == 1,
2566 "_appendVector(sp): Both arguments must be vectors but got "
2567 +
str(
size2()) +
" columns for lhs, and " +
str(
sp.size2()) +
" columns for rhs.");
2570 casadi_int sz =
nnz();
2573 std::vector<casadi_int> new_row =
get_row();
2574 const casadi_int* sp_row =
sp.row();
2575 new_row.resize(sz +
sp.nnz());
2576 for (casadi_int i=sz; i<new_row.size(); ++i)
2577 new_row[i] = sp_row[i-sz] +
size1();
2580 std::vector<casadi_int> new_colind(2, 0);
2581 new_colind[1] = new_row.size();
2586 casadi_assert(
size1()==
sp.size1(),
2587 "_appendColumns(sp): row sizes must match but got " +
str(
size1())
2588 +
" for lhs, and " +
str(
sp.size1()) +
" for rhs.");
2591 std::vector<casadi_int> new_row =
get_row();
2592 const casadi_int* sp_row =
sp.row();
2593 new_row.insert(new_row.end(), sp_row, sp_row+
sp.nnz());
2596 std::vector<casadi_int> new_colind =
get_colind();
2597 const casadi_int* sp_colind =
sp.colind();
2598 new_colind.resize(
size2() +
sp.size2() + 1);
2599 for (casadi_int i =
size2()+1; i<new_colind.size(); ++i)
2600 new_colind[i] = sp_colind[i-
size2()] +
nnz();
2607 casadi_assert_in_range(cc, -ncol+ind1, ncol+ind1);
2611 std::vector<casadi_int> cc_mod = cc;
2612 for (std::vector<casadi_int>::iterator i=cc_mod.begin(); i!=cc_mod.end(); ++i) {
2614 if (*i<0) *i += ncol;
2620 std::vector<casadi_int> new_colind =
get_colind();
2621 new_colind.resize(ncol+1,
nnz());
2623 casadi_int ik=cc.back();
2624 casadi_int nz=
nnz();
2625 for (casadi_int i=cc.size()-1; i>=0; --i) {
2627 for (; ik>cc[i]; --ik) {
2628 new_colind[ik] = nz;
2635 new_colind[cc[i]] = nz;
2639 for (; ik>=0; --ik) {
2646 const std::vector<casadi_int>& rr,
bool ind1)
const {
2647 casadi_assert_in_range(rr, -nrow+ind1, nrow+ind1);
2651 std::vector<casadi_int> rr_mod = rr;
2652 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2654 if (*i<0) *i += nrow;
2660 casadi_assert_dev(rr.size() ==
size1());
2663 std::vector<casadi_int> new_row =
get_row();
2664 for (casadi_int k=0; k<
nnz(); ++k) {
2665 new_row[k] = rr[new_row[k]];
2672 const casadi_int*
row = this->
row();
2673 mapping.resize(
nnz());
2674 for (casadi_int i=0; i<
size2(); ++i) {
2676 casadi_int j =
row[el];
2677 mapping[el] = j + i*
size1();
2686 if (rr<0) rr +=
size1();
2687 if (cc<0) cc +=
size2();
2689 const casadi_int*
row = this->
row();
2692 casadi_assert(rr>=0 && rr<
size1(),
"Row index " +
str(rr)
2693 +
" out of bounds [0, " +
str(
size1()) +
")");
2694 casadi_assert(cc>=0 && cc<
size2(),
"Column index " +
str(cc)
2695 +
" out of bounds [0, " +
str(
size2()) +
")");
2704 for (casadi_int ind=
colind[cc]; ind<
colind[cc+1]; ++ind) {
2705 if (
row[ind] == rr) {
2707 }
else if (
row[ind] > rr) {
2716 if (nrow<0 && ncol>0) {
2718 }
else if (nrow>0 && ncol<0) {
2722 casadi_assert(
numel() == nrow*ncol,
2723 "reshape: number of elements must remain the same. Old shape is "
2724 +
dim() +
". New shape is " +
str(nrow) +
"x" +
str(ncol)
2725 +
"=" +
str(nrow*ncol) +
".");
2726 std::vector<casadi_int> ret_col(
nnz());
2727 std::vector<casadi_int> ret_row(
nnz());
2729 const casadi_int*
row = this->
row();
2730 for (casadi_int i=0; i<
size2(); ++i) {
2732 casadi_int j =
row[el];
2735 casadi_int k_ret = j+i*
size1();
2738 casadi_int i_ret = k_ret/nrow;
2739 casadi_int j_ret = k_ret%nrow;
2740 ret_col[el] = i_ret;
2741 ret_row[el] = j_ret;
2749 std::vector<casadi_int> row_new, colind_new(ncol+1, 0);
2751 const casadi_int*
row = this->
row();
2755 for (i=0; i<
size2() && i<ncol; ++i) {
2757 colind_new[i] = row_new.size();
2761 row_new.push_back(
row[el]);
2766 for (; i<ncol+1; ++i) {
2767 colind_new[i] = row_new.size();
2770 return Sparsity(nrow, ncol, colind_new, row_new);
2775 const casadi_int*
row = this->
row();
2776 for (casadi_int i=0; i<
size2(); ++i) {
2777 casadi_int lastrow = -1;
2781 if (
row[k] < lastrow)
2785 if (strictly &&
row[k] == lastrow)
2798 casadi_assert_dev(mapping.size()==
nnz());
2804 casadi_int k_strict=0;
2807 for (casadi_int i=0; i<
size2(); ++i) {
2810 casadi_int lastrow = -1;
2813 casadi_int new_colind = k_strict;
2816 for (casadi_int k=ret_colind[i]; k<ret_colind[i+1]; ++k) {
2819 casadi_assert(ret_row[k] >= lastrow,
"rows are not sequential");
2822 if (ret_row[k] == lastrow)
continue;
2825 lastrow = ret_row[k];
2828 mapping[k_strict] = mapping[k];
2831 ret_row[k_strict] = ret_row[k];
2838 ret_colind[i] = new_colind;
2842 ret_colind[
size2()] = k_strict;
2843 ret_row.resize(k_strict);
2844 mapping.resize(k_strict);
2855 const casadi_int*
row = this->
row();
2861 for (casadi_int cc=0; cc<
size2(); ++cc) {
2864 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
2867 casadi_int rr =
row[el];
2870 loc[el] = rr+cc*
size1()+ind1;
2877 if (indices.empty())
return;
2881 const casadi_int*
row = this->
row();
2885 for (std::vector<casadi_int>::iterator it=indices.begin(); it!=indices.end(); ++it) {
2887 casadi_int el = *it;
2890 std::vector<casadi_int> indices_sorted, mapping;
2891 sort(indices, indices_sorted, mapping,
false);
2893 for (
size_t i=0; i<indices.size(); ++i) {
2894 indices[mapping[i]] = indices_sorted[i];
2906 std::vector<casadi_int>::iterator it=indices.begin();
2910 casadi_int cur_pos = -1;
2912 casadi_int col_pos = 0;
2915 for (casadi_int i=0; i<
size2(); ++i, col_pos+=
size1()) {
2918 casadi_int last_pos = -1;
2922 casadi_int el =
colind[i+1] - 1;
2923 casadi_int j =
row[el];
2924 last_pos = col_pos + j;
2930 for (casadi_int el=
colind[i]; el<colind[i+1] && last_pos >= *it; ++el) {
2932 casadi_int j =
row[el];
2934 cur_pos = col_pos + j;
2937 while (*it < cur_pos) {
2940 if (++it==indices.end())
return;
2943 while (cur_pos == *it) {
2949 if (++it==indices.end())
return;
2956 std::fill(it, indices.end(), -1);
2962 std::vector<casadi_int> forbiddenColors;
2963 forbiddenColors.reserve(
size2());
2964 std::vector<casadi_int> color(
size2(), 0);
2967 const casadi_int* AT_colind = AT.
colind();
2968 const casadi_int* AT_row = AT.
row();
2970 const casadi_int*
row = this->
row();
2973 for (casadi_int i=0; i<
size2(); ++i) {
2979 casadi_int c =
row[el];
2982 for (casadi_int el_prev=AT_colind[c]; el_prev<AT_colind[c+1]; ++el_prev) {
2985 casadi_int i_prev = AT_row[el_prev];
2992 casadi_int color_prev = color[i_prev];
2995 forbiddenColors[color_prev] = i;
3001 for (color_i=0; color_i<forbiddenColors.size(); ++color_i) {
3003 if (forbiddenColors[color_i]!=i)
break;
3008 if (color_i==forbiddenColors.size()) {
3009 forbiddenColors.push_back(0);
3012 if (forbiddenColors.size()>cutoff) {
3019 std::vector<casadi_int> ret_colind(forbiddenColors.size()+1, 0), ret_row;
3022 for (casadi_int i=0; i<color.size(); ++i) {
3023 ret_colind[color[i]+1]++;
3027 for (casadi_int j=0; j<forbiddenColors.size(); ++j) {
3028 ret_colind[j+1] += ret_colind[j];
3032 ret_row.resize(color.size());
3033 for (casadi_int j=0; j<ret_row.size(); ++j) {
3034 ret_row[ret_colind[color[j]]++] = j;
3038 for (casadi_int j=ret_colind.size()-2; j>=0; --j) {
3039 ret_colind[j+1] = ret_colind[j];
3044 return Sparsity(
size2(), forbiddenColors.size(), ret_colind, ret_row);
3051 casadi_message(
"StarColoring requires a square matrix, got " +
dim() +
".");
3057 const casadi_int*
row = this->
row();
3059 casadi_assert_dev(ordering==1);
3071 return ret_permuted.
pmult(ord,
true,
false,
false);
3075 std::vector<casadi_int> forbiddenColors;
3076 forbiddenColors.reserve(
size2());
3077 std::vector<casadi_int> color(
size2(), -1);
3079 std::vector<casadi_int> firstNeighborP(
size2(), -1);
3080 std::vector<casadi_int> firstNeighborQ(
size2(), -1);
3081 std::vector<casadi_int> firstNeighborQ_el(
size2(), -1);
3083 std::vector<casadi_int> treated(
size2(), -1);
3084 std::vector<casadi_int> hub(
nnz_upper(), -1);
3086 std::vector<casadi_int> Tmapping;
3089 std::vector<casadi_int> star(
nnz());
3091 for (casadi_int i=0; i<
size2(); ++i) {
3092 for (casadi_int j_el=
colind[i]; j_el<
colind[i+1]; ++j_el) {
3093 casadi_int j =
row[j_el];
3096 star[Tmapping[j]] = k;
3104 casadi_int starID = 0;
3107 for (casadi_int v=0; v<
size2(); ++v) {
3110 for (casadi_int w_el=
colind[v]; w_el<
colind[v+1]; ++w_el) {
3111 casadi_int w =
row[w_el];
3112 casadi_int colorW = color[w];
3113 if (colorW==-1)
continue;
3116 forbiddenColors[colorW] = v;
3119 casadi_int p = firstNeighborP[colorW];
3120 casadi_int q = firstNeighborQ[colorW];
3126 if (treated[q]!=v) {
3131 for (casadi_int x_el=
colind[q]; x_el<
colind[q+1]; ++x_el) {
3132 casadi_int x =
row[x_el];
3133 if (color[x]==-1)
continue;
3136 forbiddenColors[color[x]] = v;
3146 for (casadi_int x_el=
colind[w]; x_el<
colind[w+1]; ++x_el) {
3147 casadi_int x =
row[x_el];
3148 if (color[x]==-1)
continue;
3151 forbiddenColors[color[x]] = v;
3161 firstNeighborP[colorW] = v;
3162 firstNeighborQ[colorW] = w;
3163 firstNeighborQ_el[colorW] = w_el;
3166 casadi_int x_el_end =
colind[w+1];
3167 casadi_int x, colorx;
3168 for (casadi_int x_el=
colind[w]; x_el < x_el_end; ++x_el) {
3171 if (colorx==-1 || x==v)
continue;
3174 if (hub[star[x_el]]==x) {
3177 forbiddenColors[colorx] = v;
3186 bool new_color =
true;
3187 for (casadi_int color_i=0; color_i<forbiddenColors.size(); ++color_i) {
3189 if (forbiddenColors[color_i]!=v) {
3198 color[v] = forbiddenColors.size();
3199 forbiddenColors.push_back(-1);
3202 if (forbiddenColors.size()>cutoff) {
3210 for (casadi_int w_el=
colind[v]; w_el<
colind[v+1]; ++w_el) {
3211 casadi_int w =
row[w_el];
3212 casadi_int colorW = color[w];
3213 if (colorW==-1)
continue;
3221 if (x==v || color[x]!=color[v])
continue;
3228 casadi_int starwx = star[x_el];
3232 star[w_el] = starwx;
3233 star[Tmapping[w_el]] = starwx;
3239 casadi_int p = firstNeighborP[colorW];
3240 casadi_int q = firstNeighborQ[colorW];
3241 casadi_int q_el = firstNeighborQ_el[colorW];
3247 casadi_int starvq = star[q_el];
3251 star[w_el] = starvq;
3252 star[Tmapping[w_el]] = starvq;
3261 star[w_el] = starID;
3262 star[Tmapping[w_el]]= starID;
3273 std::vector<casadi_int> ret_colind(forbiddenColors.size()+1, 0), ret_row;
3276 for (casadi_int i=0; i<color.size(); ++i) {
3277 ret_colind[color[i]+1]++;
3281 for (casadi_int j=0; j<forbiddenColors.size(); ++j) {
3282 ret_colind[j+1] += ret_colind[j];
3286 ret_row.resize(color.size());
3287 for (casadi_int j=0; j<ret_row.size(); ++j) {
3288 ret_row[ret_colind[color[j]]++] = j;
3292 for (casadi_int j=ret_colind.size()-2; j>=0; --j) {
3293 ret_colind[j+1] = ret_colind[j];
3298 return Sparsity(
size2(), forbiddenColors.size(), ret_colind, ret_row);
3302 const Dict& opts)
const {
3304 bool new_algo =
false;
3305 casadi_int cutoff = std::numeric_limits<casadi_int>::max();
3307 for (
auto&& e : opts) {
3308 if (e.first==
"new_algo") {
3309 new_algo = e.second;
3310 }
else if (e.first==
"cutoff") {
3312 }
else if (e.first==
"largest_first") {
3315 casadi_warning(
"Unknown option '" + e.first +
"' for star_coloring_new.");
3320 casadi_assert(
is_symmetric(),
"Expected symmetric matrix");
3331 casadi_int ncolor = coloring.
size2();
3332 const casadi_int *col_colind = coloring.
colind(), *col_row = coloring.
row();
3335 casadi_int nrow =
size1();
3337 const casadi_int*
row = this->
row();
3340 std::vector<casadi_int> output_ctr(nrow);
3343 which_color.resize(
nnz());
3344 std::fill(which_color.begin(), which_color.end(), -1);
3345 for (casadi_int color=0; color<ncolor; ++color) {
3347 std::fill(output_ctr.begin(), output_ctr.end(), 0);
3348 for (casadi_int el=col_colind[color]; el<col_colind[color+1]; ++el) {
3349 casadi_int c = col_row[el];
3350 for (casadi_int k=
colind[c]; k<
colind[c+1]; ++k) output_ctr[
row[k]]++;
3354 for (casadi_int el=col_colind[color]; el<col_colind[color+1]; ++el) {
3355 casadi_int c = col_row[el];
3358 if (output_ctr[
row[k]] == 1 && which_color[k] < 0) which_color[k] = color;
3365 for (casadi_int c=0; c<nrow; ++c) {
3367 casadi_int r =
row[k];
3370 casadi_int k_tr = rowind[r]++;
3372 if (which_color[k] < 0) {
3374 casadi_assert(which_color[k_tr] >= 0,
3375 "Expected color for element " +
str(c) +
", " +
str(r));
3376 }
else if (which_color[k_tr] < 0) {
3378 casadi_assert(which_color[k] >= 0,
3379 "Expected color for element " +
str(r) +
", " +
str(c));
3380 }
else if (which_color[k] <= which_color[k_tr]) {
3382 which_color[k_tr] = -1;
3385 which_color[k] = -1;
3387 }
else if (r == c) {
3389 casadi_assert(which_color[k] >= 0,
"No color for diagonal element " +
str(r));
3401 casadi_message(
"StarColoring requires a square matrix, got " +
dim() +
".");
3406 casadi_assert_dev(ordering==1);
3418 return ret_permuted.
pmult(ord,
true,
false,
false);
3423 const casadi_int*
row = this->
row();
3424 std::vector<casadi_int> forbiddenColors;
3425 forbiddenColors.reserve(
size2());
3426 std::vector<casadi_int> color(
size2(), -1);
3429 for (casadi_int i=0; i<
size2(); ++i) {
3432 for (casadi_int w_el=
colind[i]; w_el<
colind[i+1]; ++w_el) {
3433 casadi_int w =
row[w_el];
3439 forbiddenColors[color[w]] = i;
3444 for (casadi_int x_el=
colind[w]; x_el<
colind[w+1]; ++x_el) {
3445 casadi_int x =
row[x_el];
3446 if (color[x]==-1)
continue;
3452 forbiddenColors[color[x]] = i;
3457 for (casadi_int y_el=
colind[x]; y_el<
colind[x+1]; ++y_el) {
3458 casadi_int y =
row[y_el];
3459 if (color[y]==-1 || y==w)
continue;
3462 if (color[y]==color[w]) {
3465 forbiddenColors[color[x]] = i;
3481 bool new_color =
true;
3482 for (casadi_int color_i=0; color_i<forbiddenColors.size(); ++color_i) {
3484 if (forbiddenColors[color_i]!=i) {
3493 color[i] = forbiddenColors.size();
3494 forbiddenColors.push_back(-1);
3497 if (forbiddenColors.size()>cutoff) {
3505 casadi_int num_colors = forbiddenColors.size();
3512 std::vector<casadi_int> degree =
get_colind();
3513 casadi_int max_degree = 0;
3514 for (casadi_int k=0; k<
size2(); ++k) {
3515 degree[k] = degree[k+1]-degree[k];
3516 max_degree = std::max(max_degree, 1+degree[k]);
3518 degree.resize(
size2());
3521 std::vector<casadi_int> degree_count(max_degree+1, 0);
3522 for (std::vector<casadi_int>::const_iterator it=degree.begin(); it!=degree.end(); ++it) {
3523 degree_count.at(*it+1)++;
3527 for (casadi_int d=0; d<max_degree; ++d) {
3528 degree_count[d+1] += degree_count[d];
3532 std::vector<casadi_int> ordering(
size2());
3533 for (casadi_int k=
size2()-1; k>=0; --k) {
3534 ordering[degree_count[degree[k]]++] = k;
3538 std::vector<casadi_int>& reverse_ordering = degree_count;
3539 reverse_ordering.resize(ordering.size());
3540 std::copy(ordering.begin(), ordering.end(), reverse_ordering.rbegin());
3543 return reverse_ordering;
3549 std::vector<casadi_int> p_inv;
3552 for (casadi_int k=0; k<p.size(); ++k) {
3559 std::vector<casadi_int> col =
get_col();
3562 const casadi_int*
row = this->
row();
3565 std::vector<casadi_int> new_row(col.size()), new_col(col.size());
3568 if (permute_columns) {
3570 casadi_assert_dev(p.size()==
size2());
3573 for (casadi_int k=0; k<col.size(); ++k) {
3574 new_col[k] = pp[col[k]];
3579 std::copy(col.begin(), col.end(), new_col.begin());
3585 casadi_assert_dev(p.size()==
size1());
3588 for (casadi_int k=0; k<
nnz(); ++k) {
3589 new_row[k] = pp[
row[k]];
3594 std::copy(
row,
row+
nnz(), new_row.begin());
3614 std::vector<casadi_int> y_col_count(y.
size2(), 0);
3616 const casadi_int*
row = this->
row();
3617 const casadi_int* y_colind = y.
colind();
3618 const casadi_int* y_row = y.
row();
3621 for (casadi_int i=0; i<
size2(); ++i) {
3627 casadi_int j=
row[el];
3630 casadi_int el_y = y_colind[j] + y_col_count[j]++;
3633 if (el_y>=y_colind[j+1])
return false;
3636 casadi_int j_y = y_row[el_y];
3639 if (j_y != i)
return false;
3649 if (
this==&y)
return true;
3659 const casadi_int*
row = this->
row();
3660 const casadi_int* y_colind = y.
colind();
3661 const casadi_int* y_row = y.
row();
3667 for (casadi_int cc=0; cc<
size2(); ++cc) {
3668 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3669 casadi_int rr=
row[el];
3672 casadi_int loc = rr+
size1()*cc;
3673 casadi_int rr_y = loc % y.
size1();
3674 casadi_int cc_y = loc / y.
size1();
3677 if (rr_y != y_row[el] || el<y_colind[cc_y] || el>=y_colind[cc_y+1])
3687 std::vector<casadi_int>& col)
const {
3690 Sparsity self = shared_from_this<Sparsity>();
3694 return nnz() ==
static_cast<casadi_int
>(
row.size() * col.size());
3702 const casadi_int*
row = this->
row();
3705 for (casadi_int rr=0; rr<
size1(); ++rr) {
3708 for (casadi_int cc=0; cc<
size2(); ++cc) {
3710 if (cind[cc]<
colind[cc+1] &&
row[cind[cc]]==rr) {
3719 stream << std::endl;
3724 std::ostream &stream,
const Dict& options)
const {
3725 casadi_assert(lang==
"matlab",
"Only matlab language supported for now.");
3728 bool opt_inline =
false;
3729 std::string name =
"sp";
3730 bool as_matrix =
true;
3731 casadi_int indent_level = 0;
3732 std::vector<std::string> nonzeros;
3735 for (
auto&& op : options) {
3736 if (op.first==
"inline") {
3737 opt_inline = op.second;
3738 }
else if (op.first==
"name") {
3739 name = op.second.to_string();
3740 }
else if (op.first==
"as_matrix") {
3741 as_matrix = op.second;
3742 }
else if (op.first==
"indent_level") {
3743 indent_level = op.second;
3744 }
else if (op.first==
"nonzeros") {
3745 nonzeros = op.second;
3747 casadi_error(
"Unknown option '" + op.first +
"'.");
3753 for (casadi_int i=0; i < indent_level; ++i) indent +=
" ";
3754 casadi_assert(!opt_inline,
"Inline not supported for now.");
3757 stream << indent << name <<
"_m = " <<
size1() <<
";\n";
3758 stream << indent << name <<
"_n = " <<
size2() <<
";\n";
3761 const casadi_int index_offset = 1;
3765 const casadi_int*
row = this->
row();
3766 stream << indent << name<<
"_j = [";
3768 for (casadi_int i=0; i<
size2(); ++i) {
3770 if (!first) stream <<
", ";
3771 stream << (i+index_offset);
3778 stream << indent << name <<
"_i = [";
3780 casadi_int nz =
nnz();
3781 for (casadi_int i=0; i<nz; ++i) {
3782 if (!first) stream <<
", ";
3783 stream << (
row[i]+index_offset);
3789 stream << indent << name <<
"_v = ";
3790 if (nonzeros.empty()) {
3791 stream <<
"ones(size(" << name <<
"_i));\n";
3794 for (casadi_int i = 0; i < nonzeros.size(); ++i) {
3795 if (i > 0) stream <<
", ";
3796 stream << nonzeros.at(i);
3803 stream << indent << name <<
" = sparse(" << name <<
"_i, " << name <<
"_j, ";
3804 stream << name <<
"_v, " << name <<
"_m, " << name <<
"_n);\n";
3812 std::ostream& mfile = *mfile_ptr;
3815 mfile <<
"% This function was automatically generated by CasADi" << std::endl;
3822 mfile <<
"spy(A);" << std::endl;
3831 const casadi_int*
row = this->
row();
3833 for (casadi_int i=0; i<
size2(); ++i) {
3838 if (strictly ? rr <= i : rr < i)
return false;
3847 const casadi_int*
row = this->
row();
3849 for (casadi_int i=0; i<
size2(); ++i) {
3854 if (strictly ? rr >= i : rr > i)
return false;
3863 const casadi_int*
row = this->
row();
3864 std::vector<casadi_int> ret_colind, ret_row;
3865 ret_colind.reserve(
size2()+1);
3866 ret_colind.push_back(0);
3867 for (casadi_int cc=0; cc<
size2(); ++cc) {
3868 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3869 casadi_int rr=
row[el];
3870 if (rr>cc || (includeDiagonal && rr==cc)) {
3871 ret_row.push_back(rr);
3874 ret_colind.push_back(ret_row.size());
3881 const casadi_int*
row = this->
row();
3882 std::vector<casadi_int> ret_colind, ret_row;
3883 ret_colind.reserve(
size2()+1);
3884 ret_colind.push_back(0);
3885 for (casadi_int cc=0; cc<
size2(); ++cc) {
3886 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3887 casadi_int rr=
row[el];
3888 if (rr<cc || (includeDiagonal && rr==cc)) {
3889 ret_row.push_back(rr);
3892 ret_colind.push_back(ret_row.size());
3899 const casadi_int*
row = this->
row();
3900 std::vector<casadi_int> ret;
3901 for (casadi_int cc=0; cc<
size2(); ++cc) {
3902 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
3913 const casadi_int*
row = this->
row();
3914 std::vector<casadi_int> ret;
3915 for (casadi_int cc=0; cc<
size2(); ++cc) {
3916 for (casadi_int el =
colind[cc]; el<
colind[cc+1] &&
row[el]<=cc; ++el) {
3926 const casadi_int*
row = this->
row();
3927 for (casadi_int cc=0; cc<
size2(); ++cc) {
3930 bw = std::max(bw, cc-rr);
3939 const casadi_int*
row = this->
row();
3940 for (casadi_int cc=0; cc<
size2(); ++cc) {
3943 bw = std::max(bw, rr-cc);
3955 const casadi_int*
row = this->
row();
3956 return std::vector<casadi_int>(
row,
row+
nnz());
3961 const Btf&
btf = this->
btf();
3963 const casadi_int*
row = this->
row();
3966 for (casadi_int b = 0; b <
btf.nb; ++b) {
3970 for (casadi_int el=
btf.rowblock[b]; el<
btf.rowblock[b+1]; ++el) {
3971 casadi_int rr =
btf.rowperm[el];
3976 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3977 casadi_int cc =
btf.colperm[el];
3982 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3983 casadi_int cc =
btf.colperm[el];
3990 casadi_int rr=
row[k];
3997 for (casadi_int b =
btf.nb; b-- > 0; ) {
4001 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
4002 casadi_int cc =
btf.colperm[el];
4009 casadi_int rr=
row[k];
4015 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
4016 casadi_int cc =
btf.colperm[el];
4021 for (casadi_int el=
btf.rowblock[b]; el<
btf.rowblock[b+1]; ++el) {
4022 casadi_int rr =
btf.rowperm[el];
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
bool is_null() const
Is a null pointer?
static casadi_int start_index
static casadi_int drop(casadi_int(*fkeep)(casadi_int, casadi_int, double, void *), void *other, casadi_int nrow, casadi_int ncol, std::vector< casadi_int > &colind, std::vector< casadi_int > &row)
drop entries for which fkeep(A(i, j)) is false; return nz if OK, else -1
Sparsity get_diag(std::vector< casadi_int > &mapping) const
Get the diagonal of the matrix/create a diagonal matrix.
static void ldl_colind(const casadi_int *sp, casadi_int *parent, casadi_int *l_colind, casadi_int *w)
Calculate the column offsets for the L factor of an LDL^T factorization.
bool is_compactible(std::vector< casadi_int > &row, std::vector< casadi_int > &col) const
Check if the nonzero pattern is a Cartesian product (row x col)
void bfs(casadi_int n, std::vector< casadi_int > &wi, std::vector< casadi_int > &wj, std::vector< casadi_int > &queue, const std::vector< casadi_int > &imatch, const std::vector< casadi_int > &jmatch, casadi_int mark) const
Breadth-first search for coarse decomposition.
Sparsity combineGen1(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
bool is_permutation() const
Is this a permutation matrix?
std::size_t hash() const
Hash the sparsity pattern.
void export_code(const std::string &lang, std::ostream &stream, const Dict &options) const
Export sparsity in Matlab format.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
static casadi_int leaf(casadi_int i, casadi_int j, const casadi_int *first, casadi_int *maxfirst, casadi_int *prevleaf, casadi_int *ancestor, casadi_int *jleaf)
Needed by casadi_qr_colind.
static casadi_int wclear(casadi_int mark, casadi_int lemax, casadi_int *w, casadi_int n)
clear w
std::pair< casadi_int, casadi_int > size() const
Shape.
bool rowsSequential(bool strictly) const
Does the rows appear sequentially on each col.
Sparsity makeDense(std::vector< casadi_int > &mapping) const
Make a patten dense.
casadi_int numel() const
Number of elements.
bool is_orthonormal_rows(bool allow_empty=false) const
Are the rows of the pattern orthonormal ?
~SparsityInternal() override
Destructor.
bool is_square() const
Is square?
std::string repr_el(casadi_int k) const
Describe the nonzero location k as a string.
static void postorder(const casadi_int *parent, casadi_int n, casadi_int *post, casadi_int *w)
Calculate the postorder permuation.
Sparsity _enlargeColumns(casadi_int ncol, const std::vector< casadi_int > &cc, bool ind1) const
Enlarge the matrix along the second dimension (i.e. insert columns)
Sparsity _mtimes(const Sparsity &y) const
Sparsity pattern for a matrix-matrix product (details in public class)
bool has_diag() const
has diagonal entries?
static casadi_int postorder_dfs(casadi_int j, casadi_int k, casadi_int *head, const casadi_int *next, casadi_int *post, casadi_int *stack)
Traverse an elimination tree using depth first search.
casadi_int dfs(casadi_int j, casadi_int top, std::vector< casadi_int > &xi, std::vector< casadi_int > &pstack, const std::vector< casadi_int > &pinv, std::vector< bool > &marked) const
Depth-first search.
bool is_transpose(const SparsityInternal &y) const
Check if the sparsity is the transpose of another.
Sparsity _enlargeRows(casadi_int nrow, const std::vector< casadi_int > &rr, bool ind1) const
Enlarge the matrix along the first dimension (i.e. insert rows)
bool is_subset(const Sparsity &rhs) const
Is subset?
casadi_int nnz_lower(bool strictly=false) const
Number of non-zeros in the lower triangular half.
bool is_orthonormal_columns(bool allow_empty=false) const
Are the columns of the pattern orthonormal ?
bool is_column() const
Check if the pattern is a column vector (i.e. size2()==1)
void maxtrans(std::vector< casadi_int > &imatch, std::vector< casadi_int > &jmatch, Sparsity &trans, casadi_int seed) const
Compute the maximum transversal (maximum matching)
const std::vector< casadi_int > & sp() const
Get number of rows (see public class)
Sparsity pattern_inverse() const
Take the inverse of a sparsity pattern; flip zeros and non-zeros.
static void ldl_row(const casadi_int *sp, const casadi_int *parent, casadi_int *l_colind, casadi_int *l_row, casadi_int *w)
Calculate the row indices for the L factor of an LDL^T factorization.
Sparsity pmult(const std::vector< casadi_int > &p, bool permute_rows=true, bool permute_cols=true, bool invert_permutation=false) const
Permute rows and/or columns.
Sparsity _removeDuplicates(std::vector< casadi_int > &mapping) const
Remove duplicate entries.
Sparsity star_coloring_new(std::vector< casadi_int > &which_color, const Dict &opts) const
Perform a star coloring.
void spy_matlab(const std::string &mfile) const
Generate a script for Matlab or Octave which visualizes the sparsity using the spy command.
std::vector< casadi_int > get_lower() const
Get nonzeros in lower triangular part.
casadi_int bw_lower() const
Lower half-bandwidth.
SparsityInternal(casadi_int nrow, casadi_int ncol, const casadi_int *colind, const casadi_int *row)
Construct a sparsity pattern from arrays.
Sparsity transpose(std::vector< casadi_int > &mapping, bool invert_mapping=false) const
Transpose the matrix and get the reordering of the non-zero entries,.
bool is_symmetric() const
Is symmetric?
std::vector< casadi_int > amd() const
Approximate minimal degree preordering.
static casadi_int qr_counts(const casadi_int *tr_sp, const casadi_int *parent, const casadi_int *post, casadi_int *counts, casadi_int *w)
Calculate the column offsets for the QR R matrix.
void disp(std::ostream &stream, bool more) const override
Print description.
bool is_reshape(const SparsityInternal &y) const
Check if the sparsity is a reshape of another.
void spsolve(bvec_t *X, bvec_t *B, bool tr) const
Propagate sparsity through a linear solve.
static casadi_int qr_nnz(const casadi_int *sp, casadi_int *pinv, casadi_int *leftmost, const casadi_int *parent, casadi_int *nrow_ext, casadi_int *w)
Calculate the number of nonzeros in the QR V matrix.
bool is_diag() const
Is diagonal?
bool is_selection(bool allow_empty=false) const
Is this a selection matrix.
bool is_tril(bool strictly) const
Is lower triangular?
void augment(casadi_int k, std::vector< casadi_int > &jmatch, casadi_int *cheap, std::vector< casadi_int > &w, casadi_int *js, casadi_int *is, casadi_int *ps) const
Find an augmenting path.
static void unmatched(casadi_int m, const std::vector< casadi_int > &wi, std::vector< casadi_int > &p, std::vector< casadi_int > &rr, casadi_int set)
Collect unmatched columns into the permutation vector p.
bool is_vector() const
Check if the pattern is a row or column vector.
casadi_int size1() const
Get number of rows (see public class)
const casadi_int * row() const
Get row indices (see public class)
Sparsity _appendColumns(const SparsityInternal &sp) const
Append another sparsity patten horizontally.
Sparsity _erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1, std::vector< casadi_int > &mapping) const
Erase rows and/or columns - does bounds checking.
std::vector< casadi_int > get_upper() const
Get nonzeros in upper triangular part.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1) const
Get a submatrix.
Sparsity star_coloring2(casadi_int ordering, casadi_int cutoff) const
An improved distance-2 coloring algorithm.
std::vector< casadi_int > largest_first() const
Order the columns by decreasing degree.
Sparsity _resize(casadi_int nrow, casadi_int ncol) const
Resize.
casadi_int size2() const
Get number of columns (see public class)
bool is_stacked(const Sparsity &y, casadi_int n) const
Check if pattern is repeated.
Sparsity _tril(bool includeDiagonal) const
Get lower triangular part.
void dmperm(std::vector< casadi_int > &rowperm, std::vector< casadi_int > &colperm, std::vector< casadi_int > &rowblock, std::vector< casadi_int > &colblock, std::vector< casadi_int > &coarse_rowblock, std::vector< casadi_int > &coarse_colblock) const
Compute the Dulmage-Mendelsohn decomposition.
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Get the index of an existing non-zero element.
Sparsity _appendVector(const SparsityInternal &sp) const
Append another sparsity patten vertically (vectors only)
std::vector< casadi_int > get_colind() const
Get colind() as a vector.
casadi_int nnz_diag() const
Number of non-zeros on the diagonal.
Sparsity combineGen(const Sparsity &y, std::vector< unsigned char > &mapping) const
static void qr_init(const casadi_int *sp, const casadi_int *sp_tr, casadi_int *leftmost, casadi_int *parent, casadi_int *pinv, casadi_int *nrow_ext, casadi_int *v_nnz, casadi_int *r_nnz, casadi_int *w)
Setup QP solver.
casadi_int scatter(casadi_int j, std::vector< casadi_int > &w, casadi_int mark, casadi_int *Ci, casadi_int nz) const
x = x + beta * A(:, j), where x is a dense vector and A(:, j) is sparse
Sparsity _triu(bool includeDiagonal) const
Get upper triangular part.
static casadi_int rprune(casadi_int i, casadi_int j, double aij, void *other)
return 1 if column i is in R2
bool is_equal(const Sparsity &y) const
Check if two sparsity patterns are the same.
static std::vector< casadi_int > randperm(casadi_int n, casadi_int seed)
return a random permutation vector
Sparsity multiply(const Sparsity &B) const
C = A*B.
Sparsity drop_diag() const
Drop diagonal entries.
const casadi_int * colind() const
Get column offsets (see public class)
Sparsity uni_coloring(const Sparsity &AT, casadi_int cutoff) const
Perform a unidirectional coloring.
Sparsity T() const
Transpose the matrix.
Sparsity permute(const std::vector< casadi_int > &pinv, const std::vector< casadi_int > &q, casadi_int values) const
C = A(p, q) where p and q are permutations of 0..m-1 and 0..n-1.
static casadi_int diag(casadi_int i, casadi_int j, double aij, void *other)
keep off-diagonal entries; drop diagonal entries
Sparsity _reshape(casadi_int nrow, casadi_int ncol) const
Reshape a sparsity, order of nonzeros remains the same.
void find(std::vector< casadi_int > &loc, bool ind1) const
Get element index for each nonzero.
bool is_orthonormal(bool allow_empty=false) const
Are the rows and columns of the pattern orthonormal ?
bool is_row() const
Check if the pattern is a row vector (i.e. size1()==1)
static std::vector< casadi_int > invertPermutation(const std::vector< casadi_int > &p)
Invert a permutation vector.
static void qr_sparsities(const casadi_int *sp_a, casadi_int nrow_ext, casadi_int *sp_v, casadi_int *sp_r, const casadi_int *leftmost, const casadi_int *parent, const casadi_int *pinv, casadi_int *iw)
Get the row indices for V and R in QR factorization.
std::vector< casadi_int > get_row() const
Get row() as a vector.
std::vector< casadi_int > get_col() const
Get the column for each nonzero.
bool is_scalar(bool scalar_and_dense) const
Is scalar?
std::string dim(bool with_nz=false) const
Get the dimension as a string.
bool is_triu(bool strictly) const
is upper triangular?
bool is_dense() const
Is dense?
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
void spy(std::ostream &stream) const
Print a textual representation of sparsity.
static void matched(casadi_int n, const std::vector< casadi_int > &wj, const std::vector< casadi_int > &imatch, std::vector< casadi_int > &p, std::vector< casadi_int > &q, std::vector< casadi_int > &cc, std::vector< casadi_int > &rr, casadi_int set, casadi_int mark)
Collect matched columns and rows into p and q.
casadi_int bw_upper() const
Upper half-bandwidth.
casadi_int nnz() const
Number of structural non-zeros.
Sparsity star_coloring(casadi_int ordering, casadi_int cutoff) const
A greedy distance-2 coloring algorithm.
static void etree(const casadi_int *sp, casadi_int *parent, casadi_int *w, casadi_int ata)
Calculate the elimination tree for a matrix.
casadi_int nnz_upper(bool strictly=false) const
Number of non-zeros in the upper triangular half.
casadi_int scc(std::vector< casadi_int > &p, std::vector< casadi_int > &r) const
Find the strongly connected components of a square matrix.
const Btf & btf() const
Get cached block triangular form.
Sparsity pmult(const std::vector< casadi_int > &p, bool permute_rows=true, bool permute_columns=true, bool invert_permutation=false) const
Permute rows and/or columns.
casadi_int size1() const
Get the number of rows.
casadi_int dfs(casadi_int j, casadi_int top, std::vector< casadi_int > &xi, std::vector< casadi_int > &pstack, const std::vector< casadi_int > &pinv, std::vector< bool > &marked) const
Depth-first search on the adjacency graph of the sparsity.
Sparsity star_coloring(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a star coloring of a symmetric matrix:
static Sparsity sum2(const Sparsity &x)
Enlarge matrix.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
SparsityInternal * get() const
bool is_scalar(bool scalar_and_dense=false) const
Is scalar?
bool is_diag() const
Is diagonal?
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.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
static Sparsity sum1(const Sparsity &x)
Enlarge matrix.
std::vector< casadi_int > get_row() const
Get the row for each non-zero entry.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
bool is_dense() const
Is dense?
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
void resize(casadi_int nrow, casadi_int ncol)
Resize.
Sparsity star_coloring2(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a star coloring of a symmetric matrix:
bool mul_overflows(const T &a, const T &b)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
std::vector< casadi_int > invert_permutation(const std::vector< casadi_int > &a)
inverse a permutation vector
unsigned long long bvec_t
bool has_negative(const std::vector< T > &v)
Check if the vector has negative entries.
void sort(const std::vector< T > &values, std::vector< T > &sorted_values, std::vector< casadi_int > &indices, bool invert_indices=false)
Sort the data in a vector.
std::string str(const T &v)
String representation, any type.
std::vector< casadi_int > lookupvector(const std::vector< casadi_int > &v, casadi_int size)
Returns a vector for quickly looking up entries of supplied list.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
std::size_t hash_sparsity(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &colind, const std::vector< casadi_int > &row)
Hash a sparsity pattern.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
bool is_nondecreasing(const std::vector< T > &v)
Check if the vector is non-decreasing.