27 #ifndef CASADI_SPARSITY_HPP
28 #define CASADI_SPARSITY_HPP
30 #include "shared_object.hpp"
31 #include "printable.hpp"
32 #include "casadi_common.hpp"
33 #include "sparsity_interface.hpp"
34 #include "generic_type.hpp"
38 #include <unordered_map>
39 #ifdef CASADI_WITH_THREAD
40 #ifdef CASADI_WITH_THREAD_MINGW
41 #include <mingw.mutex.h>
49 class SparsityInternal;
50 class SerializingStream;
51 class DeserializingStream;
61 const casadi_int*
row;
105 public SWIG_IF_ELSE(SparsityInterfaceCommon, SparsityInterface<Sparsity>),
106 public SWIG_IF_ELSE(PrintableCommon, Printable<Sparsity>) {
110 explicit Sparsity(casadi_int dummy=0);
115 Sparsity(casadi_int nrow, casadi_int ncol);
118 Sparsity(casadi_int nrow, casadi_int ncol,
119 const std::vector<casadi_int>& colind,
const std::vector<casadi_int>& row,
120 bool order_rows=
false);
125 explicit Sparsity(
const std::pair<casadi_int, casadi_int>& rc);
129 Sparsity(casadi_int nrow, casadi_int ncol,
const casadi_int* colind,
const casadi_int* row,
130 bool order_rows=
false);
154 {
return dense_scalar ? dense(1, 1) :
Sparsity(1, 1); }
161 static Sparsity dense(casadi_int nrow, casadi_int ncol=1);
163 return dense(rc.first, rc.second);
173 static Sparsity unit(casadi_int n, casadi_int el);
179 static Sparsity upper(casadi_int n);
184 static Sparsity lower(casadi_int n);
191 static Sparsity diag(casadi_int nrow, casadi_int ncol);
193 return diag(rc.first, rc.second);
204 static Sparsity band(casadi_int n, casadi_int p);
212 static Sparsity banded(casadi_int n, casadi_int p);
217 static Sparsity rowcol(
const std::vector<casadi_int>& row,
218 const std::vector<casadi_int>& col,
219 casadi_int nrow, casadi_int ncol);
225 static Sparsity triplet(casadi_int nrow, casadi_int ncol,
226 const std::vector<casadi_int>& row,
const std::vector<casadi_int>& col,
227 std::vector<casadi_int>& SWIG_OUTPUT(mapping),
bool invert_mapping);
228 static Sparsity triplet(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& row,
229 const std::vector<casadi_int>& col);
237 static Sparsity nonzeros(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& nz,
238 bool ind1=SWIG_IND1);
248 static Sparsity compressed(
const std::vector<casadi_int>& v,
bool order_rows=
false);
250 static Sparsity compressed(
const casadi_int* v,
bool order_rows=
false);
264 static Sparsity permutation(
const std::vector<casadi_int>& p,
bool invert=
false);
269 const std::vector<casadi_int> permutation_vector(
bool invert=
false)
const;
276 Sparsity get_diag(std::vector<casadi_int>& SWIG_OUTPUT(mapping))
const;
279 std::vector<casadi_int> compress(
bool canonical=
true)
const;
290 bool is_equal(const Sparsity& y) const;
291 bool is_equal(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& colind,
292 const std::vector<casadi_int>& row)
const;
294 bool is_equal(casadi_int nrow, casadi_int ncol,
295 const casadi_int* colind,
const casadi_int* row)
const;
305 bool is_stacked(
const Sparsity& y, casadi_int n)
const;
314 operator const casadi_int*()
const;
319 operator const std::vector<casadi_int>&()
const;
331 casadi_int size1()
const;
334 casadi_int
rows()
const {
return size1();}
337 casadi_int size2()
const;
348 casadi_int numel()
const;
355 double density()
const;
363 bool is_empty(
bool both=
false)
const;
370 casadi_int nnz()
const;
377 casadi_int nnz_upper(
bool strictly=
false)
const;
384 casadi_int nnz_lower(
bool strictly=
false)
const;
389 casadi_int nnz_diag()
const;
394 casadi_int bw_upper()
const;
399 casadi_int bw_lower()
const;
404 std::pair<casadi_int, casadi_int> size()
const;
409 casadi_int size(casadi_int axis)
const;
420 void to_file(
const std::string&
filename,
const std::string& format_hint=
"")
const;
422 static Sparsity from_file(
const std::string&
filename,
const std::string& format_hint=
"");
428 void serialize(std::ostream &stream)
const;
434 std::string serialize()
const;
439 static Sparsity deserialize(std::istream& stream);
444 static Sparsity deserialize(
const std::string& s);
462 const casadi_int* row()
const;
467 const casadi_int* colind()
const;
477 std::vector<casadi_int> get_row()
const;
485 std::vector<casadi_int> get_colind()
const;
490 casadi_int colind(casadi_int cc)
const;
495 casadi_int row(casadi_int el)
const;
503 std::vector<casadi_int> get_col()
const;
506 void resize(casadi_int nrow, casadi_int ncol);
513 casadi_int add_nz(casadi_int rr, casadi_int cc);
520 casadi_int get_nz(casadi_int rr, casadi_int cc)
const;
523 bool has_nz(casadi_int rr, casadi_int cc)
const;
530 std::vector<casadi_int> get_nz(
const std::vector<casadi_int>& rr,
531 const std::vector<casadi_int>& cc)
const;
540 void get_nz(std::vector<casadi_int>& SWIG_INOUT(indices))
const;
543 std::vector<casadi_int> get_lower()
const;
546 std::vector<casadi_int> get_upper()
const;
549 void get_ccs(std::vector<casadi_int>& SWIG_OUTPUT(colind),
550 std::vector<casadi_int>& SWIG_OUTPUT(row))
const;
553 void get_crs(std::vector<casadi_int>& SWIG_OUTPUT(rowind),
554 std::vector<casadi_int>& SWIG_OUTPUT(col))
const;
557 void get_triplet(std::vector<casadi_int>& SWIG_OUTPUT(row),
558 std::vector<casadi_int>& SWIG_OUTPUT(col))
const;
566 Sparsity sub(
const std::vector<casadi_int>& rr,
567 const std::vector<casadi_int>& cc,
568 std::vector<casadi_int>& SWIG_OUTPUT(mapping),
bool ind1=
false)
const;
577 std::vector<casadi_int>& SWIG_OUTPUT(mapping),
bool ind1=
false)
const;
588 Sparsity transpose(std::vector<casadi_int>& SWIG_OUTPUT(mapping),
589 bool invert_mapping=
false)
const;
592 bool is_transpose(
const Sparsity& y)
const;
595 bool is_reshape(
const Sparsity& y)
const;
606 bool is_compactible(std::vector<casadi_int>& SWIG_OUTPUT(row),
607 std::vector<casadi_int>& SWIG_OUTPUT(col))
const;
622 std::vector<unsigned char>& mapping)
const;
632 Sparsity unite(
const Sparsity& y, std::vector<unsigned char>& mapping)
const;
649 std::vector<unsigned char>& mapping)
const;
656 bool is_subset(
const Sparsity& rhs)
const;
716 static Sparsity horzcat(
const std::vector<Sparsity> & sp);
717 static Sparsity vertcat(
const std::vector<Sparsity> & sp);
718 static Sparsity blockcat(
const std::vector< std::vector< Sparsity > > &v);
719 static Sparsity diagcat(
const std::vector< Sparsity > &v);
720 static std::vector<Sparsity>
721 horzsplit(
const Sparsity& x,
const std::vector<casadi_int>& offset);
722 static std::vector<Sparsity>
723 vertsplit(
const Sparsity& x,
const std::vector<casadi_int>& offset);
724 static std::vector<Sparsity>
726 const std::vector<casadi_int>& offset1,
727 const std::vector<casadi_int>& offset2);
729 const std::string& blas =
"reference");
731 const std::string& =
"reference") {
return z;}
732 static Sparsity reshape(
const Sparsity& x, casadi_int nrow, casadi_int ncol);
735 static casadi_int sprank(
const Sparsity& x);
776 void enlarge(casadi_int nrow, casadi_int ncol,
777 const std::vector<casadi_int>& rr,
778 const std::vector<casadi_int>& cc,
bool ind1=
false);
783 void enlargeRows(casadi_int nrow,
const std::vector<casadi_int>& rr,
bool ind1=
false);
788 void enlargeColumns(casadi_int ncol,
const std::vector<casadi_int>& cc,
bool ind1=
false);
793 Sparsity makeDense(std::vector<casadi_int>& SWIG_OUTPUT(mapping))
const;
798 std::vector<casadi_int> erase(
const std::vector<casadi_int>& rr,
799 const std::vector<casadi_int>& cc,
bool ind1=
false);
804 std::vector<casadi_int> erase(
const std::vector<casadi_int>& rr,
bool ind1=
false);
810 void appendColumns(
const Sparsity& sp);
813 bool is_scalar(
bool scalar_and_dense=
false)
const;
816 bool is_dense()
const;
826 bool is_column()
const;
831 bool is_vector()
const;
836 bool is_diag()
const;
841 bool is_square()
const;
846 bool is_symmetric()
const;
851 bool is_triu(
bool strictly =
false)
const;
856 bool is_tril(
bool strictly =
false)
const;
861 bool is_singular()
const;
885 bool is_selection(
bool allow_empty=
false)
const;
892 bool is_orthonormal(
bool allow_empty=
false)
const;
899 bool is_orthonormal_rows(
bool allow_empty=
false)
const;
906 bool is_orthonormal_columns(
bool allow_empty=
false)
const;
913 bool rowsSequential(
bool strictly=
true)
const;
921 void removeDuplicates(std::vector<casadi_int>& SWIG_INOUT(mapping));
924 typedef std::unordered_multimap<std::size_t, WeakRef>
CachingMap;
929 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
931 static std::mutex cachingmap_mtx;
938 static const Sparsity& getScalarSparse();
957 std::vector<casadi_int> etree(
bool ata=
false)
const;
968 Sparsity ldl(std::vector<casadi_int>& SWIG_OUTPUT(p),
bool amd=
true)
const;
980 std::vector<casadi_int>& SWIG_OUTPUT(prinv),
981 std::vector<casadi_int>& SWIG_OUTPUT(pc),
bool amd=
true)
const;
988 casadi_int dfs(casadi_int j, casadi_int top, std::vector<casadi_int>& SWIG_INOUT(xi),
989 std::vector<casadi_int>& SWIG_INOUT(pstack),
990 const std::vector<casadi_int>& pinv, std::vector<bool>& SWIG_INOUT(marked))
const;
1015 casadi_int scc(std::vector<casadi_int>& SWIG_OUTPUT(index),
1016 std::vector<casadi_int>& SWIG_OUTPUT(offset))
const;
1039 casadi_int btf(std::vector<casadi_int>& SWIG_OUTPUT(rowperm),
1040 std::vector<casadi_int>& SWIG_OUTPUT(colperm),
1041 std::vector<casadi_int>& SWIG_OUTPUT(rowblock),
1042 std::vector<casadi_int>& SWIG_OUTPUT(colblock),
1043 std::vector<casadi_int>& SWIG_OUTPUT(coarse_rowblock),
1044 std::vector<casadi_int>& SWIG_OUTPUT(coarse_colblock))
const;
1058 std::vector<casadi_int> amd()
const;
1078 std::vector<casadi_int>
find(
bool ind1=SWIG_IND1)
const;
1082 void find(std::vector<casadi_int>& loc,
bool ind1=
false)
const;
1091 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1106 Sparsity star_coloring_new(std::vector<casadi_int>& SWIG_OUTPUT(which_color),
1120 Sparsity star_coloring(casadi_int ordering = 1,
1121 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1134 Sparsity star_coloring2(casadi_int ordering = 1,
1135 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1140 std::vector<casadi_int> largest_first()
const;
1149 Sparsity pmult(
const std::vector<casadi_int>& p,
1150 bool permute_rows=
true,
bool permute_columns=
true,
1154 std::string dim(
bool with_nz=
false)
const;
1166 std::string postfix_dim()
const;
1169 std::string repr_el(casadi_int k)
const;
1181 void spy_matlab(
const std::string& mfile)
const;
1195 void export_code(
const std::string& lang, std::ostream &stream=
casadi::uout(),
1202 std::size_t hash()
const;
1213 bool with_x_diag=
true,
bool with_lam_g_diag=
true);
1221 template<
typename T>
1229 template<
typename T>
1237 template<
typename T>
1240 static std::string file_format(
const std::string&
filename,
1241 const std::string& format_hint,
const std::set<std::string>& file_formats);
1246 void assign_cached(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& colind,
1247 const std::vector<casadi_int>& row,
bool order_rows=
false);
1250 void assign_cached(casadi_int nrow, casadi_int ncol,
1251 const casadi_int* colind,
const casadi_int* row,
bool order_rows=
false);
1259 CASADI_EXPORT std::size_t
hash_sparsity(casadi_int nrow, casadi_int ncol,
1260 const std::vector<casadi_int>& colind,
1261 const std::vector<casadi_int>& row);
1263 CASADI_EXPORT std::size_t
hash_sparsity(casadi_int nrow, casadi_int ncol,
1264 const casadi_int* colind,
1265 const casadi_int* row);
1269 template<
typename DataType>
1272 const casadi_int sz =
nnz();
1273 const casadi_int sz1 =
size1();
1274 const casadi_int sz2 =
size2();
1277 const casadi_int val_sz = val_sp.
nnz();
1278 const casadi_int val_sz1 = val_sp.
size1();
1279 const casadi_int val_sz2 = val_sp.
size2();
1280 const casadi_int val_nel = val_sz1*val_sz2;
1283 if (val_sp==*
this) {
1284 std::copy(val_data, val_data+sz, data);
1291 }
else if (val_nel==1) {
1292 std::fill(data, data+sz, val_sz==0 ? DataType(0) : val_data[0]);
1293 }
else if (sz2==val_sz2 && sz1==val_sz1) {
1296 const casadi_int* c =
row();
1297 const casadi_int* rind =
colind();
1298 const casadi_int* v_c = val_sp.
row();
1299 const casadi_int* v_rind = val_sp.
colind();
1302 for (casadi_int i=0; i<sz2; ++i) {
1305 casadi_int v_el = v_rind[i];
1308 casadi_int v_el_end = v_rind[i+1];
1311 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1314 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1322 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1327 data[el] = val_data[v_el++];
1328 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1334 }
else if (sz1==val_sz2 && sz2==val_sz1 && sz2 == 1) {
1336 const casadi_int* v_cind = val_sp.
colind();
1337 const casadi_int* r =
row();
1338 for (casadi_int el=0; el<sz; ++el) {
1339 casadi_int rr=r[el];
1340 data[el] = v_cind[rr]==v_cind[rr+1] ? 0 : val_data[v_cind[rr]];
1342 }
else if (sz1==val_sz2 && sz2==val_sz1 && sz1 == 1) {
1344 for (casadi_int el=0; el<sz; ++el) data[el] = 0;
1345 const casadi_int* cind =
colind();
1346 const casadi_int* v_r = val_sp.
row();
1347 for (casadi_int el=0; el<val_sz; ++el) {
1348 casadi_int rr=v_r[el];
1349 if (cind[rr]!=cind[rr+1]) {
1350 data[cind[rr]] = val_data[el];
1355 casadi_error(
"Sparsity::set<DataType>: shape mismatch. lhs is "
1356 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1360 template<
typename DataType>
1363 const casadi_int sz =
nnz();
1364 const casadi_int sz1 =
size1();
1365 const casadi_int sz2 =
size2();
1366 const casadi_int nel = sz1*sz2;
1369 const casadi_int val_sz = val_sp.
nnz();
1370 const casadi_int val_sz1 = val_sp.
size1();
1371 const casadi_int val_sz2 = val_sp.
size2();
1372 const casadi_int val_nel = val_sz1*val_sz2;
1375 if (val_sp==*
this) {
1376 for (casadi_int k=0; k<sz; ++k) {
1377 data[k] += val_data[k];
1385 }
else if (val_nel==1) {
1387 for (casadi_int k=0; k<sz; ++k) {
1388 data[k] += val_data[0];
1393 if (nel==0 && val_nel==0)
return;
1396 casadi_assert(sz2==val_sz2 && sz1==val_sz1,
1397 "Sparsity::add<DataType>: shape mismatch. lhs is "
1398 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1401 const casadi_int* c =
row();
1402 const casadi_int* rind =
colind();
1403 const casadi_int* v_c = val_sp.
row();
1404 const casadi_int* v_rind = val_sp.
colind();
1407 for (casadi_int i=0; i<sz2; ++i) {
1410 casadi_int v_el = v_rind[i];
1413 casadi_int v_el_end = v_rind[i+1];
1416 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1419 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1427 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1432 data[el] += val_data[v_el++];
1433 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1440 template<
typename DataType>
1443 const casadi_int sz =
nnz();
1444 const casadi_int sz1 =
size1();
1445 const casadi_int sz2 =
size2();
1446 const casadi_int nel = sz1*sz2;
1449 const casadi_int val_sz = val_sp.
nnz();
1450 const casadi_int val_sz1 = val_sp.
size1();
1451 const casadi_int val_sz2 = val_sp.
size2();
1452 const casadi_int val_nel = val_sz1*val_sz2;
1455 if (val_sp==*
this) {
1456 for (casadi_int k=0; k<sz; ++k) {
1457 data[k] |= val_data[k];
1465 }
else if (val_nel==1) {
1467 for (casadi_int k=0; k<sz; ++k) {
1468 data[k] |= val_data[0];
1473 if (nel==0 && val_nel==0)
return;
1476 casadi_assert(sz2==val_sz2 && sz1==val_sz1,
1477 "Sparsity::add<DataType>: shape mismatch. lhs is "
1478 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1481 const casadi_int* c =
row();
1482 const casadi_int* rind =
colind();
1483 const casadi_int* v_c = val_sp.
row();
1484 const casadi_int* v_rind = val_sp.
colind();
1487 for (casadi_int i=0; i<sz2; ++i) {
1490 casadi_int v_el = v_rind[i];
1493 casadi_int v_el_end = v_rind[i+1];
1496 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1499 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1507 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1512 data[el] |= val_data[v_el++];
1513 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1524 typedef std::map<std::string, Sparsity>
SpDict;
Helper class for Serialization.
Helper class for Serialization.
GenericShared implements a reference counting framework similar for efficient and.
casadi_int columns() const
Get the number of columns, Octave-style syntax.
void bor(T *data, const T *val_data, const Sparsity &val_sp) const
Bitwise or of the nonzero entries of one sparsity pattern and the nonzero.
static std::string type_name()
Readable name of the public class.
std::unordered_multimap< std::size_t, WeakRef > CachingMap
Enlarge matrix.
casadi_int size1() const
Get the number of rows.
static std::set< std::string > file_formats
Enlarge matrix.
static Sparsity dense(const std::pair< casadi_int, casadi_int > &rc)
Create a dense rectangular sparsity pattern *.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
static Sparsity diag(const std::pair< casadi_int, casadi_int > &rc)
Create diagonal sparsity pattern *.
void add(T *data, const T *val_data, const Sparsity &val_sp) const
Add the nonzero entries of one sparsity pattern to the nonzero entries.
std::string dim(bool with_nz=false) const
Get the dimension as a string.
void set(T *data, const T *val_data, const Sparsity &val_sp) const
Assign the nonzero entries of one sparsity pattern to the nonzero.
static Sparsity mac(const Sparsity &x, const Sparsity &y, const Sparsity &z, const std::string &="reference")
Enlarge matrix.
casadi_int rows() const
Get the number of rows, Octave-style syntax.
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,.
static Sparsity scalar(bool dense_scalar=true)
Create a scalar sparsity pattern *.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
bool operator!=(const Sparsity &y) const
Check if two sparsity patterns are difference.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
bool operator==(const Sparsity &y) const
SparsityInterface< Sparsity > B
Base class.
bool is_equal(double x, double y, casadi_int depth=0)
std::vector< casadi_int > invert_permutation(const std::vector< casadi_int > &a)
inverse a permutation vector
unsigned long long bvec_t
Dict combine(const Dict &first, const Dict &second, bool recurse)
Combine two dicts. First has priority.
std::vector< casadi_int > find(const std::vector< T > &v)
find nonzeros
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.
std::map< std::string, Sparsity > SpDict
MX kron_contract(const MX &m, const MX &x, bool inner)
Kronecker contraction.
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.
const casadi_int * colind