27 #include "sparsity_internal.hpp"
29 #include "casadi_misc.hpp"
30 #include "serializing_stream.hpp"
31 #include "filesystem_impl.hpp"
34 #define CASADI_THROW_ERROR(FNAME, WHAT) \
35 throw CasadiException("Error in Sparsity::" FNAME " at " + CASADI_WHERE + ":\n"\
41 class EmptySparsity :
public Sparsity {
44 const casadi_int
colind[1] = {0};
45 own(
new SparsityInternal(0, 0, colind,
nullptr));
49 class ScalarSparsity :
public Sparsity {
52 const casadi_int
colind[2] = {0, 1};
53 const casadi_int
row[1] = {0};
54 own(
new SparsityInternal(1, 1, colind, row));
58 class ScalarSparseSparsity :
public Sparsity {
60 ScalarSparseSparsity() {
61 const casadi_int
colind[2] = {0, 0};
62 const casadi_int
row[1] = {0};
63 own(
new SparsityInternal(1, 1, colind, row));
69 casadi_assert_dev(dummy==0);
79 casadi_assert(nrow>=0 && ncol>=0,
80 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
81 std::vector<casadi_int>
row,
colind(ncol+1, 0);
86 casadi_assert(rc.first>=0 && rc.second>=0,
87 "Dimensions must be non-negative, got " +
str(rc.first) +
"-by-" +
str(rc.second));
88 std::vector<casadi_int>
row,
colind(rc.second+1, 0);
89 assign_cached(rc.first, rc.second,
colind,
row);
93 const std::vector<casadi_int>& row,
bool order_rows) {
94 casadi_assert(nrow>=0 && ncol>=0,
95 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
96 assign_cached(nrow, ncol,
colind,
row, order_rows);
100 const casadi_int* colind,
const casadi_int* row,
bool order_rows) {
101 casadi_assert(nrow>=0 && ncol>=0,
102 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
104 *
this =
dense(nrow, ncol);
108 assign_cached(nrow, ncol, colindv, rowv, order_rows);
125 return (*this)->size1();
129 return (*this)->size2();
133 return (*this)->numel();
138 if (
numel()==0)
return 100;
140 r *=
static_cast<double>(
nnz());
141 r /=
static_cast<double>(
size1());
142 r /=
static_cast<double>(
size2());
147 return (*this)->is_empty(both);
151 return (*this)->nnz();
155 return (*this)->size();
160 case 1:
return size1();
161 case 2:
return size2();
163 casadi_error(
"Axis must be 1 or 2.");
167 return (*this)->row();
171 return (*this)->colind();
175 if (el<0 || el>=
nnz()) {
176 throw std::out_of_range(
"Sparsity::row: Index " +
str(el)
177 +
" out of range [0," +
str(
nnz()) +
")");
183 if (cc<0 || cc>
size2()) {
184 throw std::out_of_range(
"Sparsity::colind: Index "
185 +
str(cc) +
" out of range [0," +
str(
size2()) +
"]");
192 *
this = (*this)->_resize(nrow, ncol);
198 if (rr<0) rr +=
size1();
199 if (cc<0) cc +=
size2();
202 casadi_assert(rr>=0 && rr<
size1(),
"Row index out of bounds");
203 casadi_assert(cc>=0 && cc<
size2(),
"Column index out of bounds");
214 std::vector<casadi_int> rowv(
nnz+1);
218 for (casadi_int c=cc; c<
size2; ++c) colindv[c+1]++;
220 return rowv.size()-1;
226 if (
row[ind] == rr) {
228 }
else if (
row[ind] > rr) {
235 rowv.insert(rowv.begin()+ind, rr);
236 for (casadi_int c=cc+1; c<
size2+1; ++c) colindv[c]++;
244 return get_nz(rr, cc)!=-1;
249 return (*this)->get_nz(rr, cc);
258 casadi_assert_dev(x.
nnz()==sp.
nnz());
267 const std::vector<casadi_int>& cc)
const {
268 return (*this)->get_nz(rr, cc);
272 return (*this)->is_scalar(scalar_and_dense);
276 return (*this)->is_dense();
280 return (*this)->is_diag();
284 return (*this)->is_row();
288 return (*this)->is_column();
292 return (*this)->is_vector();
296 return (*this)->is_square();
300 return (*this)->is_permutation();
304 return (*this)->is_selection(allow_empty);
308 return (*this)->is_orthonormal(allow_empty);
312 return (*this)->is_orthonormal_rows(allow_empty);
316 return (*this)->is_orthonormal_columns(allow_empty);
320 return (*this)->is_symmetric();
324 return (*this)->is_tril(strictly);
328 return (*this)->is_triu(strictly);
332 std::vector<casadi_int>& mapping,
bool ind1)
const {
333 return (*this)->
sub(rr, *sp, mapping, ind1);
337 std::vector<casadi_int>& mapping,
bool ind1)
const {
338 return (*this)->
sub(rr, cc, mapping, ind1);
342 const std::vector<casadi_int>& cc,
bool ind1) {
343 std::vector<casadi_int> mapping;
344 *
this = (*this)->_erase(rr, cc, ind1, mapping);
348 std::vector<casadi_int>
Sparsity::erase(
const std::vector<casadi_int>& rr,
bool ind1) {
349 std::vector<casadi_int> mapping;
350 *
this = (*this)->_erase(rr, ind1, mapping);
355 return (*this)->nnz_lower(strictly);
359 return (*this)->nnz_upper(strictly);
363 return (*this)->nnz_diag();
367 return (*this)->get_colind();
371 return (*this)->get_col();
375 return (*this)->get_row();
393 return (*this)->
transpose(mapping, invert_mapping);
402 std::vector<unsigned char>& mapping)
const {
403 return (*this)->
combine(y, f0x_is_zero, fx0_is_zero, mapping);
407 bool fx0_is_zero)
const {
408 return (*this)->
combine(y, f0x_is_zero, fx0_is_zero);
412 return (*this)->
combine(y,
false,
false, mapping);
416 return (*this)->
combine(y,
false,
false);
420 std::vector<unsigned char>& mapping)
const {
421 return (*this)->
combine(y,
true,
true, mapping);
425 return (*this)->
combine(y,
true,
true);
429 return (*this)->is_subset(rhs);
433 const std::string& ) {
436 "Matrix product with incompatible dimensions. Lhs is "
437 + x.
dim() +
" and rhs is " + y.
dim() +
".");
443 return (*this)->is_stacked(y, n);
447 return (*this)->is_equal(y);
451 const std::vector<casadi_int>& row)
const {
452 return (*this)->is_equal(nrow, ncol,
colind,
row);
456 const casadi_int* colind,
const casadi_int* row)
const {
457 return (*this)->is_equal(nrow, ncol,
colind,
row);
465 std::vector< unsigned char > mapping;
482 "Sparsity::append: Dimension mismatch. "
483 "You attempt to append a shape " + sp.
dim()
484 +
" to a shape " +
dim()
485 +
". The number of columns must match.");
489 }
else if (
size1()==0) {
511 "Sparsity::appendColumns: Dimension mismatch. You attempt to "
512 "append a shape " + sp.
dim() +
" to a shape "
513 +
dim() +
". The number of rows must match.");
517 }
else if (
size2()==0) {
533 static ScalarSparsity ret;
538 static ScalarSparseSparsity ret;
543 static EmptySparsity ret;
548 const std::vector<casadi_int>& cc,
bool ind1) {
554 casadi_assert(cc.size()==
size2(),
555 "Expected " +
str(
size2()) +
" column indices, but got " +
str(cc.size()) +
".");
559 *
this = (*this)->_enlargeColumns(ncol, cc, ind1);
564 casadi_assert(rr.size()==
size1(),
565 "Expected " +
str(
size1()) +
" row indices, but got " +
str(rr.size()) +
".");
569 *
this = (*this)->_enlargeRows(nrow, rr, ind1);
574 casadi_assert(nrow>=0 && ncol>=0,
575 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
578 casadi_int n = std::min(nrow, ncol);
581 std::vector<casadi_int>
colind(ncol+1, n);
582 for (casadi_int cc=0; cc<n; ++cc)
colind[cc] = cc;
585 std::vector<casadi_int>
row =
range(n);
596 return (*this)->dim(with_nz);
608 return "[" +
dim(
false) +
"]";
611 return "[" +
dim(
true) +
"]";
616 casadi_assert(k>=0 && k<
nnz(),
617 "Index " +
str(k) +
" out of range for " +
str(
nnz()) +
" nonzeros.");
618 return (*this)->repr_el(k);
633 "LDL factorization requires a symmetric matrix");
639 std::vector<casadi_int> tmp;
642 return Aperm.
ldl(tmp,
false);
645 casadi_int n=
size1();
649 std::vector<casadi_int> w(3*n);
651 std::vector<casadi_int> parent(n);
653 std::vector<casadi_int> L_colind(1+n);
656 std::vector<casadi_int> L_row(L_colind.back());
660 return Sparsity(n, n, L_colind, L_row,
true).T();
665 std::vector<casadi_int>& pc,
bool amd)
const {
674 std::vector<casadi_int> tmp;
677 Aperm.
qr_sparse(V, R, prinv, tmp,
false);
685 std::vector<casadi_int> leftmost(
size1);
686 std::vector<casadi_int> parent(
size2);
688 std::vector<casadi_int> iw(
size1 + 7*
size2 + 1);
691 casadi_int nrow_ext, v_nnz, r_nnz;
694 &nrow_ext, &v_nnz, &r_nnz,
get_ptr(iw));
697 std::vector<casadi_int> sp_v(2 +
size2 + 1 + v_nnz);
698 std::vector<casadi_int> sp_r(2 +
size2 + 1 + r_nnz);
702 prinv.resize(nrow_ext);
707 casadi_int
Sparsity::dfs(casadi_int j, casadi_int top, std::vector<casadi_int>& xi,
708 std::vector<casadi_int>& pstack,
709 const std::vector<casadi_int>& pinv,
710 std::vector<bool>& marked)
const {
711 return (*this)->dfs(j, top, xi, pstack, pinv, marked);
714 casadi_int
Sparsity::scc(std::vector<casadi_int>& index, std::vector<casadi_int>& offset)
const {
715 casadi_assert(
is_square(),
"Expected a square pattern, but got " +
dim() +
".");
716 return (*this)->scc(index,
offset);
720 return (*this)->amd();
723 casadi_int
Sparsity::btf(std::vector<casadi_int>& rowperm, std::vector<casadi_int>& colperm,
724 std::vector<casadi_int>& rowblock, std::vector<casadi_int>& colblock,
725 std::vector<casadi_int>& coarse_rowblock,
726 std::vector<casadi_int>& coarse_colblock)
const {
728 return (*this)->btf(rowperm, colperm, rowblock, colblock,
729 coarse_rowblock, coarse_colblock);
730 }
catch (std::exception &e) {
731 CASADI_THROW_ERROR(
"btf", e.what());
736 (*this)->spsolve(
X,
B, tr);
740 return (*this)->rowsSequential(strictly);
744 *
this = (*this)->_removeDuplicates(mapping);
748 std::vector<casadi_int> loc;
754 (*this)->find(loc, ind1);
758 for (casadi_int k : indices) {
759 casadi_assert(k<
numel(),
"Index " +
str(k) +
" out of bounds for " +
dim() +
" pattern.");
761 (*this)->get_nz(indices);
773 const Dict& opts)
const {
776 }
catch (std::exception &e) {
777 CASADI_THROW_ERROR(
"star_coloring_new", e.what());
790 return (*this)->largest_first();
799 (*this)->spy_matlab(mfile);
803 const Dict& options)
const {
804 (*this)->export_code(lang, stream, options);
808 (*this)->spy(stream);
812 return (*this)->is_transpose(*y);
816 return (*this)->is_reshape(*y);
820 std::vector<casadi_int>& col)
const {
821 return (*this)->is_compactible(
row, col);
825 return (*this)->hash();
828 void Sparsity::assign_cached(casadi_int nrow, casadi_int ncol,
829 const std::vector<casadi_int>& colind,
830 const std::vector<casadi_int>& row,
bool order_rows) {
831 casadi_assert_dev(
colind.size()==ncol+1);
832 casadi_assert_dev(
row.size()==
colind.back());
836 void Sparsity::assign_cached(casadi_int nrow, casadi_int ncol,
837 const casadi_int* colind,
const casadi_int* row,
bool order_rows) {
839 if (ncol==0 && nrow==0) {
843 }
else if (ncol==1 && nrow==1) {
856 casadi_assert(
colind[0]==0,
857 "Compressed Column Storage is not sane. "
858 "First element of colind must be zero.");
861 for (casadi_int c=0; c<ncol; c++) {
863 "Compressed Column Storage is not sane. "
864 "colind must be monotone.");
868 bool rows_ordered =
true;
869 for (casadi_int c=0; c<ncol; ++c) {
870 casadi_int last_r = -1;
872 casadi_int r =
row[k];
874 casadi_assert(r>=0 && r<nrow,
875 "Compressed Column Storage is not sane.\n"
876 "row[ " +
str(k) +
" == " +
str(r) +
" not in range "
877 "[0, " +
str(nrow) +
")");
879 if (r<=last_r) rows_ordered =
false;
886 casadi_assert(order_rows,
887 "Compressed Column Storage is not sane.\n"
888 "Row indices not strictly monotonically increasing for each "
889 "column and reordering is not enabled.");
893 std::vector<casadi_int> col(
nnz);
894 for (casadi_int c=0; c<ncol; ++c) {
895 for (casadi_int k=
colind[c]; k<
colind[c+1]; ++k) col[k] = c;
905 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
907 std::lock_guard<std::mutex> lock(cachingmap_mtx);
914 casadi_int bucket_count_before = cache.bucket_count();
917 if (bucket_count_before>0) {
920 std::pair<CachingMap::iterator, CachingMap::iterator> eq = cache.equal_range(h);
923 for (CachingMap::iterator i=eq.first; i!=eq.second; ++i) {
926 WeakRef& wref = i->second;
929 SharedObject ref_shared;
932 if (wref.shared_if_alive(ref_shared)) {
935 Sparsity ref = shared_cast<Sparsity>(ref_shared);
938 if (ref.is_equal(nrow, ncol,
colind,
row)) {
951 CachingMap::iterator j=i;
953 for (; j!=eq.second; ++j) {
956 SharedObject ref_shared;
957 if (j->second.shared_if_alive(ref_shared)) {
960 Sparsity ref = shared_cast<Sparsity>(ref_shared);
963 if (ref.is_equal(nrow, ncol,
colind,
row)) {
986 cache.insert(std::pair<std::size_t, WeakRef>(h, *
this));
989 casadi_int bucket_count_after = cache.bucket_count();
992 if (bucket_count_before!=bucket_count_after) {
993 CachingMap::const_iterator i=cache.begin();
994 while (i!=cache.end()) {
995 if (!i->second.alive()) {
1004 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
1005 std::mutex Sparsity::cachingmap_mtx;
1009 return x->
_tril(includeDiagonal);
1013 return x->
_triu(includeDiagonal);
1017 return (*this)->get_lower();
1021 return (*this)->get_upper();
1025 std::size_t
hash_sparsity(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& colind,
1026 const std::vector<casadi_int>& row) {
1031 const casadi_int* colind,
const casadi_int* row) {
1042 casadi_assert(nrow>=0 && ncol>=0,
1043 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
1045 std::vector<casadi_int>
colind(ncol+1);
1046 for (casadi_int cc=0; cc<ncol+1; ++cc)
colind[cc] = cc*nrow;
1049 std::vector<casadi_int>
row(ncol*nrow);
1050 for (casadi_int cc=0; cc<ncol; ++cc)
1051 for (casadi_int rr=0; rr<nrow; ++rr)
1052 row[rr+cc*nrow] = rr;
1058 casadi_assert(n>=0,
"Sparsity::upper expects a positive integer as argument");
1059 casadi_int nrow=n, ncol=n;
1062 row.reserve((n*(n+1))/2);
1066 for (casadi_int cc=0; cc<ncol; ++cc) {
1068 for (casadi_int rr=0; rr<=cc; ++rr) {
1079 casadi_assert(n>=0,
"Sparsity::lower expects a positive integer as argument");
1080 casadi_int nrow=n, ncol=n;
1083 row.reserve((n*(n+1))/2);
1087 for (casadi_int cc=0; cc<ncol; ++cc) {
1089 for (casadi_int rr=cc; rr<nrow; ++rr) {
1100 casadi_assert(n>=0,
"Sparsity::band expects a positive integer as argument");
1101 casadi_assert((p<0? -p : p)<n,
1102 "Sparsity::band: position of band should be smaller than size argument");
1104 casadi_int nc = n-(p<0? -p : p);
1106 std::vector< casadi_int >
row(nc);
1108 casadi_int
offset = std::max(p, casadi_int(0));
1109 for (casadi_int i=0;i<nc;i++) {
1113 std::vector< casadi_int >
colind(n+1);
1115 offset = std::min(p, casadi_int(0));
1116 for (casadi_int i=0;i<n+1;i++) {
1117 colind[i] = std::max(std::min(i+
offset, nc), casadi_int(0));
1127 p = std::min(p, n-1);
1128 for (casadi_int i=-p;i<=p;++i) {
1135 std::vector<casadi_int>
row(1, el),
colind(2);
1142 casadi_int nrow, casadi_int ncol) {
1143 std::vector<casadi_int> all_rows, all_cols;
1144 all_rows.reserve(
row.size()*col.size());
1145 all_cols.reserve(
row.size()*col.size());
1146 for (std::vector<casadi_int>::const_iterator c_it=col.begin(); c_it!=col.end(); ++c_it) {
1147 casadi_assert(*c_it>=0 && *c_it<ncol,
"Sparsity::rowcol: Column index out of bounds");
1148 for (std::vector<casadi_int>::const_iterator r_it=
row.begin(); r_it!=
row.end(); ++r_it) {
1149 casadi_assert(*r_it>=0 && *r_it<nrow,
"Sparsity::rowcol: Row index out of bounds");
1150 all_rows.push_back(*r_it);
1151 all_cols.push_back(*c_it);
1158 const std::vector<casadi_int>& col, std::vector<casadi_int>& mapping,
1159 bool invert_mapping) {
1161 casadi_assert(nrow>=0 && ncol>=0,
1162 "Dimensions must be non-negative, got " +
str(nrow) +
"-by-" +
str(ncol));
1163 casadi_assert(col.size()==
row.size(),
"inconsistent lengths");
1166 std::vector<casadi_int> r_colind(ncol+1, 0);
1167 std::vector<casadi_int> r_row;
1168 r_row.reserve(
row.size());
1171 casadi_int last_col=-1, last_row=-1;
1172 bool perfectly_ordered=
true;
1173 for (casadi_int k=0; k<col.size(); ++k) {
1175 casadi_assert(col[k]>=0 && col[k]<ncol,
1176 "Column index (" +
str(col[k]) +
") out of bounds [0," +
str(ncol) +
"[");
1177 casadi_assert(
row[k]>=0 &&
row[k]<nrow,
1178 "Row index (" +
str(
row[k]) +
") out of bounds [0," +
str(nrow) +
"[");
1181 perfectly_ordered = perfectly_ordered && (col[k]<last_col ||
1182 (col[k]==last_col &&
row[k]<=last_row));
1188 if (perfectly_ordered) {
1190 r_row.resize(
row.size());
1191 std::copy(
row.begin(),
row.end(), r_row.begin());
1195 for (casadi_int i=0; i<ncol; ++i) {
1196 while (el<col.size() && col[el]==i) el++;
1201 mapping.resize(
row.size());
1202 for (casadi_int k=0; k<
row.size(); ++k) mapping[k] = k;
1205 return Sparsity(nrow, ncol, r_colind, r_row);
1209 std::vector<casadi_int>& mapping1 = invert_mapping ? r_row : mapping;
1210 std::vector<casadi_int>& mapping2 = invert_mapping ? mapping : r_row;
1213 mapping1.reserve(std::max(nrow+1,
static_cast<casadi_int
>(col.size())));
1216 std::vector<casadi_int>& rowcount = mapping1;
1217 rowcount.resize(nrow+1);
1218 std::fill(rowcount.begin(), rowcount.end(), 0);
1219 for (std::vector<casadi_int>::const_iterator it=
row.begin(); it!=
row.end(); ++it) {
1224 for (casadi_int i=0; i<nrow; ++i) {
1225 rowcount[i+1] += rowcount[i];
1229 mapping2.resize(
row.size());
1230 for (casadi_int k=0; k<
row.size(); ++k) {
1231 mapping2[rowcount[
row[k]]++] = k;
1236 std::vector<casadi_int>& colcount = r_colind;
1238 for (std::vector<casadi_int>::const_iterator it=mapping2.begin(); it!=mapping2.end(); ++it) {
1239 colcount[col[*it]+1]++;
1243 for (casadi_int i=0; i<ncol; ++i) {
1244 colcount[i+1] += colcount[i];
1248 mapping1.resize(col.size());
1249 for (std::vector<casadi_int>::const_iterator it=mapping2.begin(); it!=mapping2.end(); ++it) {
1250 mapping1[colcount[col[*it]]++] = *it;
1254 casadi_int r_el = 0;
1255 r_row.resize(col.size());
1258 std::vector<casadi_int>::const_iterator it=mapping1.begin();
1262 for (casadi_int i=0; i<ncol; ++i) {
1265 casadi_int j_prev = -1;
1268 while (it!=mapping1.end() && col[*it]==i) {
1271 casadi_int el = *it;
1275 casadi_int j =
row[el];
1281 if (invert_mapping) {
1283 mapping2[el] = r_el-1;
1287 mapping1[r_el-1] = el;
1295 r_colind[i+1] = r_el;
1302 if (!invert_mapping) {
1303 mapping1.resize(r_el);
1306 return Sparsity(nrow, ncol, r_colind, r_row);
1310 const std::vector<casadi_int>& col) {
1311 std::vector<casadi_int> mapping;
1316 const std::vector<casadi_int>& nz,
bool ind1) {
1317 casadi_assert(nrow>0,
"nrow must be >0.");
1318 std::vector<casadi_int>
row(nz.size());
1319 std::vector<casadi_int> col(nz.size());
1320 for (casadi_int i=0;i<nz.size();++i) {
1321 casadi_int k = nz[i];
1331 "is_singular: only defined for square matrices, but got " +
dim());
1341 return (*this)->sp();
1344 Sparsity::operator
const std::vector<casadi_int>&()
const {
1345 return (*this)->sp();
1349 const casadi_int* sp = *
this;
1350 casadi_int nrow = sp[0], ncol = sp[1];
1351 const casadi_int* colind = sp+2, *row = sp+2+ncol+1;
1357 casadi_assert_dev(v.size() >= 2);
1358 casadi_int nrow = v[0];
1359 casadi_int ncol = v[1];
1362 casadi_assert_dev(v.size() >= 2 + ncol+1);
1363 casadi_int
nnz = v[2 + ncol];
1365 bool sparse = v.size() == 2 + ncol+1 +
nnz;
1366 casadi_assert_dev(
dense || sparse);
1373 casadi_assert_dev(v!=
nullptr);
1376 casadi_int nrow = v[0];
1377 casadi_int ncol = v[1];
1378 const casadi_int *
colind = v+2;
1384 if (nrow*ncol ==
nnz) {
1389 const casadi_int *
row = v + 2 + ncol+1;
1392 std::vector<casadi_int>(
row,
row+
nnz), order_rows);
1398 "Sparsity::permutation supplied list is not a permutation.");
1399 std::vector<casadi_int>
colind =
range(p.size()+1);
1408 casadi_assert(
is_permutation(),
"Sparsity::permutation called on non-permutation matrix.");
1417 return (*this)->bw_upper();
1421 return (*this)->bw_lower();
1426 if (sp.empty())
return Sparsity(1, 0);
1427 if (sp.size()==1)
return sp.front();
1430 casadi_int nnz_total = 0;
1431 for (casadi_int i=0; i<sp.size(); ++i) nnz_total += sp[i].
nnz();
1434 std::vector<casadi_int> ret_row, ret_col;
1435 ret_row.reserve(nnz_total);
1436 ret_col.reserve(nnz_total);
1437 casadi_int ret_ncol = 0;
1438 casadi_int ret_nrow = 0;
1439 for (casadi_int i=0; i<sp.size() && ret_nrow==0; ++i)
1440 ret_nrow = sp[i].
size1();
1443 for (std::vector<Sparsity>::const_iterator i=sp.begin(); i!=sp.end(); ++i) {
1445 casadi_int sp_nrow = i->size1();
1446 casadi_int sp_ncol = i->size2();
1447 const casadi_int* sp_colind = i->colind();
1448 const casadi_int* sp_row = i->row();
1449 casadi_assert(sp_nrow==ret_nrow || sp_nrow==0,
1450 "Sparsity::horzcat: Mismatching number of rows");
1453 for (casadi_int cc=0; cc<sp_ncol; ++cc) {
1454 for (casadi_int k=sp_colind[cc]; k<sp_colind[cc+1]; ++k) {
1455 ret_row.push_back(sp_row[k]);
1456 ret_col.push_back(cc + ret_ncol);
1461 ret_ncol += sp_ncol;
1467 casadi_int a_ncol = a.
size2();
1468 casadi_int b_ncol = b.size2();
1469 casadi_int a_nrow = a.
size1();
1470 casadi_int b_nrow = b.size1();
1473 const casadi_int* a_colind = a.
colind();
1474 const casadi_int* a_row = a.
row();
1475 const casadi_int* b_colind = b.colind();
1476 const casadi_int* b_row = b.row();
1478 std::vector<casadi_int> r_colind(a_ncol*b_ncol+1, 0);
1479 std::vector<casadi_int> r_row(a.
nnz()*b.nnz());
1481 casadi_int* r_colind_ptr =
get_ptr(r_colind);
1482 casadi_int* r_row_ptr =
get_ptr(r_row);
1487 for (casadi_int a_cc=0; a_cc<a_ncol; ++a_cc) {
1488 casadi_int a_start = a_colind[a_cc];
1489 casadi_int a_stop = a_colind[a_cc+1];
1491 for (casadi_int b_cc=0; b_cc<b_ncol; ++b_cc) {
1492 casadi_int b_start = b_colind[b_cc];
1493 casadi_int b_stop = b_colind[b_cc+1];
1495 for (casadi_int a_el=a_start; a_el<a_stop; ++a_el) {
1496 casadi_int a_r = a_row[a_el];
1498 for (casadi_int b_el=b_start; b_el<b_stop; ++b_el) {
1499 casadi_int b_r = b_row[b_el];
1500 r_row_ptr[i++] = a_r*b_nrow+b_r;
1504 r_colind_ptr[j] = r_colind_ptr[j-1] + (b_stop-b_start)*(a_stop-a_start);
1507 return Sparsity(a_nrow*b_nrow, a_ncol*b_ncol, r_colind, r_row);
1511 casadi_int xrow = sp_x.
size1();
1512 casadi_int xcol = sp_x.
size2();
1513 casadi_assert(xrow > 0 && xcol > 0,
1514 "Sparsity::kron_contract: sp_x must be nonempty");
1515 casadi_assert(sp_m.
size1() % xrow == 0 && sp_m.
size2() % xcol == 0,
1516 "Sparsity::kron_contract: sp_m dims must be multiples of sp_x dims");
1517 casadi_int yrow = sp_m.
size1() / xrow;
1518 casadi_int ycol = sp_m.
size2() / xcol;
1521 casadi_int split_r = inner ? xrow : yrow;
1522 casadi_int split_c = inner ? xcol : ycol;
1524 std::vector<bool> x_dense(xrow * xcol,
false);
1525 const casadi_int* x_colind = sp_x.
colind();
1526 const casadi_int* x_row = sp_x.
row();
1527 for (casadi_int cc = 0; cc < xcol; ++cc) {
1528 for (casadi_int el = x_colind[cc]; el < x_colind[cc+1]; ++el) {
1529 x_dense[cc*xrow + x_row[el]] =
true;
1534 std::vector<bool> y_dense(yrow * ycol,
false);
1535 const casadi_int* m_colind = sp_m.
colind();
1536 const casadi_int* m_row = sp_m.
row();
1537 casadi_int outer_c_count = sp_m.
size2() / split_c;
1538 for (casadi_int outer_c = 0; outer_c < outer_c_count; ++outer_c) {
1539 for (casadi_int inner_c = 0; inner_c < split_c; ++inner_c) {
1540 casadi_int cc = outer_c*split_c + inner_c;
1541 casadi_int y_c = inner ? outer_c : inner_c;
1542 casadi_int x_c = inner ? inner_c : outer_c;
1543 for (casadi_int el = m_colind[cc]; el < m_colind[cc+1]; ++el) {
1544 casadi_int rr = m_row[el];
1545 casadi_int outer_r = rr / split_r;
1546 casadi_int inner_r = rr % split_r;
1547 casadi_int y_r = inner ? outer_r : inner_r;
1548 casadi_int x_r = inner ? inner_r : outer_r;
1549 if (x_dense[x_c*xrow + x_r]) {
1550 y_dense[y_c*yrow + y_r] =
true;
1556 std::vector<casadi_int> y_colind(ycol + 1, 0);
1557 std::vector<casadi_int> y_row;
1558 for (casadi_int j = 0; j < ycol; ++j) {
1559 for (casadi_int i = 0; i < yrow; ++i) {
1560 if (y_dense[j*yrow + i]) y_row.push_back(i);
1562 y_colind[j+1] = y_row.size();
1564 return Sparsity(yrow, ycol, y_colind, y_row);
1569 if (sp.empty())
return Sparsity(0, 1);
1570 if (sp.size()==1)
return sp.front();
1573 casadi_int nnz_total = 0;
1574 for (casadi_int i=0; i<sp.size(); ++i) nnz_total += sp[i].
nnz();
1577 std::vector<casadi_int> ret_row, ret_col;
1578 ret_row.reserve(nnz_total);
1579 ret_col.reserve(nnz_total);
1580 casadi_int ret_nrow = 0;
1581 casadi_int ret_ncol = 0;
1582 for (casadi_int i=0; i<sp.size() && ret_ncol==0; ++i)
1583 ret_ncol = sp[i].
size2();
1586 for (std::vector<Sparsity>::const_iterator i=sp.begin(); i!=sp.end(); ++i) {
1588 casadi_int sp_nrow = i->size1();
1589 casadi_int sp_ncol = i->size2();
1590 const casadi_int* sp_colind = i->colind();
1591 const casadi_int* sp_row = i->row();
1592 casadi_assert(sp_ncol==ret_ncol || sp_ncol==0,
1593 "Sparsity::vertcat: Mismatching number of columns");
1596 for (casadi_int cc=0; cc<sp_ncol; ++cc) {
1597 for (casadi_int k=sp_colind[cc]; k<sp_colind[cc+1]; ++k) {
1598 ret_row.push_back(sp_row[k] + ret_nrow);
1599 ret_col.push_back(cc);
1604 ret_nrow += sp_nrow;
1613 std::vector<casadi_int>
colind(1, 0);
1614 std::vector<casadi_int>
row;
1617 for (casadi_int i=0;i<v.size();++i) {
1618 const casadi_int* colind_ = v[i].colind();
1619 casadi_int ncol = v[i].size2();
1620 const casadi_int* row_ = v[i].row();
1621 casadi_int sz = v[i].nnz();
1622 for (casadi_int k=1; k<ncol+1; ++k) {
1623 colind.push_back(colind_[k]+nz);
1625 for (casadi_int k=0; k<sz; ++k) {
1626 row.push_back(row_[k]+m);
1637 const std::vector<casadi_int>& offset) {
1642 casadi_int n =
offset.size()-1;
1645 const casadi_int* colind_x = x.
colind();
1646 const casadi_int* row_x = x.
row();
1649 std::vector<Sparsity> ret;
1654 casadi_int ncol, nrow = x.
size1();
1657 for (casadi_int i=0; i<n; ++i) {
1658 casadi_int first_col =
offset[i];
1659 casadi_int last_col =
offset[i+1];
1660 ncol = last_col - first_col;
1664 std::copy(colind_x+first_col, colind_x+last_col+1,
colind.begin());
1665 for (std::vector<casadi_int>::iterator it=
colind.begin()+1; it!=
colind.end(); ++it)
1669 std::copy(row_x+colind_x[first_col], row_x+colind_x[last_col],
row.begin());
1680 const std::vector<casadi_int>& offset) {
1682 for (std::vector<Sparsity>::iterator it=ret.begin(); it!=ret.end(); ++it) {
1689 std::vector< Sparsity > ret;
1690 for (casadi_int i=0; i<v.size(); ++i)
1691 if (!v[i].empty()) ret.push_back(
horzcat(v[i]));
1692 if (ret.empty())
return Sparsity(0, 0);
1697 const std::vector<casadi_int>& offset1,
1698 const std::vector<casadi_int>& offset2) {
1702 casadi_assert(offset1.size()==offset2.size(),
1703 "diagsplit: offset1 and offset2 must have the same length");
1706 casadi_int n = offset1.size()-1;
1709 std::vector<Sparsity> ret;
1715 for (casadi_int i=0; i<n; ++i) {
1716 ret.push_back(x2(
Slice(offset1[i], offset1[i+1]),
1717 Slice(offset2[i], offset2[i+1])).sparsity());
1718 nnz += ret.back().nnz();
1720 casadi_assert(
nnz==x.
nnz(),
1721 "diagsplit: the presence of nonzeros outside the diagonal blocks is unsupported.");
1735 std::vector<casadi_int> rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock;
1736 x.
btf(rowperm, colperm, rowblock, colblock, coarse_rowblock, coarse_colblock);
1737 return coarse_colblock.at(3);
1740 Sparsity::operator
const casadi_int*()
const {
1741 return &(*this)->sp().front();
1746 casadi_assert(A.
size1()==x.
size2(),
"Dimension error. Got " + x.
dim()
1747 +
" times " + A.
dim() +
".");
1749 casadi_int n_row = A.
size2();
1750 casadi_int n_col = x.
size1();
1753 std::vector<bool> Bwork(n_col);
1754 std::vector<casadi_int> Iwork(n_row+1+n_col);
1756 const casadi_int* Aj = A.
row();
1757 const casadi_int* Ap = A.
colind();
1758 const casadi_int* Bj = x.
row();
1759 const casadi_int* Bp = x.
colind();
1760 casadi_int *Cp =
get_ptr(Iwork);
1761 casadi_int *mask = Cp+n_row+1;
1765 std::fill(mask, mask+n_col, -1);
1769 for (casadi_int i = 0; i < n_row; i++) {
1770 casadi_int row_nnz = 0;
1771 for (casadi_int jj = Ap[i]; jj < Ap[i+1]; jj++) {
1772 casadi_int j = Aj[jj];
1773 for (casadi_int kk = Bp[j]; kk < Bp[j+1]; kk++) {
1774 casadi_int k = Bj[kk];
1781 casadi_int next_nnz =
nnz + row_nnz;
1787 casadi_int *next =
get_ptr(Iwork) + n_row+1;
1788 std::fill(next, next+n_col, -1);
1789 std::vector<bool> & sums = Bwork;
1790 std::fill(sums.begin(), sums.end(),
false);
1793 for (casadi_int i = 0; i < n_row; i++) {
1794 casadi_int head = -2;
1795 casadi_int length = 0;
1796 casadi_int jj_start = Ap[i];
1797 casadi_int jj_end = Ap[i+1];
1798 for (casadi_int jj = jj_start; jj < jj_end; jj++) {
1799 casadi_int j = Aj[jj];
1800 casadi_int kk_start = Bp[j];
1801 casadi_int kk_end = Bp[j+1];
1802 for (casadi_int kk = kk_start; kk < kk_end; kk++) {
1803 casadi_int k = Bj[kk];
1805 if (next[k] == -1) {
1812 for (casadi_int jj = 0; jj < length; jj++) {
1816 casadi_int temp = head;
1829 template<
bool COMBINE_AND>
1836 "Dimension error. Got x=" + x_sp.
dim() +
", y=" + y_sp.
dim()
1837 +
" and z=" + z_sp.
dim() +
".");
1840 const casadi_int* y_colind = y_sp.
colind();
1841 const casadi_int* y_row = y_sp.
row();
1842 const casadi_int* x_colind = x_sp.
colind();
1843 const casadi_int* x_row = x_sp.
row();
1844 const casadi_int* z_colind = z_sp.
colind();
1845 const casadi_int* z_row = z_sp.
row();
1848 casadi_int ncol = z_sp.
size2();
1849 for (casadi_int cc=0; cc<ncol; ++cc) {
1851 for (casadi_int kk=z_colind[cc]; kk<z_colind[cc+1]; ++kk) {
1852 w[z_row[kk]] = z[kk];
1856 for (casadi_int kk=y_colind[cc]; kk<y_colind[cc+1]; ++kk) {
1857 casadi_int rr = y_row[kk];
1861 for (casadi_int kk1=x_colind[rr]; kk1<x_colind[rr+1]; ++kk1) {
1862 w[x_row[kk1]] |= COMBINE_AND ? (x[kk1] & yy) : (x[kk1] | yy);
1867 for (casadi_int kk=z_colind[cc]; kk<z_colind[cc+1]; ++kk) {
1868 z[kk] = w[z_row[kk]];
1877 mul_bvec_fwd<false>(x, x_sp, y, y_sp, z, z_sp, w);
1884 mul_bvec_fwd<true>(x, x_sp, y, y_sp, z, z_sp, w);
1894 "Dimension error. Got x=" + x_sp.
dim() +
", y=" + y_sp.
dim()
1895 +
" and z=" + z_sp.
dim() +
".");
1898 const casadi_int* y_colind = y_sp.
colind();
1899 const casadi_int* y_row = y_sp.
row();
1900 const casadi_int* x_colind = x_sp.
colind();
1901 const casadi_int* x_row = x_sp.
row();
1902 const casadi_int* z_colind = z_sp.
colind();
1903 const casadi_int* z_row = z_sp.
row();
1908 casadi_int nrow = z_sp.
size1();
1912 casadi_int ncol = z_sp.
size2();
1913 for (casadi_int cc=0; cc<ncol; ++cc) {
1915 for (casadi_int kk=z_colind[cc]; kk<z_colind[cc+1]; ++kk) {
1916 w[z_row[kk]] = z[kk];
1920 for (casadi_int kk=y_colind[cc]; kk<y_colind[cc+1]; ++kk) {
1921 casadi_int rr = y_row[kk];
1925 for (casadi_int kk1=x_colind[rr]; kk1<x_colind[rr+1]; ++kk1) {
1926 yy |= w[x_row[kk1]];
1927 x[kk1] |= w[x_row[kk1]];
1933 for (casadi_int kk=z_colind[cc]; kk<z_colind[cc+1]; ++kk) {
1934 z[kk] = w[z_row[kk]];
1944 std::vector<unsigned char> mapping;
1945 X.unite(x, mapping);
1948 const casadi_int* Y_colind =
Y.colind();
1949 const casadi_int* Y_row =
Y.row();
1950 std::vector<casadi_int> y_colind(
Y.size2()+1, 0);
1951 std::vector<casadi_int> y_row;
1952 y_row.reserve(
Y.nnz());
1953 casadi_assert_dev(
Y.nnz()==mapping.size());
1957 for (casadi_int cc=0; cc<
Y.size2(); ++cc) {
1958 y_colind[cc+1] = y_colind[cc];
1960 for (casadi_int kk=Y_colind[cc]; kk<Y_colind[cc+1]; ++kk) {
1962 casadi_int e = mapping[i++];
1966 y_row.push_back(Y_row[kk]);
1968 casadi_assert_dev(e==1);
1973 Sparsity ret(
Y.size1(),
Y.size2(), y_colind, y_row,
true);
1985 const std::string& format_hint,
const std::set<std::string>& file_formats) {
1986 if (format_hint.empty()) {
1990 "Extension '" + extension +
"' not recognised. "
1996 "File format hint '" + format_hint +
"' not recognised. "
2005 std::ostream& out = *out_ptr;
2006 if (format==
"mtx") {
2007 out << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1);
2008 out <<
"%%MatrixMarket matrix coordinate pattern general" << std::endl;
2009 out <<
size1() <<
" " <<
size2() <<
" " <<
nnz() << std::endl;
2011 std::vector<casadi_int> col =
get_col();
2013 for (casadi_int k=0;k<
row.size();++k) {
2014 out <<
row[k]+1 <<
" " << col[k]+1 << std::endl;
2017 casadi_error(
"Unknown format '" + format +
"'");
2024 std::istream& in = *in_ptr;
2025 if (format==
"mtx") {
2027 std::vector<casadi_int>
row, col;
2030 while (std::getline(in, line)) {
2032 if (!line.empty() && line.back()==
'\r') line.pop_back();
2033 casadi_assert(line==
"%%MatrixMarket matrix coordinate pattern general",
"Wrong header");
2035 }
else if (line_num==1) {
2036 std::stringstream stream(line);
2044 std::stringstream stream(line);
2054 casadi_error(
"Unknown format '" + format +
"'");
2059 bool with_x_diag,
bool with_lam_g_diag) {
2061 casadi_assert(H.
is_square(),
"H must be square");
2062 casadi_assert(H.
size1() == J.
size2(),
"Dimension mismatch");
2065 if (with_x_diag)
return kkt(H +
diag(H.
size()), J,
false, with_lam_g_diag);
2087 s.
pack(
"SparsityInternal::compressed", std::vector<casadi_int>{});
2094 std::vector<casadi_int> i;
2095 s.
unpack(
"SparsityInternal::compressed", i);
2104 std::stringstream ss;
2110 std::stringstream ss;
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
static std::unique_ptr< std::istream > ifstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::in, bool fail=true)
static MatType zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
SharedObjectInternal * get() const
Get a const pointer to the node.
bool is_null() const
Is a null pointer?
void own(SharedObjectInternal *node)
SharedObjectInternal * operator->() const
Access a member function or object.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
static std::vector< casadi_int > offset(const std::vector< Sparsity > &v, bool vert=true)
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.
Sparsity makeDense(std::vector< casadi_int > &mapping) const
Make a patten dense.
Sparsity _mtimes(const Sparsity &y) const
Sparsity pattern for a matrix-matrix product (details in 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 star_coloring_new(std::vector< casadi_int > &which_color, const Dict &opts) const
Perform a star coloring.
Sparsity transpose(std::vector< casadi_int > &mapping, bool invert_mapping=false) const
Transpose the matrix and get the reordering of the non-zero entries,.
Sparsity _appendColumns(const SparsityInternal &sp) const
Append another sparsity patten horizontally.
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.
Sparsity _tril(bool includeDiagonal) const
Get lower triangular part.
Sparsity _appendVector(const SparsityInternal &sp) const
Append another sparsity patten vertically (vectors only)
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.
Sparsity _triu(bool includeDiagonal) const
Get upper triangular part.
Sparsity uni_coloring(const Sparsity &AT, casadi_int cutoff) const
Perform a unidirectional coloring.
Sparsity T() const
Transpose the matrix.
Sparsity _reshape(casadi_int nrow, casadi_int ncol) const
Reshape a sparsity, order of nonzeros remains the same.
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.
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
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.
std::vector< casadi_int > get_upper() const
Nonzero indices of the entries in the upper triangular part (row <= col)
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Nonzero index of entry (rr, cc), or -1 if it is a structural zero.
Sparsity pmult(const std::vector< casadi_int > &p, bool permute_rows=true, bool permute_columns=true, bool invert_permutation=false) const
Permute the rows and/or columns of the pattern.
Sparsity(casadi_int dummy=0)
Default constructor: a null object that holds no pattern.
static Sparsity banded(casadi_int n, casadi_int p)
Create a banded square sparsity pattern.
bool is_subset(const Sparsity &rhs) const
Check whether every nonzero of this pattern is also a nonzero of rhs.
static Sparsity upper(casadi_int n)
Create an upper triangular square sparsity pattern.
static const Sparsity & getScalar()
(Dense) scalar
bool is_stacked(const Sparsity &y, casadi_int n) const
Check whether the pattern is n copies of y placed side by side.
Sparsity makeDense(std::vector< casadi_int > &mapping) const
Dense pattern of the same shape, with the flat index of every nonzero.
Sparsity intersect(const Sparsity &y, std::vector< unsigned char > &mapping) const
Intersection of two sparsity patterns of the same shape (also the * operator)
static Sparsity vertcat(const std::vector< Sparsity > &sp)
Accessed by SparsityInterface.
bool is_vector() const
Check whether the pattern is a row or a column vector.
std::vector< casadi_int > erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Turn the entries with rows rr and columns cc into structural zeros, in place.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Pattern of the submatrix with rows rr and columns cc.
casadi_int numel() const
Total number of entries, structural zeros included, i.e. size1()*size2()
static CachingMap & getCache()
Cached sparsity patterns.
std::unordered_multimap< std::size_t, WeakRef > CachingMap
casadi_int size1() const
Number of rows.
void enlarge(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the pattern in place by inserting empty rows and columns.
std::vector< casadi_int > find(bool ind1=SWIG_IND1) const
Flat (column-major) element index of every nonzero.
static Sparsity permutation(const std::vector< casadi_int > &p, bool invert=false)
Construct the pattern of a permutation matrix P from a permutation vector p.
static std::set< std::string > file_formats
Dict info() const
The pattern as a dictionary with entries nrow, ncol, colind and row.
static const Sparsity & getScalarSparse()
(Sparse) scalar
Sparsity star_coloring(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Star coloring of a symmetric pattern (greedy distance-2 coloring)
static Sparsity rowcol(const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, casadi_int nrow, casadi_int ncol)
Create the pattern of a block: all entries (i, j) with i in row and j in col.
Sparsity pattern_inverse() const
Complement of the pattern: structural zeros become nonzeros and vice versa.
static Sparsity diag(casadi_int nrow)
Create a diagonal sparsity pattern.
casadi_int dfs(casadi_int j, casadi_int top, std::vector< casadi_int > &SWIG_INOUT1(xi), std::vector< casadi_int > &SWIG_INOUT2(pstack), const std::vector< casadi_int > &pinv, std::vector< bool > &SWIG_INOUT3(marked)) const
Depth-first search on the adjacency graph of the sparsity.
static Sparsity sum2(const Sparsity &x)
Accessed by SparsityInterface.
bool is_orthonormal(bool allow_empty=false) const
Check whether every row and every column has at most one nonzero.
const std::vector< casadi_int > permutation_vector(bool invert=false) const
Recover the permutation vector p from the pattern of a permutation matrix.
casadi_int nnz_lower(bool strictly=false) const
Number of nonzeros in the lower triangular part, i.e. entries (i, j) with i >= j.
casadi_int scc(std::vector< casadi_int > &index, std::vector< casadi_int > &offset) const
Strongly connected components of the directed graph of a square pattern.
std::string dim(bool with_nz=false) const
Dimensions as a string "nrow x ncol", optionally with the number of nonzeros.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
static Sparsity triu(const Sparsity &x, bool includeDiagonal=true)
Accessed by SparsityInterface.
Sparsity transpose(std::vector< casadi_int > &mapping, bool invert_mapping=false) const
Transposed pattern together with the reordering of the nonzeros.
Sparsity T() const
Transposed pattern.
bool is_column() const
Check whether the pattern is a column vector, i.e. size2() == 1.
Sparsity unite(const Sparsity &y, std::vector< unsigned char > &mapping) const
Union of two sparsity patterns of the same shape (also available as the + operator)
void spsolve(bvec_t *X, bvec_t *B, bool tr) const
Propagate sparsity through a linear solve.
void spy(std::ostream &stream=casadi::uout()) const
Print a textual picture of the pattern.
bool is_compactible(std::vector< casadi_int > &row, std::vector< casadi_int > &col) const
Check if the nonzero pattern is the Cartesian product of a row and a column subset.
bool is_reshape(const Sparsity &y) const
Check whether y is a reshape of this pattern.
void get_crs(std::vector< casadi_int > &rowind, std::vector< casadi_int > &col) const
The pattern in compressed row storage: the rowind and col vectors.
static std::string file_format(const std::string &filename, const std::string &format_hint, const std::set< std::string > &file_formats)
SparsityInternal * get() const
void removeDuplicates(std::vector< casadi_int > &mapping)
Remove duplicate entries, in place.
static Sparsity deserialize(std::istream &stream)
Build a Sparsity from a serialized stream.
bool is_scalar(bool scalar_and_dense=false) const
Check whether the pattern is 1-by-1.
std::vector< casadi_int > get_lower() const
Nonzero indices of the entries in the lower triangular part (row >= col)
bool has_nz(casadi_int rr, casadi_int cc) const
Check whether entry (rr, cc) is a structural nonzero.
bool is_orthonormal_rows(bool allow_empty=false) const
Check whether the rows are orthonormal: one nonzero per row, at most one per column.
static Sparsity blockcat(const std::vector< std::vector< Sparsity > > &v)
Accessed by SparsityInterface.
void enlargeColumns(casadi_int ncol, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the pattern in place by inserting empty columns.
static Sparsity create(SparsityInternal *node)
Create from node.
const SparsityInternal * operator->() const
Access a member function or object.
void append(const Sparsity &sp)
Append a pattern below this one, in place (vertical concatenation)
casadi_int add_nz(casadi_int rr, casadi_int cc)
Nonzero index of entry (rr, cc), inserting the entry into the pattern if needed.
bool is_row() const
Check whether the pattern is a row vector, i.e. size1() == 1.
Sparsity get_diag(std::vector< casadi_int > &mapping) const
Pattern of the diagonal of a matrix, or of the diagonal matrix built from a vector.
static Sparsity tril(const Sparsity &x, bool includeDiagonal=true)
Accessed by SparsityInterface.
std::vector< casadi_int > etree(bool ata=false) const
Elimination tree of the pattern.
static Sparsity unit(casadi_int n, casadi_int el)
Create the pattern of a unit vector: a column of length n with one nonzero.
bool is_diag() const
Check whether the pattern is square with exactly the full diagonal as nonzeros.
std::vector< casadi_int > get_col() const
Column index of every nonzero, in nonzero (column-major) order.
static std::vector< Sparsity > vertsplit(const Sparsity &x, const std::vector< casadi_int > &offset)
Accessed by SparsityInterface.
Sparsity star_coloring_new(std::vector< casadi_int > &which_color, const Dict &opts=Dict()) const
Star coloring of a symmetric pattern, with the color that recovers each nonzero.
static Sparsity reshape(const Sparsity &x, casadi_int nrow, casadi_int ncol)
Accessed by SparsityInterface.
bool is_equal(const Sparsity &y) const
Check whether two sparsity patterns are identical.
static const Sparsity & getEmpty()
Empty zero-by-zero.
static void mul_sparsityR(bvec_t *x, const Sparsity &x_sp, bvec_t *y, const Sparsity &y_sp, bvec_t *z, const Sparsity &z_sp, bvec_t *w)
Propagate sparsity using 0-1 logic through a matrix product,.
static std::vector< Sparsity > horzsplit(const Sparsity &x, const std::vector< casadi_int > &offset)
Accessed by SparsityInterface.
void enlargeRows(casadi_int nrow, const std::vector< casadi_int > &rr, bool ind1=false)
Enlarge the pattern in place by inserting empty rows.
bool is_tril(bool strictly=false) const
Check whether all nonzeros are on or below the diagonal (row >= col)
Sparsity combine(const Sparsity &y, bool f0x_is_zero, bool function0_is_zero, std::vector< unsigned char > &mapping) const
Combine two patterns of the same shape, as the result of a binary operation.
std::vector< casadi_int > amd() const
Approximate minimum degree (AMD) ordering of a symmetric pattern.
void spy_matlab(const std::string &mfile) const
Write a MATLAB/Octave script that builds the pattern as a sparse matrix and calls spy.
casadi_int nnz_upper(bool strictly=false) const
Number of nonzeros in the upper triangular part, i.e. entries (i, j) with i <= j.
casadi_int nnz() const
Number of structural nonzeros.
casadi_int size2() const
Number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
casadi_int btf(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
Block triangular form (BTF) through the Dulmage-Mendelsohn decomposition.
std::string serialize() const
Serialize the pattern to a string.
bool is_selection(bool allow_empty=false) const
Check whether the pattern is that of a selection matrix.
std::pair< casadi_int, casadi_int > size() const
Shape as a pair (number of rows, number of columns)
static Sparsity sparsity_cast(const Sparsity &x, const Sparsity &sp)
Accessed by SparsityInterface.
Sparsity sparsity_cast_mod(const Sparsity &X, const Sparsity &Y) const
Propagate a subset of a pattern through a sparsity cast.
bool is_permutation() const
Check whether the pattern is that of a permutation matrix.
std::vector< casadi_int > get_colind() const
Column offsets of the compressed column storage.
Sparsity ldl(std::vector< casadi_int > &p, bool amd=true) const
Symbolic LDL factorization of a symmetric pattern.
static casadi_int sprank(const Sparsity &x)
Accessed by SparsityInterface.
bool is_empty(bool both=false) const
Check whether the pattern has a zero dimension.
casadi_int bw_upper() const
Upper half-bandwidth: the largest j - i over all nonzeros (i, j) with j > i.
const SparsityInternal & operator*() const
Reference to internal structure.
static Sparsity sum1(const Sparsity &x)
Accessed by SparsityInterface.
static Sparsity kron(const Sparsity &a, const Sparsity &b)
Accessed by SparsityInterface.
bool is_singular() const
Check whether a square pattern is structurally singular.
void export_code(const std::string &lang, std::ostream &stream=casadi::uout(), const Dict &options=Dict()) const
Write code that reconstructs the pattern in another language.
void to_file(const std::string &filename, const std::string &format_hint="") const
Write the pattern to a file.
std::vector< casadi_int > compress(bool canonical=true) const
Compact single-vector representation of the pattern.
static std::vector< Sparsity > diagsplit(const Sparsity &x, const std::vector< casadi_int > &offset1, const std::vector< casadi_int > &offset2)
Accessed by SparsityInterface.
void get_triplet(std::vector< casadi_int > &row, std::vector< casadi_int > &col) const
The pattern in sparse triplet format: the row and column of every nonzero.
static Sparsity horzcat(const std::vector< Sparsity > &sp)
Accessed by SparsityInterface.
static casadi_int norm_0_mul(const Sparsity &x, const Sparsity &A)
Accessed by SparsityInterface.
double density() const
Percentage of nonzeros: 100*nnz()/numel()
Sparsity uni_coloring(const Sparsity &AT=Sparsity(), casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Unidirectional (column) coloring for compressed Jacobian evaluation.
Sparsity operator+(const Sparsity &b) const
Union of two sparsity patterns of the same shape (also available as the + operator)
static Sparsity diagcat(const std::vector< Sparsity > &v)
Accessed by SparsityInterface.
casadi_int nnz_diag() const
Number of nonzeros on the main diagonal, i.e. entries (i, i)
bool is_transpose(const Sparsity &y) const
Check whether y is the transpose of this pattern.
std::size_t hash() const
Hash of the pattern (dimensions, colind and row)
std::vector< casadi_int > get_row() const
Row index of every nonzero, in nonzero (column-major) order.
void appendColumns(const Sparsity &sp)
Append a pattern to the right of this one, in place (horizontal concatenation)
void get_ccs(std::vector< casadi_int > &colind, std::vector< casadi_int > &row) const
The pattern in compressed column storage: the colind and row vectors.
static Sparsity nonzeros(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &nz, bool ind1=SWIG_IND1)
Create a sparsity pattern from the flat (column-major) index of every nonzero.
static bool test_cast(const SharedObjectInternal *ptr)
Check if a particular cast is allowed.
static void mul_activityF(const bvec_t *x, const Sparsity &x_sp, const bvec_t *y, const Sparsity &y_sp, bvec_t *z, const Sparsity &z_sp, bvec_t *w)
Propagate signal activity through a matrix product, forward mode.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
static Sparsity kron_contract(const Sparsity &sp_m, const Sparsity &sp_x, bool inner)
Output sparsity of casadi::KronContract.
static Sparsity lower(casadi_int n)
Create a lower triangular square sparsity pattern.
bool is_dense() const
Check whether every entry is a structural nonzero, i.e. nnz() == numel()
bool is_orthonormal_columns(bool allow_empty=false) const
Check whether the columns are orthonormal (see is_orthonormal_rows)
static void mul_sparsityF(const bvec_t *x, const Sparsity &x_sp, const bvec_t *y, const Sparsity &y_sp, bvec_t *z, const Sparsity &z_sp, bvec_t *w)
Propagate sparsity using 0-1 logic through a matrix product,.
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 from the (row, col) index of every nonzero.
static Sparsity band(casadi_int n, casadi_int p)
Create a single band in a square sparsity pattern.
static Sparsity kkt(const Sparsity &H, const Sparsity &J, bool with_x_diag=true, bool with_lam_g_diag=true)
Pattern of a KKT system [H + I1, J'; J, I2].
void resize(casadi_int nrow, casadi_int ncol)
Change the shape in place, keeping the nonzeros that still fit.
static Sparsity mtimes(const Sparsity &x, const Sparsity &y, const std::string &blas="reference")
Accessed by SparsityInterface.
std::string postfix_dim() const
Dimension string to append to a name, as used when printing symbolic primitives.
bool is_square() const
Check whether the number of rows equals the number of columns.
void qr_sparse(Sparsity &V, Sparsity &R, std::vector< casadi_int > &prinv, std::vector< casadi_int > &pc, bool amd=true) const
Symbolic QR factorization.
static Sparsity from_file(const std::string &filename, const std::string &format_hint="")
Read a pattern from a file written by to_file (Matrix Market pattern format)
static Sparsity compressed(const std::vector< casadi_int > &v, bool order_rows=false)
Create from the compact single-vector representation of a pattern.
bool rowsSequential(bool strictly=true) const
Check whether the row indices are increasing within every column.
bool is_triu(bool strictly=false) const
Check whether all nonzeros are on or above the diagonal (row <= col)
std::vector< casadi_int > largest_first() const
Column indices ordered by decreasing number of nonzeros.
std::string repr_el(casadi_int k) const
Describe the position of nonzero k as a string.
Sparsity star_coloring2(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Star coloring of a symmetric pattern with the newer algorithm.
bool is_symmetric() const
Check whether the pattern equals its transpose.
casadi_int bw_lower() const
Lower half-bandwidth: the largest i - j over all nonzeros (i, j) with i > j.
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
void check_offset(const std::vector< casadi_int > &offset, casadi_int n, const std::string &fname)
Assert that offset starts at 0, is nondecreasing and ends at n.
void casadi_fill(T1 *x, casadi_int n, T1 alpha)
FILL: x <- alpha.
static void mul_bvec_fwd(const bvec_t *x, const Sparsity &x_sp, const bvec_t *y, const Sparsity &y_sp, bvec_t *z, const Sparsity &z_sp, bvec_t *w)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void hash_combine(std::size_t &seed, T v)
Generate a hash value incrementally (function taken from boost)
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_permutation(const std::vector< casadi_int > &order)
Does the list represent a permutation?
std::string filename(const std::string &path)
Compact representation of a sparsity pattern.