X-Git-Url: https://git.sthu.org/?a=blobdiff_plain;f=include%2Flibstick-0.1%2Fbooleanmatrix.h;h=594eb92c8a410bc749042afc541d572fea12994e;hb=54836e4fa90f52c9682c7918c47b28177e6f4170;hp=774aeb73095c6abb2738d49d9f6d8ad63f88ddbc;hpb=88ea14f1e9079c9b8c4af7aff01a3fe960e9472b;p=libstick.git diff --git a/include/libstick-0.1/booleanmatrix.h b/include/libstick-0.1/booleanmatrix.h index 774aeb7..594eb92 100644 --- a/include/libstick-0.1/booleanmatrix.h +++ b/include/libstick-0.1/booleanmatrix.h @@ -11,10 +11,15 @@ #include #include +#include "booleanvector.h" namespace libstick { +template +std::ostream& operator<<(std::ostream &, const std::vector &); + + /** The base class of boolean_colmatrix and boolean_colrowmatrix which implements * the common logic of both. */ template @@ -22,24 +27,41 @@ class boolean_colmatrix_base { public: typedef IT index_type; - typedef std::vector column_type; + typedef sorted_boolean_vector column_type; typedef D derived; + protected: /** Create a matrix with 'width' columns, initalized with zero entries. */ boolean_colmatrix_base(size_t width) : cols(width) { } - /** Get height resp. width of the matrix. */ + public: + /** A casting constructor for any colmatrix with same entries type. */ + template + boolean_colmatrix_base(const boolean_colmatrix_base &mat) : + cols(mat.get_columns()) { + } + + /** Get width of the matrix. */ size_t width() const { return cols.size(); } + /** Get height of the matrix, i.e. maximum row-index + 1 among all + * columns. */ + size_t height() const { + IT h = 0; + for (unsigned c=0; c < width(); ++c) + if (cols[c].size() > 0) + h = std::max(h, cols[c].back()); + return h+1; + } + /** Get the matrix entry at row 'r' and column 'c'. */ bool get(index_type r, index_type c) const { assert(c < width()); - const column_type &col = get_column(c); - return binary_search(col.begin(), col.end(), r); + return get_column(c).get(r); } /** Set the matrix entry at row 'r' and column 'c'. */ @@ -47,65 +69,77 @@ class boolean_colmatrix_base { get_derived()->_set(r, c, value); } + /** For each of the 'count'-many (row-index, column-pair) pair in + * 'indices', set the specific value. */ + void set_all(index_type indices[][2], size_t count, bool value) { + for (unsigned i=0; i < count; ++i) + set(indices[i][0], indices[i][1], value); + } + /** Get the c-th column. */ const column_type& get_column(index_type c) const { assert(c < width()); return cols[c]; } + /** Get all columns */ + const std::vector& get_columns() const { + return cols; + } + /** Add the column-vector 'col' to the c-th column. Note that 'col' * actually contains the list of row-indices that are 1. */ void add_column(index_type c, const column_type &col) { assert(c < width()); // Flip all entries that are set in 'col'. - for (typename column_type::const_iterator it = col.begin(); it != col.end(); ++it) + for (typename column_type::indexarray::const_iterator it = col.get_ones().begin(); + it != col.get_ones().end(); ++it) set(*it, c, !get(*it, c)); } /** Two matrices are equal iff they have the same entries */ - bool operator==(const boolean_colmatrix_base &m) const { - return cols == m.cols; + template + bool operator==(const boolean_colmatrix_base &m) const { + return cols == m.get_columns(); } /** Two matrices are equal iff they have the same entries */ - bool operator!=(const boolean_colmatrix_base &m) const { + template + bool operator!=(const boolean_colmatrix_base &m) const { return !(*this == m); } + /** Print index pairs of the 1s as { {r, c}, {r, c}, {r, c} } */ + void print_indexpairs(std::ostream &os) const { + bool first=true; + + os << "{"; + for (unsigned c=0; c < width(); ++c) { + const column_type &col = get_column(c); + const typename column_type::indexarray &ones = col.get_ones(); + typename column_type::indexarray::iterator it = ones.begin(); + + for (typename column_type::indexarray::iterator it = ones.begin(); + it != ones.end(); ++it) { + if (first) + first = false; + else + os << ","; + os << " {" << *it << ", " << c << "}"; + } + } + os << " }"; + } + protected: /** Set the matrix entry at row 'r' and column 'c'. */ void _set(index_type r, index_type c, bool value) { assert(c < width()); - - column_type &col = cols.at(c); - // Let us see where to insert the new element - typename column_type::iterator it = lower_bound(col.begin(), col.end(), r); - bool exists = (it != col.end() && *it == r); - assert(get(r,c) == exists); - - // Add 'r' to c-th column - if (value) { - // r is new, insert it - if (!exists) - col.insert(it, r); - assert(get(r,c)); - } - // Remove the element - else { - if (exists) - col.erase(it); - assert(!get(r,c)); - } - -#ifndef NDEBUG - // C++11 would have is_sorted - for (unsigned i=1; i < col.size(); i++) - assert(col[i-1] < col[i]); -#endif + cols.at(c).set(r, value); } - private: + protected: /** The matrix is the set of columns. */ std::vector cols; @@ -125,6 +159,7 @@ class boolean_colmatrix : public boolean_colmatrix_base > base; + typedef typename base::column_type column_type; /** Create a matrix with 'width' columns, initalized with zero entries. */ boolean_colmatrix(size_t columns) : @@ -135,6 +170,14 @@ class boolean_colmatrix : public boolean_colmatrix_base row_type; + typedef sorted_boolean_vector row_type; typedef D derived; + protected: /** Create a matrix with 'height' rows, initalized with zero entries. * */ boolean_rowmatrix_base(size_t height) : rows(height) { } - /** Get height resp. width of the matrix. */ + public: + /** Get height of the matrix. */ size_t height() const { return rows.size(); } @@ -162,8 +207,7 @@ class boolean_rowmatrix_base { /** Get the matrix entry at row 'r' and column 'c'. */ bool get(index_type r, index_type c) const { assert(r < height()); - const row_type &row = get_row(r); - return binary_search(row.begin(), row.end(), c); + return get_row(r).get(c); } /** Set the matrix entry at row 'r' and column 'c'. */ @@ -171,6 +215,13 @@ class boolean_rowmatrix_base { get_derived()->_set(r, c, value); } + /** For each of the 'count'-many (row-index, column-pair) pair in + * 'indices', set the specific value. */ + void set_all(index_type indices[][2], size_t count, bool value) { + for (unsigned i=0; i < count; ++i) + set(indices[i][0], indices[i][1], value); + } + /** Get the r-th row. */ const row_type& get_row(index_type r) const { assert(r < height()); @@ -183,7 +234,8 @@ class boolean_rowmatrix_base { assert(r < height()); // Flip all entries that are set in 'row'. - for (typename row_type::const_iterator it = row.begin(); it != row.end(); ++it) + for (typename row_type::indexarray::const_iterator it = row.get_ones().begin(); + it != row.get_ones().end(); ++it) set(r, *it, !get(r, *it)); } @@ -201,35 +253,10 @@ class boolean_rowmatrix_base { /** Set the matrix entry at row 'r' and column 'c'. */ void _set(index_type r, index_type c, bool value) { assert(r < height()); - - row_type &row = rows.at(r); - // Let us see where to insert/remove the new element - typename row_type::iterator it = lower_bound(row.begin(), row.end(), c); - bool exists = (it != row.end() && *it == c); - assert(get(r,c) == exists); - - // Add 'r' to c-th column - if (value) { - // r is new, insert it - if (!exists) - row.insert(it, c); - assert(get(r,c)); - } - // Remove the element - else { - if (exists) - row.erase(it); - assert(!get(r,c)); - } - -#ifndef NDEBUG - // C++11 would have is_sorted - for (unsigned i=1; i < row.size(); i++) - assert(row[i-1] < row[i]); -#endif + rows.at(r).set(c, value); } - private: + protected: derived* get_derived() { return static_cast(this); } @@ -280,6 +307,23 @@ class boolean_colrowmatrix : public boolean_colmatrix_base + boolean_colrowmatrix(const boolean_colmatrix_base& mat) : + colbase(std::max(mat.width(), mat.height())), + rowbase(std::max(mat.width(), mat.height())) { + for (unsigned c=0; c < mat.width(); ++c) { + const typename colbase::column_type &col = mat.get_column(c); + for (unsigned i=0; i < col.size(); ++i) + set(col.get_ones()[i], c, true); + } + for (unsigned r=0; r < size(); ++r) { + const typename rowbase::row_type &row = rowbase::get_row(r); + for (unsigned i=0; i < row.size(); ++i) + assert(get(r, row.get_ones()[i]) == true); + } + } + /** Override implementation. */ void _set(index_type r, index_type c, bool value) { colbase::_set(r, c, value); @@ -301,6 +345,12 @@ class boolean_colrowmatrix : public boolean_colmatrix_base + bool operator==(const boolean_colmatrix_base &m) const { + return colbase::operator==(m); + } + /** Two matrices are equal iff they have the same entries */ bool operator!=(const boolean_colrowmatrix &m) const { return !(*this == m); @@ -320,7 +376,7 @@ class boolean_colrowmatrix : public boolean_colmatrix_base - boolean_colrowmatrix operator*(const boolean_colmatrix_base &b) { + boolean_colrowmatrix operator*(const boolean_colmatrix_base &b) const { boolean_colrowmatrix c(size()); multiply_matrix(c, *this, b); return c; @@ -331,12 +387,12 @@ class boolean_colrowmatrix : public boolean_colmatrix_base -size_t count_set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) +size_t count_set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { size_t count = 0; // As long as we did not either end, look for common elements - while (first1!=last1 && first2!=last2) + while (first1 != last1 && first2 != last2) { if (*first1 < *first2) ++first1; @@ -352,16 +408,19 @@ size_t count_set_intersection (InputIterator1 first1, InputIterator1 last1, Inpu return count; } -/** Multiply a*b and save the product in 'result'. It is assumed that 'result' is intially empty and has appropriate size. */ -template -void multiply_matrix(RT &result, const boolean_rowmatrix_base &a, const boolean_colmatrix_base &b) { +/** Multiply a*b and save the product in 'result'. It is assumed that 'result' + * is intially empty and has appropriate size. */ +template +void multiply_matrix(RT &result, const boolean_rowmatrix_base &a, const boolean_colmatrix_base &b) { assert(a.height() == b.width()); for (unsigned r=0; r < a.height(); ++r) { - const typename boolean_rowmatrix_base::row_type &row = a.get_row(r); + const typename boolean_rowmatrix_base::row_type &row = a.get_row(r); for (unsigned c=0; c < b.width(); ++c) { - const typename boolean_colmatrix_base::column_type &col = b.get_column(c); - if (count_set_intersection(row.begin(), row.end(), col.begin(), col.end()) % 2 == 1) + const typename boolean_colmatrix_base::column_type &col = b.get_column(c); + if (count_set_intersection( + row.get_ones().begin(), row.get_ones().end(), + col.get_ones().begin(), col.get_ones().end()) % 2 == 1) result.set(r, c, true); } } @@ -377,7 +436,24 @@ MT create_unit_matrix(size_t size) { template std::ostream& operator<<(std::ostream &os, const boolean_colrowmatrix &mat) { + + os << " "; + for (unsigned c=0; c < mat.size(); ++c) { + const unsigned d = (c % 10); + if (d > 0) + os << d; + else + os << " "; + } + os << std::endl; + for (unsigned r=0; r < mat.size(); ++r) { + const unsigned d = (r % 10); + if (d > 0) + os << d; + else + os << " "; + for (unsigned c=0; c < mat.size(); ++c) os << (mat.get(r,c) ? "X" : "."); @@ -468,6 +544,21 @@ std::ostream& operator<<(std::ostream &os, boolean_colmatrix_base &mat) { return os << m; } +template +std::ostream& operator<<(std::ostream& os, const std::vector &vec) { + os << "["; + + typename std::vector::const_iterator it = vec.begin(); + while ( it != vec.end()) { + os << *it; + if (++it != vec.end()) + os << " "; + } + + os << "]"; + return os; +} + } #endif