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;
275 if ((pa=parent[c]) != -1) {
277 if (nque[pa]==0) tail[pa] = tail[c];
278 next[tail[c]] = head[pa];
283 for (r=0; r<nrow; ++r)
if (pinv[r]<0) pinv[r] = c++;
284 if (nrow_ext) *nrow_ext = nrow_new;
289 qr_init(
const casadi_int* sp,
const casadi_int* sp_tr,
290 casadi_int* leftmost, casadi_int* parent, casadi_int* pinv,
291 casadi_int* nrow_ext, casadi_int* v_nnz, casadi_int* r_nnz, casadi_int* w) {
293 casadi_int ncol =
sp[1];
297 casadi_int* post = w; w += ncol;
300 *r_nnz =
qr_counts(sp_tr, parent, post, w, w+ncol);
302 *v_nnz =
qr_nnz(
sp, pinv, leftmost, parent, nrow_ext, w);
306 qr_sparsities(
const casadi_int* sp_a, casadi_int nrow_ext, casadi_int* sp_v, casadi_int* sp_r,
307 const casadi_int* leftmost,
const casadi_int* parent,
const casadi_int* pinv,
314 casadi_int ncol = sp_a[1];
315 const casadi_int *
colind=sp_a+2, *
row=sp_a+2+ncol+1;
316 casadi_int *v_colind=sp_v+2, *v_row=sp_v+2+ncol+1;
317 casadi_int *r_colind=sp_r+2, *r_row=sp_r+2+ncol+1;
319 sp_v[0] = sp_r[0] = nrow_ext;
320 sp_v[1] = sp_r[1] = ncol;
322 casadi_int* s = iw; iw += ncol;
324 casadi_int r, c, k, k1, top, len, k2, r2;
326 for (r=0; r<nrow_ext; ++r) iw[r] = -1;
328 casadi_int nnz_r=0, nnz_v=0;
330 for (c=0; c<ncol; ++c) {
334 v_colind[c] = k1 = nnz_v;
340 r = leftmost[
row[k]];
342 for (len=0; iw[r]!=c; r=parent[r]) {
346 while (len>0) s[--top] = s[--len];
348 if (r>c && iw[r]<c) {
354 for (k = top; k<ncol; ++k) {
360 for (k2=v_colind[r]; k2<v_colind[r+1]; ++k2) {
373 r_colind[ncol] = nnz_r;
374 v_colind[ncol] = nnz_v;
378 ldl_colind(
const casadi_int* sp, casadi_int* parent, casadi_int* l_colind, casadi_int* w) {
383 casadi_int n =
sp[0];
388 casadi_int* visited=w; w+=n;
390 for (c=0; c<n; ++c) {
398 while (visited[r]!=c) {
400 if (parent[r]==-1) parent[r]=c;
409 for (c=0; c<n; ++c) l_colind[c+1] += l_colind[c];
413 ldl_row(
const casadi_int* sp,
const casadi_int* parent, casadi_int* l_colind,
414 casadi_int* l_row, casadi_int *w) {
420 casadi_int n =
sp[0];
423 casadi_int *visited=w; w+=n;
427 for (c=0; c<n; ++c) {
433 while (visited[r]!=c) {
434 l_row[l_colind[r]++] = c;
442 for (c=0; c<n; ++c) {
451 const casadi_int* colind,
const casadi_int* row) :
452 sp_(2 + ncol+1 + colind[ncol]), btf_(nullptr) {
464 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
466 std::lock_guard<std::mutex> lock(btf_mtx_);
469 btf_ =
new SparsityInternal::Btf();
470 btf_->nb =
btf(btf_->rowperm, btf_->colperm, btf_->rowblock, btf_->colblock,
471 btf_->coarse_rowblock, btf_->coarse_colblock);
485 stream <<
"colind: " <<
get_colind() << std::endl;
486 stream <<
"row: " <<
get_row() << std::endl;
492 std::vector<casadi_int> col(
nnz());
493 for (casadi_int r=0; r<
size2(); ++r) {
494 for (casadi_int el =
colind[r]; el <
colind[r+1]; ++el) {
503 std::vector<casadi_int> mapping;
509 std::vector<casadi_int>& mapping,
bool invert_mapping)
const {
511 std::vector<casadi_int> trans_col =
get_row();
512 std::vector<casadi_int> trans_row =
get_col();
519 std::vector<casadi_int>& pstack,
520 const std::vector<casadi_int>& pinv,
521 std::vector<bool>& marked)
const {
529 const casadi_int*
row = this->
row();
537 casadi_int jnew = !pinv.empty() ? (pinv[j]) : j;
542 pstack[head] = (jnew < 0) ? 0 :
colind[jnew];
547 casadi_int p2 = (jnew < 0) ? 0 :
colind[jnew+1];
550 for (casadi_int p = pstack[head]; p< p2; ++p) {
553 casadi_int i =
row[p];
556 if (marked[i]) continue ;
584 std::vector<casadi_int>& r)
const {
590 std::vector<casadi_int> tmp;
594 std::vector<casadi_int> xi(2*
size2()+1);
595 std::vector<casadi_int>& Blk = xi;
597 std::vector<casadi_int> pstack(
size2()+1);
602 std::vector<bool> marked(
size2(),
false);
604 casadi_int top =
size2();
607 for (casadi_int i = 0; i<
size2(); ++i) {
609 top =
dfs(i, top, xi, pstack, tmp, marked);
613 std::fill(marked.begin(), marked.end(),
false);
616 casadi_int nb =
size2();
619 for (casadi_int k=0 ; k <
size2() ; ++k) {
621 casadi_int i = xi[k];
624 if (marked[i])
continue;
628 top = AT.
dfs(i, top, p, pstack, tmp, marked);
633 for (casadi_int k = nb ; k <=
size2() ; ++k)
640 for (casadi_int b = 0 ; b < nb ; b++) {
641 for (casadi_int k = r[b]; k<r[b+1] ; ++k)
646 for (casadi_int i=0; i<
size2(); ++i) {
652 for (casadi_int i=nb; i>0; --i) {
666 casadi_assert(
is_symmetric(),
"AMD requires a symmetric matrix");
668 casadi_int n=
size2();
673 casadi_int col_begin, col_end=0;
674 for (casadi_int c=0; c<n; ++c) {
679 for (casadi_int k=col_begin; k<col_end; ++k) {
687 casadi_int dense =
static_cast<casadi_int
>(10*sqrt(
static_cast<double>(n)));
688 dense = std::max(casadi_int(16), dense);
689 dense = std::min(n-2, dense);
691 std::vector<casadi_int>
P(n+1);
693 std::vector<casadi_int> len(n+1), nv(n+1), next(n+1), head(n+1), elen(n+1), degree(n+1),
698 casadi_int mindeg = 0;
700 casadi_int lemax = 0;
706 #define FLIP(i) (-(i)-2)
710 for (casadi_int k = 0; k<n; ++k) len[k] =
colind[k+1] -
colind[k];
712 casadi_int nzmax =
row.size();
713 for (casadi_int i=0; i<=n; ++i) {
728 for (casadi_int i = 0; i < n; ++i) {
735 }
else if (d > dense) {
742 if (head[d] != -1)
P[head[d]] = i;
750 for (k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {}
751 if (next[k] != -1)
P[next[k]] = -1;
752 head[mindeg] = next[k];
753 casadi_int elenk = elen[k];
754 casadi_int nvk = nv[k];
757 if (elenk > 0 &&
nnz + mindeg >= nzmax) {
758 for (casadi_int j = 0; j < n; j++) {
760 if ((p =
colind[j]) >= 0) {
766 for (q = 0, p = 0; p <
nnz; ) {
768 if ((j = FLIP(
row[p++])) >= 0) {
771 for (casadi_int k3 = 0; k3 < len[j]-1; k3++)
row[q++] =
row[p++];
780 casadi_int pk1 = (elenk == 0) ? p :
nnz;
781 casadi_int pk2 = pk1;
782 casadi_int e, pj, ln;
783 for (casadi_int k1 = 1; k1 <= elenk + 1; k1++) {
793 for (casadi_int k2 = 1; k2 <= ln; k2++) {
794 casadi_int i =
row[pj++];
796 if ((nvi = nv[i]) <= 0)
continue;
800 if (next[i] != -1)
P[next[i]] =
P[i];
802 next[
P[i]] = next[i];
804 head[degree[i]] = next[i];
812 if (elenk != 0)
nnz = pk2;
819 for (casadi_int pk = pk1; pk < pk2; pk++) {
820 casadi_int i =
row[pk];
822 if ((eln = elen[i]) <= 0)
continue;
823 casadi_int nvi = -nv[i];
824 casadi_int wnvi = mark - nvi;
829 }
else if (w[e] != 0) {
830 w[e] = degree[e] + wnvi;
835 for (casadi_int pk = pk1; pk < pk2; pk++) {
836 casadi_int i =
row[pk];
837 casadi_int p1 =
colind[i];
838 casadi_int p2 = p1 + elen[i] - 1;
840 for (h = 0, d = 0, p = p1; p <= p2; p++) {
843 casadi_int dext = w[e] - mark;
854 elen[i] = pn - p1 + 1;
856 casadi_int p4 = p1 + len[i];
857 for (p = p2 + 1; p < p4; p++) {
858 casadi_int j =
row[p];
860 if ((nvj = nv[j]) <= 0)
continue;
867 casadi_int nvi = -nv[i];
874 degree[i] = std::min(degree[i], d);
878 len[i] = pn - p1 + 1;
886 lemax = std::max(lemax, dk);
889 for (casadi_int pk = pk1; pk < pk2; pk++) {
890 casadi_int i =
row[pk];
891 if (nv[i] >= 0)
continue;
895 for (; i != -1 && next[i] != -1; i = next[i], mark++) {
897 casadi_int eln = elen[i];
899 casadi_int jlast = i;
900 for (casadi_int j = next[i]; j != -1; ) {
901 casadi_int ok = (len[j] == ln) && (elen[j] == eln);
902 for (p =
colind[j] + 1; ok && p <=
colind[j] + ln - 1; p++) {
903 if (w[
row[p]] != mark) ok = 0;
921 for (p = pk1, pk = pk1; pk < pk2; pk++) {
922 casadi_int i =
row[pk];
924 if ((nvi = -nv[i]) <= 0)
continue;
926 d = degree[i] + dk - nvi;
927 d = std::min(d, n - nel - nvi);
928 if (head[d] != -1)
P[head[d]] = i;
932 mindeg = std::min(mindeg, d);
937 if ((len[k] = p-pk1) == 0) {
941 if (elenk != 0)
nnz = p;
944 for (casadi_int i = 0; i < n; i++)
colind[i] = FLIP(
colind[i]);
945 for (casadi_int j = 0; j <= n; j++) head[j] = -1;
946 for (casadi_int j = n; j >= 0; j--) {
947 if (nv[j] > 0)
continue;
948 next[j] = head[
colind[j]];
951 for (casadi_int e = n; e >= 0; e--) {
952 if (nv[e] <= 0)
continue;
954 next[e] = head[
colind[e]];
958 for (casadi_int k = 0, i = 0; i <= n; i++) {
968 std::vector<casadi_int>& queue,
const std::vector<casadi_int>& imatch,
969 const std::vector<casadi_int>& jmatch, casadi_int mark)
const {
975 casadi_int head = 0, tail = 0, j, i, p, j2 ;
978 for (j=0; j<n; ++j) {
980 if (imatch[j] >= 0)
continue;
990 if (tail == 0)
return;
993 const casadi_int *C_row, *C_colind;
1000 C_colind = trans.
colind();
1004 while (head < tail) {
1008 for (p = C_colind[j] ; p < C_colind[j+1] ; p++) {
1012 if (wi[i] >= 0)
continue;
1021 if (wj[j2] >= 0)
continue;
1033 const std::vector<casadi_int>& imatch, std::vector<casadi_int>& p,
1034 std::vector<casadi_int>& q, std::vector<casadi_int>& cc, std::vector<casadi_int>& rr,
1035 casadi_int set, casadi_int mark) {
1041 casadi_int kc = cc[set];
1042 casadi_int kr = rr[set-1] ;
1043 for (casadi_int j=0; j<n; ++j) {
1045 if (wj[j] != mark)
continue;
1047 p[kr++] = imatch[j] ;
1056 std::vector<casadi_int>& p, std::vector<casadi_int>& rr, casadi_int set) {
1062 casadi_int i, kr = rr[set] ;
1076 std::vector<casadi_int> &rr = *
static_cast<std::vector<casadi_int> *
>(other);
1077 return (i >= rr[1] && i < rr[2]) ;
1081 std::vector<casadi_int>& w, casadi_int *js, casadi_int *is, casadi_int *ps)
const {
1088 const casadi_int*
row = this->
row();
1090 casadi_int found = 0, p, i = -1, head = 0, j ;
1106 for (p = cheap[j] ; p <
colind[j+1] && !found; ++p) {
1108 found = (jmatch[i] == -1) ;
1126 for (p = ps[head]; p<
colind[j+1]; ++p) {
1132 if (w[jmatch[i]] == k)
continue;
1141 js[++head] = jmatch[i];
1146 if (p ==
colind[j+1]) head--;
1150 for (p = head; p>=0; --p)
1151 jmatch[is[p]] = js[p];
1155 Sparsity& trans, casadi_int seed)
const {
1162 const casadi_int*
row = this->
row();
1164 casadi_int n2 = 0, m2 = 0;
1167 jmatch.resize(
size1());
1168 imatch.resize(
size2());
1173 for (casadi_int j=0; j<
size2(); ++j) {
1186 for (i=0; i<k; ++i) jmatch[i] = i;
1187 for (; i<
size1(); ++i) jmatch[i] = -1;
1190 for (j=0; j<k; ++j) imatch[j] = j;
1191 for (; j<
size2(); ++j) imatch[j] = -1;
1194 for (casadi_int i=0; i<
size1(); ++i) m2 += w[i];
1197 if (m2 < n2 && trans.
is_null())
1201 const SparsityInternal*
C = m2 < n2 ? static_cast<const SparsityInternal*>(trans.
get()) :
this;
1202 const casadi_int* C_colind =
C->colind();
1204 std::vector<casadi_int>& Cjmatch = m2 < n2 ? imatch : jmatch;
1205 std::vector<casadi_int>& Cimatch = m2 < n2 ? jmatch : imatch;
1208 w.resize(5 *
C->size2());
1210 casadi_int *cheap = &w.front() +
C->size2();
1211 casadi_int *js = &w.front() + 2*
C->size2();
1212 casadi_int *is = &w.front() + 3*
C->size2();
1213 casadi_int *ps = &w.front() + 4*
C->size2();
1216 for (casadi_int j=0; j<
C->size2(); ++j)
1217 cheap[j] = C_colind[j];
1220 for (casadi_int j=0; j<
C->size2(); ++j)
1224 for (casadi_int i=0; i<
C->size1(); ++i)
1228 std::vector<casadi_int> q =
randperm(
C->size2(), seed);
1231 for (k=0; k<
C->size2(); ++k) {
1232 C->augment(!q.empty() ? q[k]: k, Cjmatch, cheap, w, js, is, ps);
1236 for (casadi_int j=0; j<
C->size2(); ++j)
1239 for (casadi_int i = 0; i<
C->size1(); ++i)
1240 if (Cjmatch[i] >= 0)
1241 Cimatch[Cjmatch[i]] = i;
1245 std::vector<casadi_int>& colperm,
1246 std::vector<casadi_int>& rowblock,
1247 std::vector<casadi_int>& colblock,
1248 std::vector<casadi_int>& coarse_rowblock,
1249 std::vector<casadi_int>& coarse_colblock)
const {
1255 casadi_int seed = 0;
1266 colperm.resize(
size2());
1269 rowblock.resize(
size1()+6);
1272 colblock.resize(
size2()+6);
1275 coarse_rowblock.resize(5);
1276 std::fill(coarse_rowblock.begin(), coarse_rowblock.end(), 0);
1279 coarse_colblock.resize(5);
1280 std::fill(coarse_colblock.begin(), coarse_colblock.end(), 0);
1283 std::vector<casadi_int> imatch, jmatch;
1284 maxtrans(imatch, jmatch, trans, seed);
1289 std::vector<casadi_int>& wi = rowblock;
1290 std::vector<casadi_int>& wj = colblock;
1293 for (casadi_int j=0; j<
size2(); ++j)
1297 for (casadi_int i=0; i<
size1(); ++i)
1301 bfs(
size2(), wi, wj, colperm, imatch, jmatch, 1);
1304 bfs(
size1(), wj, wi, rowperm, jmatch, imatch, 3);
1310 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 1, 1);
1313 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 2, -1);
1316 matched(
size2(), wj, imatch, rowperm, colperm, coarse_colblock, coarse_rowblock, 3, 3);
1326 std::vector<casadi_int> colind_C, row_C;
1327 permute(pinv, colperm, 0, colind_C, row_C);
1330 casadi_int nc = coarse_colblock[3] - coarse_colblock[2];
1331 if (coarse_colblock[2] > 0) {
1332 for (casadi_int j = coarse_colblock[2]; j <= coarse_colblock[3]; ++j)
1333 colind_C[j-coarse_colblock[2]] = colind_C[j];
1335 casadi_int ncol_C = nc;
1337 colind_C.resize(nc+1);
1339 if (coarse_rowblock[2] - coarse_rowblock[1] <
size1()) {
1341 casadi_int cnz = colind_C[nc];
1342 if (coarse_rowblock[1] > 0)
1343 for (casadi_int k=0; k<cnz; ++k)
1344 row_C[k] -= coarse_rowblock[1];
1346 row_C.resize(colind_C.back());
1347 casadi_int nrow_C = nc ;
1348 Sparsity C(nrow_C, ncol_C, colind_C, row_C,
true);
1351 std::vector<casadi_int> scc_p, scc_r;
1352 casadi_int scc_nb =
C.scc(scc_p, scc_r);
1357 std::vector<casadi_int> ps = scc_p;
1360 std::vector<casadi_int> rs = scc_r;
1363 casadi_int nb1 = scc_nb;
1365 for (casadi_int k=0; k<nc; ++k)
1366 wj[k] = colperm[ps[k] + coarse_colblock[2]];
1368 for (casadi_int k=0; k<nc; ++k)
1369 colperm[k + coarse_colblock[2]] = wj[k];
1371 for (casadi_int k=0; k<nc; ++k)
1372 wi[k] = rowperm[ps[k] + coarse_rowblock[1]];
1374 for (casadi_int k=0; k<nc; ++k)
1375 rowperm[k + coarse_rowblock[1]] = wi[k];
1379 rowblock[0] = colblock[0] = 0;
1382 if (coarse_colblock[2] > 0)
1386 for (casadi_int k=0; k<nb1; ++k) {
1388 rowblock[nb2] = rs[k] + coarse_rowblock[1];
1389 colblock[nb2] = rs[k] + coarse_colblock[2] ;
1393 if (coarse_rowblock[2] <
size1()) {
1395 rowblock[nb2] = coarse_rowblock[2];
1396 colblock[nb2] = coarse_colblock[3];
1400 rowblock[nb2] =
size1();
1401 colblock[nb2] =
size2() ;
1404 rowblock.resize(nb2+1);
1405 colblock.resize(nb2+1);
1415 std::vector<casadi_int> p;
1418 if (seed==0)
return p;
1423 for (casadi_int k=0; k<n; ++k)
1427 if (seed==-1)
return p;
1431 unsigned int seedu =
static_cast<unsigned int>(seed);
1434 for (casadi_int k=0; k<n; ++k) {
1437 casadi_int j = k + (rand() % (n-k));
1439 casadi_int j = k + (rand_r(&seedu) % (n-k));
1442 casadi_int t = p[j];
1451 std::vector<casadi_int> pinv(p.size());
1452 for (casadi_int k=0; k<p.size(); ++k) pinv[p[k]] = k;
1457 const std::vector<casadi_int>& q, casadi_int values)
const {
1458 std::vector<casadi_int> colind_C, row_C;
1459 permute(pinv, q, values, colind_C, row_C);
1464 const std::vector<casadi_int>& q, casadi_int values,
1465 std::vector<casadi_int>& colind_C,
1466 std::vector<casadi_int>& row_C)
const {
1473 const casadi_int*
row = this->
row();
1476 colind_C.resize(
size2()+1);
1479 row_C.resize(
nnz());
1481 for (casadi_int k = 0; k<
size2(); ++k) {
1485 casadi_int j = !q.empty() ? (q[k]) : k;
1488 row_C[nz++] = !pinv.empty() ? (pinv[
row[t]]) :
row[t] ;
1493 colind_C[
size2()] = nz;
1497 void *other, casadi_int nrow, casadi_int ncol,
1498 std::vector<casadi_int>& colind, std::vector<casadi_int>& row) {
1506 for (casadi_int j = 0; j<ncol; ++j) {
1508 casadi_int p =
colind[j];
1512 for ( ; p <
colind[j+1] ; ++p) {
1513 if (fkeep(
row[p], j, 1, other)) {
1526 casadi_int *w, casadi_int n) {
1532 if (mark < 2 || (mark + lemax < 0)) {
1533 for (casadi_int k = 0; k<n; ++k)
if (w[k] != 0) w[k] = 1;
1550 casadi_int mark, casadi_int* Ci, casadi_int nz)
const {
1557 const casadi_int *Ap =
colind();
1558 const casadi_int *Ai =
row();
1560 for (p = Ap[j]; p<Ap[j+1]; ++p) {
1582 casadi_assert(
size2() == B.
size1(),
"Dimension mismatch.");
1583 casadi_int m =
size1();
1584 casadi_int anz =
nnz();
1585 casadi_int n = B.
size2();
1586 const casadi_int* Bp = B.
colind();
1587 const casadi_int* Bi = B.
row();
1588 casadi_int bnz = Bp[n];
1591 std::vector<casadi_int> w(m);
1594 std::vector<casadi_int> C_colind(n+1, 0), C_row;
1596 C_colind.resize(anz + bnz);
1598 casadi_int* Cp = &C_colind.front();
1599 for (casadi_int j=0; j<n; ++j) {
1600 if (nz+m > C_row.size()) {
1601 C_row.resize(2*(C_row.size())+m);
1606 for (casadi_int p = Bp[j] ; p<Bp[j+1] ; ++p) {
1607 nz =
scatter(Bi[p], w, j+1, &C_row.front(), nz);
1616 return Sparsity(m, n, C_colind, C_row);
1620 casadi_int nrow = this->
size1();
1621 casadi_int ncol = this->
size2();
1623 const casadi_int*
row = this->
row();
1630 casadi_int n = nrow * ncol;
1631 std::vector<casadi_int> ret_colind(n+1, 0), ret_row;
1635 for (casadi_int cc=0; cc<ncol; ++cc) {
1637 casadi_int rr=
row[k];
1638 casadi_int el=rr+nrow*cc;
1639 while (ret_i<=el) ret_colind[ret_i++]=ret_row.size();
1640 ret_row.push_back(el);
1641 mapping.push_back(k);
1644 while (ret_i<=n) ret_colind[ret_i++]=ret_row.size();
1647 return Sparsity(n, n, ret_colind, ret_row);
1651 casadi_int n = std::min(nrow, ncol);
1652 std::vector<casadi_int> ret_row, ret_colind(2, 0);
1655 for (casadi_int cc=0; cc<n; ++cc) {
1656 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1658 ret_row.push_back(
row[el]);
1660 mapping.push_back(el);
1666 return Sparsity(n, 1, ret_colind, ret_row);
1671 casadi_int nrow = this->
size1();
1672 casadi_int ncol = this->
size2();
1674 const casadi_int*
row = this->
row();
1675 for (casadi_int c=0; c<ncol && c<nrow; ++c) {
1677 if (
row[k]==c)
return true;
1684 casadi_int nrow = this->
size1();
1685 casadi_int ncol = this->
size2();
1687 const casadi_int*
row = this->
row();
1689 std::vector<casadi_int> ret_colind(ncol+1), ret_row;
1691 ret_row.reserve(
nnz());
1692 for (casadi_int c=0; c<ncol; ++c) {
1695 ret_row.push_back(
row[k]);
1698 ret_colind[c+1] = ret_row.size();
1700 return Sparsity(nrow, ncol, ret_colind, ret_row);
1705 if (with_nz) ret +=
"," +
str(
nnz()) +
"nz";
1711 std::stringstream ss;
1713 ss <<
"nonzero index " << k+start_index <<
" ";
1715 casadi_int r =
row()[k];
1717 ss <<
"(row " << r+start_index <<
", col " << c+start_index <<
")";
1724 casadi_int d1 =
size1();
1725 casadi_int d2 = y.
size2();
1744 if (y.
is_diag())
return shared_from_this<Sparsity>();
1747 const casadi_int* x_row =
row();
1748 const casadi_int* x_colind =
colind();
1749 const casadi_int* y_row = y.
row();
1750 const casadi_int* y_colind = y.
colind();
1753 std::vector<casadi_int>
row, col;
1756 std::vector<casadi_int> tmp(d1, -1);
1759 for (casadi_int cc=0; cc<d2; ++cc) {
1760 for (casadi_int kk=y_colind[cc]; kk<y_colind[cc+1]; ++kk) {
1761 casadi_int rr = y_row[kk];
1764 for (casadi_int kk1=x_colind[rr]; kk1<x_colind[rr+1]; ++kk1) {
1765 casadi_int rr1 = x_row[kk1];
1782 return size2()==1 &&
size1()==1 && (!scalar_and_dense ||
nnz()==1);
1807 const casadi_int*
row = this->
row();
1813 if (
nnz() !=
size2())
return false;
1816 for (casadi_int i=0; i<
nnz(); ++i) {
1822 for (casadi_int i=0; i<
size2(); ++i) {
1850 if (sum2(
sp).
nnz()!=
nnz())
return false;
1851 if (sum1(
sp).
nnz()!=
nnz())
return false;
1862 if (sum2(
sp).
nnz()!=
nnz())
return false;
1863 if (sum1(
sp).
nnz()!=
nnz())
return false;
1874 if (sum2(
sp).
nnz()!=
nnz())
return false;
1875 if (sum1(
sp).
nnz()!=
nnz())
return false;
1885 const casadi_int*
row = this->
row();
1887 for (casadi_int cc=0; cc<
size2(); ++cc) {
1888 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1889 if (cc<
row[el] || (!strictly && cc==
row[el]))
nnz++;
1897 const casadi_int*
row = this->
row();
1899 for (casadi_int cc=0; cc<
size2(); ++cc) {
1900 for (casadi_int el =
colind[cc]; el <
colind[cc+1]; ++el) {
1909 const casadi_int*
row = this->
row();
1911 for (casadi_int cc=0; cc<
size2(); ++cc) {
1912 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
1913 if (cc>
row[el] || (!strictly && cc==
row[el]))
nnz++;
1920 return std::pair<casadi_int, casadi_int>(
size1(),
size2());
1924 std::vector<casadi_int>& mapping)
const {
1928 return shared_from_this<Sparsity>();
1930 casadi_assert_in_range(rr, -
numel()+ind1,
numel()+ind1);
1934 std::vector<casadi_int> rr_mod = rr;
1935 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
1937 if (*i<0) *i +=
numel();
1939 return _erase(rr_mod,
false, mapping);
1944 std::vector<casadi_int> rr_sorted = rr;
1945 std::sort(rr_sorted.begin(), rr_sorted.end());
1946 return _erase(rr_sorted,
false, mapping);
1953 if (
numel()==0)
return shared_from_this<Sparsity>();
1956 mapping.reserve(
nnz());
1962 std::vector<casadi_int>::const_iterator next_rr = rr.begin();
1968 casadi_int k_first, k_last=0;
1971 for (casadi_int j=0; j<
size2(); ++j) {
1974 k_last = ret_colind[j+1];
1977 for (casadi_int k=k_first; k<k_last; ++k) {
1979 casadi_int i=ret_row[k];
1982 casadi_int el = i+j*
size1();
1985 while (next_rr!=rr.end() && *next_rr<el) next_rr++;
1988 if (next_rr!=rr.end() && *next_rr==el) {
1994 mapping.push_back(k);
2001 ret_colind[j+1] = nz;
2011 const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
2012 bool ind1, std::vector<casadi_int>& mapping)
const {
2013 casadi_assert_in_range(rr, -
size1()+ind1,
size1()+ind1);
2014 casadi_assert_in_range(cc, -
size2()+ind1,
size2()+ind1);
2020 std::vector<casadi_int> rr_mod = rr;
2021 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2023 if (*i<0) *i +=
size1();
2025 std::sort(rr_mod.begin(), rr_mod.end());
2028 std::vector<casadi_int> cc_mod = cc;
2029 for (std::vector<casadi_int>::iterator i=cc_mod.begin(); i!=cc_mod.end(); ++i) {
2031 if (*i<0) *i +=
size2();
2033 std::sort(cc_mod.begin(), cc_mod.end());
2036 return _erase(rr_mod, cc_mod,
false, mapping);
2043 if (
numel()==0)
return shared_from_this<Sparsity>();
2046 mapping.reserve(
nnz());
2055 std::vector<casadi_int>::const_iterator ie = cc.begin();
2058 casadi_int el_first=0, el_last=0;
2061 for (casadi_int i=0; i<
size2(); ++i) {
2064 el_last = ret_colind[i+1];
2067 bool deletable_col = ie!=cc.end() && *ie==i;
2068 if (deletable_col) {
2072 std::vector<casadi_int>::const_iterator je = rr.begin();
2075 for (casadi_int el=el_first; el<el_last; ++el) {
2077 casadi_int j=ret_row[el];
2080 for (; je!=rr.end() && *je<j; ++je) {}
2083 if (je!=rr.end() && *je==j) {
2089 mapping.push_back(el);
2096 for (casadi_int el=el_first; el<el_last; ++el) {
2098 casadi_int j=ret_row[el];
2101 mapping.push_back(el);
2119 const std::vector<casadi_int>& cc)
const {
2120 casadi_assert_bounded(rr,
size1());
2121 casadi_assert_bounded(cc,
size2());
2123 std::vector<casadi_int> rr_sorted;
2124 std::vector<casadi_int> rr_sorted_index;
2126 sort(rr, rr_sorted, rr_sorted_index);
2128 std::vector<casadi_int> ret(cc.size()*rr.size());
2130 casadi_int stride = rr.size();
2132 const casadi_int*
row = this->
row();
2134 for (casadi_int i=0;i<cc.size();++i) {
2135 casadi_int it = cc[i];
2136 casadi_int el=
colind[it];
2137 for (casadi_int j=0;j<rr_sorted.size();++j) {
2138 casadi_int jt=rr_sorted[j];
2140 for (; el<
colind[it+1] &&
row[el]<jt; ++el) {}
2143 ret[i*stride+rr_sorted_index[j]] = el;
2145 ret[i*stride+rr_sorted_index[j]] = -1;
2153 std::vector<casadi_int>& mapping,
bool ind1)
const {
2154 casadi_assert_dev(rr.size()==
sp.nnz());
2157 casadi_assert_in_range(rr, -
numel()+ind1,
numel()+ind1);
2161 std::vector<casadi_int> rr_mod = rr;
2162 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2163 casadi_assert(!(ind1 && (*i)<=0),
2164 "Matlab is 1-based, but requested index " +
str(*i) +
". "
2165 "Note that negative slices are disabled in the Matlab interface. "
2166 "Possibly you may want to use 'end'.");
2168 if (*i<0) *i +=
numel();
2170 return sub(rr_mod,
sp, mapping,
false);
2174 mapping.resize(rr.size());
2175 std::copy(rr.begin(), rr.end(), mapping.begin());
2179 std::vector<casadi_int> ret_colind(
sp.size2()+1), ret_row;
2181 const casadi_int* sp_colind =
sp.colind();
2182 const casadi_int* sp_row =
sp.row();
2183 for (casadi_int c=0; c<
sp.size2(); ++c) {
2184 for (casadi_int el=sp_colind[c]; el<sp_colind[c+1]; ++el) {
2185 if (mapping[el]>=0) {
2186 mapping[ret_row.size()] = mapping[el];
2187 ret_row.push_back(sp_row[el]);
2190 ret_colind[c+1] = ret_row.size();
2192 mapping.resize(ret_row.size());
2193 return Sparsity(
sp.size1(),
sp.size2(), ret_colind, ret_row);
2197 const std::vector<casadi_int>& rr,
const std::vector<casadi_int>& cc,
2198 std::vector<casadi_int>& mapping,
bool ind1)
const {
2199 casadi_assert_in_range(rr, -
size1()+ind1,
size1()+ind1);
2200 casadi_assert_in_range(cc, -
size2()+ind1,
size2()+ind1);
2203 std::vector<casadi_int> tmp = rr;
2204 for (std::vector<casadi_int>::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
2206 if (*i<0) *i +=
size1();
2208 std::vector<casadi_int> rr_sorted, rr_sorted_index;
2209 sort(tmp, rr_sorted, rr_sorted_index,
false);
2213 for (std::vector<casadi_int>::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
2215 if (*i<0) *i +=
size2();
2217 std::vector<casadi_int> cc_sorted, cc_sorted_index;
2218 sort(tmp, cc_sorted, cc_sorted_index,
false);
2219 std::vector<casadi_int> columns, rows;
2222 bool with_lookup =
static_cast<double>(cc.size())*
static_cast<double>(rr.size()) >
nnz();
2223 std::vector<casadi_int> rrlookup;
2241 const casadi_int*
row = this->
row();
2242 for (casadi_int i=0; i<cc.size(); ++i) {
2243 casadi_int it = cc_sorted[i];
2246 for (casadi_int el=
colind[it]; el<
colind[it+1]; ++el) {
2247 casadi_int j =
row[el];
2248 casadi_int ji = rrlookup[j];
2250 casadi_int jv = rr_sorted[ji];
2251 while (ji>=0 && jv == rr_sorted[ji--])
nnz++;
2256 casadi_int el =
colind[it];
2257 for (casadi_int j=0; j<rr_sorted.size(); ++j) {
2258 casadi_int jt=rr_sorted[j];
2260 while (el<
colind[it+1] &&
row[el]<jt) el++;
2267 mapping.resize(
nnz);
2268 columns.resize(
nnz);
2273 for (casadi_int i=0; i<cc.size(); ++i) {
2274 casadi_int it = cc_sorted[i];
2277 for (casadi_int el=
colind[it]; el<
colind[it+1]; ++el) {
2278 casadi_int jt =
row[el];
2279 casadi_int ji = rrlookup[jt];
2281 casadi_int jv = rr_sorted[ji];
2282 while (ji>=0 && jv == rr_sorted[ji]) {
2283 rows[k] = rr_sorted_index[ji];
2284 columns[k] = cc_sorted_index[i];
2293 casadi_int el =
colind[it];
2294 for (casadi_int j=0; j<rr_sorted.size(); ++j) {
2295 casadi_int jt=rr_sorted[j];
2297 while (el<
colind[it+1] &&
row[el]<jt) el++;
2300 rows[k] = rr_sorted_index[j];
2301 columns[k] = cc_sorted_index[i];
2309 std::vector<casadi_int> sp_mapping;
2310 std::vector<casadi_int> mapping_ = mapping;
2313 for (casadi_int i=0; i<mapping.size(); ++i)
2314 mapping[i] = mapping_[sp_mapping[i]];
2321 bool function0_is_zero)
const {
2322 static std::vector<unsigned char> mapping;
2323 return combineGen1<false>(y, f0x_is_zero, function0_is_zero, mapping);
2327 bool function0_is_zero,
2328 std::vector<unsigned char>& mapping)
const {
2329 return combineGen1<true>(y, f0x_is_zero, function0_is_zero, mapping);
2334 std::vector<unsigned char> mapping;
2335 shared_from_this<Sparsity>().unite(rhs, mapping);
2336 for (
auto e : mapping) {
2337 if (e==1)
return false;
2342 template<
bool with_mapping>
2344 bool function0_is_zero,
2345 std::vector<unsigned char>& mapping)
const {
2351 std::fill(mapping.begin(), mapping.end(), 1 | 2);
2357 if (function0_is_zero) {
2358 return combineGen<with_mapping, true, true>(y, mapping);
2360 return combineGen<with_mapping, true, false>(y, mapping);
2362 }
else if (function0_is_zero) {
2363 return combineGen<with_mapping, false, true>(y, mapping);
2365 return combineGen<with_mapping, false, false>(y, mapping);
2369 template<
bool with_mapping,
bool f0x_is_zero,
bool function0_is_zero>
2371 std::vector<unsigned char>& mapping)
const {
2375 "Dimension mismatch : " +
str(
size()) +
" versus " +
str(y.
size()) +
".");
2378 const casadi_int* y_colind = y.
colind();
2379 const casadi_int* y_row = y.
row();
2381 const casadi_int*
row = this->
row();
2384 std::vector<casadi_int> ret_colind(
size2()+1, 0);
2385 std::vector<casadi_int> ret_row;
2388 if (with_mapping) mapping.clear();
2391 for (casadi_int i=0; i<
size2(); ++i) {
2393 casadi_int el1 =
colind[i];
2394 casadi_int el2 = y_colind[i];
2397 casadi_int el1_last =
colind[i+1];
2398 casadi_int el2_last = y_colind[i+1];
2401 while (el1<el1_last || el2<el2_last) {
2403 casadi_int row1 = el1<el1_last ?
row[el1] :
size1();
2404 casadi_int row2 = el2<el2_last ? y_row[el2] :
size1();
2408 ret_row.push_back(row1);
2409 if (with_mapping) mapping.push_back( 1 | 2);
2411 }
else if (row1<row2) {
2412 if (!function0_is_zero) {
2413 ret_row.push_back(row1);
2414 if (with_mapping) mapping.push_back(1);
2416 if (with_mapping) mapping.push_back(1 | 4);
2421 ret_row.push_back(row2);
2422 if (with_mapping) mapping.push_back(2);
2424 if (with_mapping) mapping.push_back(2 | 4);
2431 ret_colind[i+1] = ret_row.size();
2440 if (n==1 &&
is_equal(y))
return true;
2445 const casadi_int*
row = this->
row();
2446 casadi_int y_size1 = y.
size1();
2447 casadi_int y_size2 = y.
size2();
2448 const casadi_int* y_colind = y.
colind();
2449 const casadi_int* y_row = y.
row();
2451 if (
size1!=y_size1 ||
size2!=n*y_size2)
return false;
2454 if (
nnz!=n*y_nnz)
return false;
2456 if (y_nnz==y_size1*y_size2)
return true;
2458 casadi_int offset = 0;
2462 for (
int i=0; i<n; ++i) {
2464 for (
int c=0; c<y_size2; ++c)
if (y_colind[c+1]+offset != *
colind++)
return false;
2466 for (
int k=0; k<y_nnz; ++k)
if (y_row[k] != *
row++)
return false;
2476 if (
this == y.
get())
return true;
2488 std::vector<casadi_int> row_ret;
2489 std::vector<casadi_int> colind_ret=
get_colind();
2491 const casadi_int*
row = this->
row();
2494 for (casadi_int i=0;i<
size2();++i) {
2507 row_ret.push_back(j);
2513 while (j <
size1()) {
2514 row_ret.push_back(j);
2525 const std::vector<casadi_int>& y_colind,
2526 const std::vector<casadi_int>& y_row)
const {
2527 casadi_assert_dev(y_colind.size()==y_ncol+1);
2528 casadi_assert_dev(y_row.size()==y_colind.back());
2533 const casadi_int* y_colind,
const casadi_int* y_row)
const {
2535 const casadi_int*
row = this->
row();
2538 casadi_int nz = y_colind[y_ncol];
2541 if (
nnz()!=nz ||
size2()!=y_ncol ||
size1()!=y_nrow)
return false;
2550 if (!std::equal(
row,
row+nz, y_row))
return false;
2557 casadi_assert(
size2() == 1 &&
sp.size2() == 1,
2558 "_appendVector(sp): Both arguments must be vectors but got "
2559 +
str(
size2()) +
" columns for lhs, and " +
str(
sp.size2()) +
" columns for rhs.");
2562 casadi_int sz =
nnz();
2565 std::vector<casadi_int> new_row =
get_row();
2566 const casadi_int* sp_row =
sp.row();
2567 new_row.resize(sz +
sp.nnz());
2568 for (casadi_int i=sz; i<new_row.size(); ++i)
2569 new_row[i] = sp_row[i-sz] +
size1();
2572 std::vector<casadi_int> new_colind(2, 0);
2573 new_colind[1] = new_row.size();
2578 casadi_assert(
size1()==
sp.size1(),
2579 "_appendColumns(sp): row sizes must match but got " +
str(
size1())
2580 +
" for lhs, and " +
str(
sp.size1()) +
" for rhs.");
2583 std::vector<casadi_int> new_row =
get_row();
2584 const casadi_int* sp_row =
sp.row();
2585 new_row.insert(new_row.end(), sp_row, sp_row+
sp.nnz());
2588 std::vector<casadi_int> new_colind =
get_colind();
2589 const casadi_int* sp_colind =
sp.colind();
2590 new_colind.resize(
size2() +
sp.size2() + 1);
2591 for (casadi_int i =
size2()+1; i<new_colind.size(); ++i)
2592 new_colind[i] = sp_colind[i-
size2()] +
nnz();
2599 casadi_assert_in_range(cc, -ncol+ind1, ncol+ind1);
2603 std::vector<casadi_int> cc_mod = cc;
2604 for (std::vector<casadi_int>::iterator i=cc_mod.begin(); i!=cc_mod.end(); ++i) {
2606 if (*i<0) *i += ncol;
2612 std::vector<casadi_int> new_colind =
get_colind();
2613 new_colind.resize(ncol+1,
nnz());
2615 casadi_int ik=cc.back();
2616 casadi_int nz=
nnz();
2617 for (casadi_int i=cc.size()-1; i>=0; --i) {
2619 for (; ik>cc[i]; --ik) {
2620 new_colind[ik] = nz;
2627 new_colind[cc[i]] = nz;
2631 for (; ik>=0; --ik) {
2638 const std::vector<casadi_int>& rr,
bool ind1)
const {
2639 casadi_assert_in_range(rr, -nrow+ind1, nrow+ind1);
2643 std::vector<casadi_int> rr_mod = rr;
2644 for (std::vector<casadi_int>::iterator i=rr_mod.begin(); i!=rr_mod.end(); ++i) {
2646 if (*i<0) *i += nrow;
2652 casadi_assert_dev(rr.size() ==
size1());
2655 std::vector<casadi_int> new_row =
get_row();
2656 for (casadi_int k=0; k<
nnz(); ++k) {
2657 new_row[k] = rr[new_row[k]];
2664 const casadi_int*
row = this->
row();
2665 mapping.resize(
nnz());
2666 for (casadi_int i=0; i<
size2(); ++i) {
2668 casadi_int j =
row[el];
2669 mapping[el] = j + i*
size1();
2678 if (rr<0) rr +=
size1();
2679 if (cc<0) cc +=
size2();
2681 const casadi_int*
row = this->
row();
2684 casadi_assert(rr>=0 && rr<
size1(),
"Row index " +
str(rr)
2685 +
" out of bounds [0, " +
str(
size1()) +
")");
2686 casadi_assert(cc>=0 && cc<
size2(),
"Column index " +
str(cc)
2687 +
" out of bounds [0, " +
str(
size2()) +
")");
2696 for (casadi_int ind=
colind[cc]; ind<
colind[cc+1]; ++ind) {
2697 if (
row[ind] == rr) {
2699 }
else if (
row[ind] > rr) {
2708 if (nrow<0 && ncol>0) {
2710 }
else if (nrow>0 && ncol<0) {
2714 casadi_assert(
numel() == nrow*ncol,
2715 "reshape: number of elements must remain the same. Old shape is "
2716 +
dim() +
". New shape is " +
str(nrow) +
"x" +
str(ncol)
2717 +
"=" +
str(nrow*ncol) +
".");
2718 std::vector<casadi_int> ret_col(
nnz());
2719 std::vector<casadi_int> ret_row(
nnz());
2721 const casadi_int*
row = this->
row();
2722 for (casadi_int i=0; i<
size2(); ++i) {
2724 casadi_int j =
row[el];
2727 casadi_int k_ret = j+i*
size1();
2730 casadi_int i_ret = k_ret/nrow;
2731 casadi_int j_ret = k_ret%nrow;
2732 ret_col[el] = i_ret;
2733 ret_row[el] = j_ret;
2741 std::vector<casadi_int> row_new, colind_new(ncol+1, 0);
2743 const casadi_int*
row = this->
row();
2747 for (i=0; i<
size2() && i<ncol; ++i) {
2749 colind_new[i] = row_new.size();
2753 row_new.push_back(
row[el]);
2758 for (; i<ncol+1; ++i) {
2759 colind_new[i] = row_new.size();
2762 return Sparsity(nrow, ncol, colind_new, row_new);
2767 const casadi_int*
row = this->
row();
2768 for (casadi_int i=0; i<
size2(); ++i) {
2769 casadi_int lastrow = -1;
2773 if (
row[k] < lastrow)
2777 if (strictly &&
row[k] == lastrow)
2790 casadi_assert_dev(mapping.size()==
nnz());
2796 casadi_int k_strict=0;
2799 for (casadi_int i=0; i<
size2(); ++i) {
2802 casadi_int lastrow = -1;
2805 casadi_int new_colind = k_strict;
2808 for (casadi_int k=ret_colind[i]; k<ret_colind[i+1]; ++k) {
2811 casadi_assert(ret_row[k] >= lastrow,
"rows are not sequential");
2814 if (ret_row[k] == lastrow)
continue;
2817 lastrow = ret_row[k];
2820 mapping[k_strict] = mapping[k];
2823 ret_row[k_strict] = ret_row[k];
2830 ret_colind[i] = new_colind;
2834 ret_colind[
size2()] = k_strict;
2835 ret_row.resize(k_strict);
2836 mapping.resize(k_strict);
2847 const casadi_int*
row = this->
row();
2853 for (casadi_int cc=0; cc<
size2(); ++cc) {
2856 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
2859 casadi_int rr =
row[el];
2862 loc[el] = rr+cc*
size1()+ind1;
2869 if (indices.empty())
return;
2873 const casadi_int*
row = this->
row();
2877 for (std::vector<casadi_int>::iterator it=indices.begin(); it!=indices.end(); ++it) {
2879 casadi_int el = *it;
2882 std::vector<casadi_int> indices_sorted, mapping;
2883 sort(indices, indices_sorted, mapping,
false);
2885 for (
size_t i=0; i<indices.size(); ++i) {
2886 indices[mapping[i]] = indices_sorted[i];
2898 std::vector<casadi_int>::iterator it=indices.begin();
2902 casadi_int cur_pos = -1;
2904 casadi_int col_pos = 0;
2907 for (casadi_int i=0; i<
size2(); ++i, col_pos+=
size1()) {
2910 casadi_int last_pos = -1;
2914 casadi_int el =
colind[i+1] - 1;
2915 casadi_int j =
row[el];
2916 last_pos = col_pos + j;
2922 for (casadi_int el=
colind[i]; el<colind[i+1] && last_pos >= *it; ++el) {
2924 casadi_int j =
row[el];
2926 cur_pos = col_pos + j;
2929 while (*it < cur_pos) {
2932 if (++it==indices.end())
return;
2935 while (cur_pos == *it) {
2941 if (++it==indices.end())
return;
2948 std::fill(it, indices.end(), -1);
2954 std::vector<casadi_int> forbiddenColors;
2955 forbiddenColors.reserve(
size2());
2956 std::vector<casadi_int> color(
size2(), 0);
2959 const casadi_int* AT_colind = AT.
colind();
2960 const casadi_int* AT_row = AT.
row();
2962 const casadi_int*
row = this->
row();
2965 for (casadi_int i=0; i<
size2(); ++i) {
2971 casadi_int c =
row[el];
2974 for (casadi_int el_prev=AT_colind[c]; el_prev<AT_colind[c+1]; ++el_prev) {
2977 casadi_int i_prev = AT_row[el_prev];
2984 casadi_int color_prev = color[i_prev];
2987 forbiddenColors[color_prev] = i;
2993 for (color_i=0; color_i<forbiddenColors.size(); ++color_i) {
2995 if (forbiddenColors[color_i]!=i)
break;
3000 if (color_i==forbiddenColors.size()) {
3001 forbiddenColors.push_back(0);
3004 if (forbiddenColors.size()>cutoff) {
3011 std::vector<casadi_int> ret_colind(forbiddenColors.size()+1, 0), ret_row;
3014 for (casadi_int i=0; i<color.size(); ++i) {
3015 ret_colind[color[i]+1]++;
3019 for (casadi_int j=0; j<forbiddenColors.size(); ++j) {
3020 ret_colind[j+1] += ret_colind[j];
3024 ret_row.resize(color.size());
3025 for (casadi_int j=0; j<ret_row.size(); ++j) {
3026 ret_row[ret_colind[color[j]]++] = j;
3030 for (casadi_int j=ret_colind.size()-2; j>=0; --j) {
3031 ret_colind[j+1] = ret_colind[j];
3036 return Sparsity(
size2(), forbiddenColors.size(), ret_colind, ret_row);
3043 casadi_message(
"StarColoring requires a square matrix, got " +
dim() +
".");
3049 const casadi_int*
row = this->
row();
3051 casadi_assert_dev(ordering==1);
3063 return ret_permuted.
pmult(ord,
true,
false,
false);
3067 std::vector<casadi_int> forbiddenColors;
3068 forbiddenColors.reserve(
size2());
3069 std::vector<casadi_int> color(
size2(), -1);
3071 std::vector<casadi_int> firstNeighborP(
size2(), -1);
3072 std::vector<casadi_int> firstNeighborQ(
size2(), -1);
3073 std::vector<casadi_int> firstNeighborQ_el(
size2(), -1);
3075 std::vector<casadi_int> treated(
size2(), -1);
3076 std::vector<casadi_int> hub(
nnz_upper(), -1);
3078 std::vector<casadi_int> Tmapping;
3081 std::vector<casadi_int> star(
nnz());
3083 for (casadi_int i=0; i<
size2(); ++i) {
3084 for (casadi_int j_el=
colind[i]; j_el<
colind[i+1]; ++j_el) {
3085 casadi_int j =
row[j_el];
3088 star[Tmapping[j]] = k;
3096 casadi_int starID = 0;
3099 for (casadi_int v=0; v<
size2(); ++v) {
3102 for (casadi_int w_el=
colind[v]; w_el<
colind[v+1]; ++w_el) {
3103 casadi_int w =
row[w_el];
3104 casadi_int colorW = color[w];
3105 if (colorW==-1)
continue;
3108 forbiddenColors[colorW] = v;
3111 casadi_int p = firstNeighborP[colorW];
3112 casadi_int q = firstNeighborQ[colorW];
3118 if (treated[q]!=v) {
3123 for (casadi_int x_el=
colind[q]; x_el<
colind[q+1]; ++x_el) {
3124 casadi_int x =
row[x_el];
3125 if (color[x]==-1)
continue;
3128 forbiddenColors[color[x]] = v;
3138 for (casadi_int x_el=
colind[w]; x_el<
colind[w+1]; ++x_el) {
3139 casadi_int x =
row[x_el];
3140 if (color[x]==-1)
continue;
3143 forbiddenColors[color[x]] = v;
3153 firstNeighborP[colorW] = v;
3154 firstNeighborQ[colorW] = w;
3155 firstNeighborQ_el[colorW] = w_el;
3158 casadi_int x_el_end =
colind[w+1];
3159 casadi_int x, colorx;
3160 for (casadi_int x_el=
colind[w]; x_el < x_el_end; ++x_el) {
3163 if (colorx==-1 || x==v)
continue;
3166 if (hub[star[x_el]]==x) {
3169 forbiddenColors[colorx] = v;
3178 bool new_color =
true;
3179 for (casadi_int color_i=0; color_i<forbiddenColors.size(); ++color_i) {
3181 if (forbiddenColors[color_i]!=v) {
3190 color[v] = forbiddenColors.size();
3191 forbiddenColors.push_back(-1);
3194 if (forbiddenColors.size()>cutoff) {
3202 for (casadi_int w_el=
colind[v]; w_el<
colind[v+1]; ++w_el) {
3203 casadi_int w =
row[w_el];
3204 casadi_int colorW = color[w];
3205 if (colorW==-1)
continue;
3213 if (x==v || color[x]!=color[v])
continue;
3220 casadi_int starwx = star[x_el];
3224 star[w_el] = starwx;
3225 star[Tmapping[w_el]] = starwx;
3231 casadi_int p = firstNeighborP[colorW];
3232 casadi_int q = firstNeighborQ[colorW];
3233 casadi_int q_el = firstNeighborQ_el[colorW];
3239 casadi_int starvq = star[q_el];
3243 star[w_el] = starvq;
3244 star[Tmapping[w_el]] = starvq;
3253 star[w_el] = starID;
3254 star[Tmapping[w_el]]= starID;
3265 std::vector<casadi_int> ret_colind(forbiddenColors.size()+1, 0), ret_row;
3268 for (casadi_int i=0; i<color.size(); ++i) {
3269 ret_colind[color[i]+1]++;
3273 for (casadi_int j=0; j<forbiddenColors.size(); ++j) {
3274 ret_colind[j+1] += ret_colind[j];
3278 ret_row.resize(color.size());
3279 for (casadi_int j=0; j<ret_row.size(); ++j) {
3280 ret_row[ret_colind[color[j]]++] = j;
3284 for (casadi_int j=ret_colind.size()-2; j>=0; --j) {
3285 ret_colind[j+1] = ret_colind[j];
3290 return Sparsity(
size2(), forbiddenColors.size(), ret_colind, ret_row);
3296 casadi_message(
"StarColoring requires a square matrix, got " +
dim() +
".");
3301 casadi_assert_dev(ordering==1);
3313 return ret_permuted.
pmult(ord,
true,
false,
false);
3318 const casadi_int*
row = this->
row();
3319 std::vector<casadi_int> forbiddenColors;
3320 forbiddenColors.reserve(
size2());
3321 std::vector<casadi_int> color(
size2(), -1);
3324 for (casadi_int i=0; i<
size2(); ++i) {
3327 for (casadi_int w_el=
colind[i]; w_el<
colind[i+1]; ++w_el) {
3328 casadi_int w =
row[w_el];
3334 forbiddenColors[color[w]] = i;
3339 for (casadi_int x_el=
colind[w]; x_el<
colind[w+1]; ++x_el) {
3340 casadi_int x =
row[x_el];
3341 if (color[x]==-1)
continue;
3347 forbiddenColors[color[x]] = i;
3352 for (casadi_int y_el=
colind[x]; y_el<
colind[x+1]; ++y_el) {
3353 casadi_int y =
row[y_el];
3354 if (color[y]==-1 || y==w)
continue;
3357 if (color[y]==color[w]) {
3360 forbiddenColors[color[x]] = i;
3376 bool new_color =
true;
3377 for (casadi_int color_i=0; color_i<forbiddenColors.size(); ++color_i) {
3379 if (forbiddenColors[color_i]!=i) {
3388 color[i] = forbiddenColors.size();
3389 forbiddenColors.push_back(-1);
3392 if (forbiddenColors.size()>cutoff) {
3400 casadi_int num_colors = forbiddenColors.size();
3407 std::vector<casadi_int> degree =
get_colind();
3408 casadi_int max_degree = 0;
3409 for (casadi_int k=0; k<
size2(); ++k) {
3410 degree[k] = degree[k+1]-degree[k];
3411 max_degree = std::max(max_degree, 1+degree[k]);
3413 degree.resize(
size2());
3416 std::vector<casadi_int> degree_count(max_degree+1, 0);
3417 for (std::vector<casadi_int>::const_iterator it=degree.begin(); it!=degree.end(); ++it) {
3418 degree_count.at(*it+1)++;
3422 for (casadi_int d=0; d<max_degree; ++d) {
3423 degree_count[d+1] += degree_count[d];
3427 std::vector<casadi_int> ordering(
size2());
3428 for (casadi_int k=
size2()-1; k>=0; --k) {
3429 ordering[degree_count[degree[k]]++] = k;
3433 std::vector<casadi_int>& reverse_ordering = degree_count;
3434 reverse_ordering.resize(ordering.size());
3435 std::copy(ordering.begin(), ordering.end(), reverse_ordering.rbegin());
3438 return reverse_ordering;
3444 std::vector<casadi_int> p_inv;
3447 for (casadi_int k=0; k<p.size(); ++k) {
3454 std::vector<casadi_int> col =
get_col();
3457 const casadi_int*
row = this->
row();
3460 std::vector<casadi_int> new_row(col.size()), new_col(col.size());
3463 if (permute_columns) {
3465 casadi_assert_dev(p.size()==
size2());
3468 for (casadi_int k=0; k<col.size(); ++k) {
3469 new_col[k] = pp[col[k]];
3474 std::copy(col.begin(), col.end(), new_col.begin());
3480 casadi_assert_dev(p.size()==
size1());
3483 for (casadi_int k=0; k<
nnz(); ++k) {
3484 new_row[k] = pp[
row[k]];
3489 std::copy(
row,
row+
nnz(), new_row.begin());
3509 std::vector<casadi_int> y_col_count(y.
size2(), 0);
3511 const casadi_int*
row = this->
row();
3512 const casadi_int* y_colind = y.
colind();
3513 const casadi_int* y_row = y.
row();
3516 for (casadi_int i=0; i<
size2(); ++i) {
3522 casadi_int j=
row[el];
3525 casadi_int el_y = y_colind[j] + y_col_count[j]++;
3528 if (el_y>=y_colind[j+1])
return false;
3531 casadi_int j_y = y_row[el_y];
3534 if (j_y != i)
return false;
3544 if (
this==&y)
return true;
3554 const casadi_int*
row = this->
row();
3555 const casadi_int* y_colind = y.
colind();
3556 const casadi_int* y_row = y.
row();
3562 for (casadi_int cc=0; cc<
size2(); ++cc) {
3563 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3564 casadi_int rr=
row[el];
3567 casadi_int loc = rr+
size1()*cc;
3568 casadi_int rr_y = loc % y.
size1();
3569 casadi_int cc_y = loc / y.
size1();
3572 if (rr_y != y_row[el] || el<y_colind[cc_y] || el>=y_colind[cc_y+1])
3586 const casadi_int*
row = this->
row();
3589 for (casadi_int rr=0; rr<
size1(); ++rr) {
3592 for (casadi_int cc=0; cc<
size2(); ++cc) {
3594 if (cind[cc]<
colind[cc+1] &&
row[cind[cc]]==rr) {
3603 stream << std::endl;
3608 std::ostream &stream,
const Dict& options)
const {
3609 casadi_assert(lang==
"matlab",
"Only matlab language supported for now.");
3612 bool opt_inline =
false;
3613 std::string name =
"sp";
3614 bool as_matrix =
true;
3615 casadi_int indent_level = 0;
3616 std::vector<std::string> nonzeros;
3619 for (
auto&& op : options) {
3620 if (op.first==
"inline") {
3621 opt_inline = op.second;
3622 }
else if (op.first==
"name") {
3623 name = op.second.to_string();
3624 }
else if (op.first==
"as_matrix") {
3625 as_matrix = op.second;
3626 }
else if (op.first==
"indent_level") {
3627 indent_level = op.second;
3628 }
else if (op.first==
"nonzeros") {
3629 nonzeros = op.second;
3631 casadi_error(
"Unknown option '" + op.first +
"'.");
3637 for (casadi_int i=0; i < indent_level; ++i) indent +=
" ";
3638 casadi_assert(!opt_inline,
"Inline not supported for now.");
3641 stream << indent << name <<
"_m = " <<
size1() <<
";\n";
3642 stream << indent << name <<
"_n = " <<
size2() <<
";\n";
3645 const casadi_int index_offset = 1;
3649 const casadi_int*
row = this->
row();
3650 stream << indent << name<<
"_j = [";
3652 for (casadi_int i=0; i<
size2(); ++i) {
3654 if (!first) stream <<
", ";
3655 stream << (i+index_offset);
3662 stream << indent << name <<
"_i = [";
3664 casadi_int nz =
nnz();
3665 for (casadi_int i=0; i<nz; ++i) {
3666 if (!first) stream <<
", ";
3667 stream << (
row[i]+index_offset);
3673 stream << indent << name <<
"_v = ";
3674 if (nonzeros.empty()) {
3675 stream <<
"ones(size(" << name <<
"_i));\n";
3678 for (casadi_int i = 0; i < nonzeros.size(); ++i) {
3679 if (i > 0) stream <<
", ";
3680 stream << nonzeros.at(i);
3687 stream << indent << name <<
" = sparse(" << name <<
"_i, " << name <<
"_j, ";
3688 stream << name <<
"_v, " << name <<
"_m, " << name <<
"_n);\n";
3695 std::ofstream mfile;
3696 mfile.open(mfile_name.c_str());
3699 mfile <<
"% This function was automatically generated by CasADi" << std::endl;
3706 mfile <<
"spy(A);" << std::endl;
3717 const casadi_int*
row = this->
row();
3719 for (casadi_int i=0; i<
size2(); ++i) {
3724 if (strictly ? rr <= i : rr < i)
return false;
3733 const casadi_int*
row = this->
row();
3735 for (casadi_int i=0; i<
size2(); ++i) {
3740 if (strictly ? rr >= i : rr > i)
return false;
3749 const casadi_int*
row = this->
row();
3750 std::vector<casadi_int> ret_colind, ret_row;
3751 ret_colind.reserve(
size2()+1);
3752 ret_colind.push_back(0);
3753 for (casadi_int cc=0; cc<
size2(); ++cc) {
3754 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3755 casadi_int rr=
row[el];
3756 if (rr>cc || (includeDiagonal && rr==cc)) {
3757 ret_row.push_back(rr);
3760 ret_colind.push_back(ret_row.size());
3767 const casadi_int*
row = this->
row();
3768 std::vector<casadi_int> ret_colind, ret_row;
3769 ret_colind.reserve(
size2()+1);
3770 ret_colind.push_back(0);
3771 for (casadi_int cc=0; cc<
size2(); ++cc) {
3772 for (casadi_int el=
colind[cc]; el<
colind[cc+1]; ++el) {
3773 casadi_int rr=
row[el];
3774 if (rr<cc || (includeDiagonal && rr==cc)) {
3775 ret_row.push_back(rr);
3778 ret_colind.push_back(ret_row.size());
3785 const casadi_int*
row = this->
row();
3786 std::vector<casadi_int> ret;
3787 for (casadi_int cc=0; cc<
size2(); ++cc) {
3788 for (casadi_int el =
colind[cc]; el<
colind[cc+1]; ++el) {
3799 const casadi_int*
row = this->
row();
3800 std::vector<casadi_int> ret;
3801 for (casadi_int cc=0; cc<
size2(); ++cc) {
3802 for (casadi_int el =
colind[cc]; el<
colind[cc+1] &&
row[el]<=cc; ++el) {
3812 const casadi_int*
row = this->
row();
3813 for (casadi_int cc=0; cc<
size2(); ++cc) {
3816 bw = std::max(bw, cc-rr);
3825 const casadi_int*
row = this->
row();
3826 for (casadi_int cc=0; cc<
size2(); ++cc) {
3829 bw = std::max(bw, rr-cc);
3841 const casadi_int*
row = this->
row();
3842 return std::vector<casadi_int>(
row,
row+
nnz());
3847 const Btf&
btf = this->
btf();
3849 const casadi_int*
row = this->
row();
3852 for (casadi_int b = 0; b <
btf.nb; ++b) {
3856 for (casadi_int el=
btf.rowblock[b]; el<
btf.rowblock[b+1]; ++el) {
3857 casadi_int rr =
btf.rowperm[el];
3862 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3863 casadi_int cc =
btf.colperm[el];
3868 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3869 casadi_int cc =
btf.colperm[el];
3876 casadi_int rr=
row[k];
3883 for (casadi_int b =
btf.nb; b-- > 0; ) {
3887 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3888 casadi_int cc =
btf.colperm[el];
3895 casadi_int rr=
row[k];
3901 for (casadi_int el=
btf.colblock[b]; el<
btf.colblock[b+1]; ++el) {
3902 casadi_int cc =
btf.colperm[el];
3907 for (casadi_int el=
btf.rowblock[b]; el<
btf.rowblock[b+1]; ++el) {
3908 casadi_int rr =
btf.rowperm[el];
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.
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.
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 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?
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.
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:
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.
bool mul_overflows(const T &a, const T &b)