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;
610 std::vector<unsigned char>& mapping)
const;
620 Sparsity unite(
const Sparsity& y, std::vector<unsigned char>& mapping)
const;
637 std::vector<unsigned char>& mapping)
const;
644 bool is_subset(
const Sparsity& rhs)
const;
692 static Sparsity horzcat(
const std::vector<Sparsity> & sp);
693 static Sparsity vertcat(
const std::vector<Sparsity> & sp);
694 static Sparsity blockcat(
const std::vector< std::vector< Sparsity > > &v);
695 static Sparsity diagcat(
const std::vector< Sparsity > &v);
696 static std::vector<Sparsity>
697 horzsplit(
const Sparsity& x,
const std::vector<casadi_int>& offset);
698 static std::vector<Sparsity>
699 vertsplit(
const Sparsity& x,
const std::vector<casadi_int>& offset);
700 static std::vector<Sparsity>
702 const std::vector<casadi_int>& offset1,
703 const std::vector<casadi_int>& offset2);
706 static Sparsity reshape(
const Sparsity& x, casadi_int nrow, casadi_int ncol);
709 static casadi_int sprank(
const Sparsity& x);
733 void enlarge(casadi_int nrow, casadi_int ncol,
734 const std::vector<casadi_int>& rr,
735 const std::vector<casadi_int>& cc,
bool ind1=
false);
740 void enlargeRows(casadi_int nrow,
const std::vector<casadi_int>& rr,
bool ind1=
false);
745 void enlargeColumns(casadi_int ncol,
const std::vector<casadi_int>& cc,
bool ind1=
false);
750 Sparsity makeDense(std::vector<casadi_int>& SWIG_OUTPUT(mapping))
const;
755 std::vector<casadi_int> erase(
const std::vector<casadi_int>& rr,
756 const std::vector<casadi_int>& cc,
bool ind1=
false);
761 std::vector<casadi_int> erase(
const std::vector<casadi_int>& rr,
bool ind1=
false);
767 void appendColumns(
const Sparsity& sp);
770 bool is_scalar(
bool scalar_and_dense=
false)
const;
773 bool is_dense()
const;
783 bool is_column()
const;
788 bool is_vector()
const;
793 bool is_diag()
const;
798 bool is_square()
const;
803 bool is_symmetric()
const;
808 bool is_triu(
bool strictly =
false)
const;
813 bool is_tril(
bool strictly =
false)
const;
818 bool is_singular()
const;
842 bool is_selection(
bool allow_empty=
false)
const;
849 bool is_orthonormal(
bool allow_empty=
false)
const;
856 bool is_orthonormal_rows(
bool allow_empty=
false)
const;
863 bool is_orthonormal_columns(
bool allow_empty=
false)
const;
870 bool rowsSequential(
bool strictly=
true)
const;
878 void removeDuplicates(std::vector<casadi_int>& SWIG_INOUT(mapping));
881 typedef std::unordered_multimap<std::size_t, WeakRef>
CachingMap;
886 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
888 static std::mutex cachingmap_mtx;
895 static const Sparsity& getScalarSparse();
914 std::vector<casadi_int> etree(
bool ata=
false)
const;
925 Sparsity ldl(std::vector<casadi_int>& SWIG_OUTPUT(p),
bool amd=
true)
const;
937 std::vector<casadi_int>& SWIG_OUTPUT(prinv),
938 std::vector<casadi_int>& SWIG_OUTPUT(pc),
bool amd=
true)
const;
945 casadi_int dfs(casadi_int j, casadi_int top, std::vector<casadi_int>& SWIG_INOUT(xi),
946 std::vector<casadi_int>& SWIG_INOUT(pstack),
947 const std::vector<casadi_int>& pinv, std::vector<bool>& SWIG_INOUT(marked))
const;
972 casadi_int scc(std::vector<casadi_int>& SWIG_OUTPUT(index),
973 std::vector<casadi_int>& SWIG_OUTPUT(offset))
const;
996 casadi_int btf(std::vector<casadi_int>& SWIG_OUTPUT(rowperm),
997 std::vector<casadi_int>& SWIG_OUTPUT(colperm),
998 std::vector<casadi_int>& SWIG_OUTPUT(rowblock),
999 std::vector<casadi_int>& SWIG_OUTPUT(colblock),
1000 std::vector<casadi_int>& SWIG_OUTPUT(coarse_rowblock),
1001 std::vector<casadi_int>& SWIG_OUTPUT(coarse_colblock))
const;
1015 std::vector<casadi_int> amd()
const;
1035 std::vector<casadi_int>
find(
bool ind1=SWIG_IND1)
const;
1039 void find(std::vector<casadi_int>& loc,
bool ind1=
false)
const;
1048 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1061 Sparsity star_coloring(casadi_int ordering = 1,
1062 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1075 Sparsity star_coloring2(casadi_int ordering = 1,
1076 casadi_int cutoff = std::numeric_limits<casadi_int>::max())
const;
1081 std::vector<casadi_int> largest_first()
const;
1090 Sparsity pmult(
const std::vector<casadi_int>& p,
1091 bool permute_rows=
true,
bool permute_columns=
true,
1095 std::string dim(
bool with_nz=
false)
const;
1107 std::string postfix_dim()
const;
1110 std::string repr_el(casadi_int k)
const;
1122 void spy_matlab(
const std::string& mfile)
const;
1136 void export_code(
const std::string& lang, std::ostream &stream=
casadi::uout(),
1143 std::size_t hash()
const;
1154 bool with_x_diag=
true,
bool with_lam_g_diag=
true);
1162 template<
typename T>
1170 template<
typename T>
1178 template<
typename T>
1181 static std::string file_format(
const std::string&
filename,
1182 const std::string& format_hint,
const std::set<std::string>& file_formats);
1187 void assign_cached(casadi_int nrow, casadi_int ncol,
const std::vector<casadi_int>& colind,
1188 const std::vector<casadi_int>& row,
bool order_rows=
false);
1191 void assign_cached(casadi_int nrow, casadi_int ncol,
1192 const casadi_int* colind,
const casadi_int* row,
bool order_rows=
false);
1200 template<
typename T>
1206 template<
typename T>
1208 seed ^=
hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1214 template<
typename T>
1216 for (casadi_int i=0; i<sz; ++i)
hash_combine(seed, v[i]);
1222 template<
typename T>
1237 CASADI_EXPORT std::size_t
hash_sparsity(casadi_int nrow, casadi_int ncol,
1238 const std::vector<casadi_int>& colind,
1239 const std::vector<casadi_int>& row);
1241 CASADI_EXPORT std::size_t
hash_sparsity(casadi_int nrow, casadi_int ncol,
1242 const casadi_int* colind,
1243 const casadi_int* row);
1247 template<
typename DataType>
1250 const casadi_int sz =
nnz();
1251 const casadi_int sz1 =
size1();
1252 const casadi_int sz2 =
size2();
1255 const casadi_int val_sz = val_sp.
nnz();
1256 const casadi_int val_sz1 = val_sp.
size1();
1257 const casadi_int val_sz2 = val_sp.
size2();
1258 const casadi_int val_nel = val_sz1*val_sz2;
1261 if (val_sp==*
this) {
1262 std::copy(val_data, val_data+sz, data);
1269 }
else if (val_nel==1) {
1270 std::fill(data, data+sz, val_sz==0 ? DataType(0) : val_data[0]);
1271 }
else if (sz2==val_sz2 && sz1==val_sz1) {
1274 const casadi_int* c =
row();
1275 const casadi_int* rind =
colind();
1276 const casadi_int* v_c = val_sp.
row();
1277 const casadi_int* v_rind = val_sp.
colind();
1280 for (casadi_int i=0; i<sz2; ++i) {
1283 casadi_int v_el = v_rind[i];
1286 casadi_int v_el_end = v_rind[i+1];
1289 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1292 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1300 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1305 data[el] = val_data[v_el++];
1306 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1312 }
else if (sz1==val_sz2 && sz2==val_sz1 && sz2 == 1) {
1314 const casadi_int* v_cind = val_sp.
colind();
1315 const casadi_int* r =
row();
1316 for (casadi_int el=0; el<sz; ++el) {
1317 casadi_int rr=r[el];
1318 data[el] = v_cind[rr]==v_cind[rr+1] ? 0 : val_data[v_cind[rr]];
1320 }
else if (sz1==val_sz2 && sz2==val_sz1 && sz1 == 1) {
1322 for (casadi_int el=0; el<sz; ++el) data[el] = 0;
1323 const casadi_int* cind =
colind();
1324 const casadi_int* v_r = val_sp.
row();
1325 for (casadi_int el=0; el<val_sz; ++el) {
1326 casadi_int rr=v_r[el];
1327 if (cind[rr]!=cind[rr+1]) {
1328 data[cind[rr]] = val_data[el];
1333 casadi_error(
"Sparsity::set<DataType>: shape mismatch. lhs is "
1334 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1338 template<
typename DataType>
1341 const casadi_int sz =
nnz();
1342 const casadi_int sz1 =
size1();
1343 const casadi_int sz2 =
size2();
1344 const casadi_int nel = sz1*sz2;
1347 const casadi_int val_sz = val_sp.
nnz();
1348 const casadi_int val_sz1 = val_sp.
size1();
1349 const casadi_int val_sz2 = val_sp.
size2();
1350 const casadi_int val_nel = val_sz1*val_sz2;
1353 if (val_sp==*
this) {
1354 for (casadi_int k=0; k<sz; ++k) {
1355 data[k] += val_data[k];
1363 }
else if (val_nel==1) {
1365 for (casadi_int k=0; k<sz; ++k) {
1366 data[k] += val_data[0];
1371 if (nel==0 && val_nel==0)
return;
1374 casadi_assert(sz2==val_sz2 && sz1==val_sz1,
1375 "Sparsity::add<DataType>: shape mismatch. lhs is "
1376 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1379 const casadi_int* c =
row();
1380 const casadi_int* rind =
colind();
1381 const casadi_int* v_c = val_sp.
row();
1382 const casadi_int* v_rind = val_sp.
colind();
1385 for (casadi_int i=0; i<sz2; ++i) {
1388 casadi_int v_el = v_rind[i];
1391 casadi_int v_el_end = v_rind[i+1];
1394 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1397 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1405 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1410 data[el] += val_data[v_el++];
1411 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1418 template<
typename DataType>
1421 const casadi_int sz =
nnz();
1422 const casadi_int sz1 =
size1();
1423 const casadi_int sz2 =
size2();
1424 const casadi_int nel = sz1*sz2;
1427 const casadi_int val_sz = val_sp.
nnz();
1428 const casadi_int val_sz1 = val_sp.
size1();
1429 const casadi_int val_sz2 = val_sp.
size2();
1430 const casadi_int val_nel = val_sz1*val_sz2;
1433 if (val_sp==*
this) {
1434 for (casadi_int k=0; k<sz; ++k) {
1435 data[k] |= val_data[k];
1443 }
else if (val_nel==1) {
1445 for (casadi_int k=0; k<sz; ++k) {
1446 data[k] |= val_data[0];
1451 if (nel==0 && val_nel==0)
return;
1454 casadi_assert(sz2==val_sz2 && sz1==val_sz1,
1455 "Sparsity::add<DataType>: shape mismatch. lhs is "
1456 +
dim() +
", while rhs is " + val_sp.
dim() +
".");
1459 const casadi_int* c =
row();
1460 const casadi_int* rind =
colind();
1461 const casadi_int* v_c = val_sp.
row();
1462 const casadi_int* v_rind = val_sp.
colind();
1465 for (casadi_int i=0; i<sz2; ++i) {
1468 casadi_int v_el = v_rind[i];
1471 casadi_int v_el_end = v_rind[i+1];
1474 casadi_int v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1477 for (casadi_int el=rind[i]; el!=rind[i+1]; ++el) {
1485 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1490 data[el] |= val_data[v_el++];
1491 v_j = v_el<v_el_end ? v_c[v_el] : sz1;
1502 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.
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.
static Sparsity mac(const Sparsity &x, const Sparsity &y, const Sparsity &z)
Enlarge matrix.
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.
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.
size_t hash_value(T v)
Hash value of an integer.
std::map< std::string, Sparsity > SpDict
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.
const casadi_int * colind