1 #ifndef booleanmatrix_h_AechohNgakoghahV
2 #define booleanmatrix_h_AechohNgakoghahV
18 /** The base class of BooleanColMatrix and BooleanColRowMatrix which implements
19 * the common logic of both. */
20 template<class IT
, class D
>
21 class BooleanColMatrix_base
{
24 typedef IT index_type
;
25 typedef std::vector
<index_type
> column_type
;
28 /** Create a matrix with 'width' columns, initalized with zero entries. */
29 BooleanColMatrix_base(size_t width
) :
33 /** Get height resp. width of the matrix. */
34 size_t width() const {
38 /** Get the matrix entry at row 'r' and column 'c'. */
39 bool get(index_type r
, index_type c
) const {
41 const column_type
&col
= getColumn(c
);
42 return binary_search(col
.begin(), col
.end(), r
);
45 /** Set the matrix entry at row 'r' and column 'c'. */
46 void set(index_type r
, index_type c
, bool value
) {
47 getDerived()->_set(r
, c
, value
);
50 /** Get the c-th column. */
51 const column_type
& getColumn(index_type c
) const {
56 /** Add the column-vector 'col' to the c-th column. Note that 'col'
57 * actually contains the list of row-indices that are 1. */
58 void add_column(index_type c
, const column_type
&col
) {
61 // Flip all entries that are set in 'col'.
62 for (typename
column_type::const_iterator it
= col
.begin(); it
!= col
.end(); ++it
)
63 set(*it
, c
, !get(*it
, c
));
66 /** Two matrices are equal iff they have the same entries */
67 bool operator==(const BooleanColMatrix_base
<IT
, D
> &m
) const {
68 return cols
== m
.cols
;
71 /** Two matrices are equal iff they have the same entries */
72 bool operator!=(const BooleanColMatrix_base
<IT
, D
> &m
) const {
79 /** Set the matrix entry at row 'r' and column 'c'. */
80 void _set(index_type r
, index_type c
, bool value
) {
83 column_type
&col
= cols
.at(c
);
84 // Let us see where to insert the new element
85 typename
column_type::iterator it
= lower_bound(col
.begin(), col
.end(), r
);
86 bool exists
= (it
!= col
.end() && *it
== r
);
87 assert(get(r
,c
) == exists
);
89 // Add 'r' to c-th column
91 // r is new, insert it
104 for (unsigned i
=1; i
< col
.size(); i
++)
105 assert(col
[i
-1] < col
[i
]);
110 /** The matrix is the set of columns. */
111 std::vector
<column_type
> cols
;
113 /** A cast to the derived type */
114 derived
* getDerived() {
115 return static_cast<derived
*>(this);
120 /** This is boolean matrix that is a std::vector of column-vectors and in each
121 * column-vector we save the row-indices of the 1s. It is designed to handle a
122 * few 1s and column-wise operations well. */
123 template<class IT
=uint32_t>
124 class BooleanColMatrix
: public BooleanColMatrix_base
<IT
, BooleanColMatrix
<IT
> > {
127 typedef IT index_type
;
128 typedef BooleanColMatrix_base
<IT
, BooleanColMatrix
<IT
> > base
;
130 /** Create a matrix with 'width' columns, initalized with zero entries. */
131 BooleanColMatrix(size_t columns
) :
135 /** Set the matrix entry at row 'r' and column 'c'. */
136 void _set(index_type r
, index_type c
, bool value
) {
137 base::_set(r
, c
, value
);
142 /** The base class of BooleanRowMatrix and BooleanColRowMatrix which implements
143 * the common logic of both. */
144 template<class IT
, class D
>
145 class BooleanRowMatrix_base
{
148 typedef IT index_type
;
149 typedef std::vector
<index_type
> row_type
;
152 /** Create a matrix with 'height' rows, initalized with zero entries.
154 BooleanRowMatrix_base(size_t height
) :
158 /** Get height resp. width of the matrix. */
159 size_t height() const {
163 /** Get the matrix entry at row 'r' and column 'c'. */
164 bool get(index_type r
, index_type c
) const {
165 assert(r
< height());
166 const row_type
&row
= getRow(r
);
167 return binary_search(row
.begin(), row
.end(), c
);
170 /** Set the matrix entry at row 'r' and column 'c'. */
171 void set(index_type r
, index_type c
, bool value
) {
172 getDerived()->_set(r
, c
, value
);
175 /** Get the r-th row. */
176 const row_type
& getRow(index_type r
) const {
177 assert(r
< height());
181 /** Add the row-vector 'row' to the r-th row. Note that 'row'
182 * actually contains the list of column-indices that are 1. */
183 void add_row(index_type r
, const row_type
&row
) {
184 assert(r
< height());
186 // Flip all entries that are set in 'row'.
187 for (typename
row_type::const_iterator it
= row
.begin(); it
!= row
.end(); ++it
)
188 set(r
, *it
, !get(r
, *it
));
191 /** Two matrices are equal iff they have the same entries */
192 bool operator==(const BooleanRowMatrix_base
<IT
, D
> &m
) const {
193 return rows
== m
.rows
;
196 /** Two matrices are equal iff they have the same entries */
197 bool operator!=(const BooleanRowMatrix_base
<IT
, D
> &m
) const {
198 return !(*this == m
);
202 /** Set the matrix entry at row 'r' and column 'c'. */
203 void _set(index_type r
, index_type c
, bool value
) {
204 assert(r
< height());
206 row_type
&row
= rows
.at(r
);
207 // Let us see where to insert/remove the new element
208 typename
row_type::iterator it
= lower_bound(row
.begin(), row
.end(), c
);
209 bool exists
= (it
!= row
.end() && *it
== c
);
210 assert(get(r
,c
) == exists
);
212 // Add 'r' to c-th column
214 // r is new, insert it
219 // Remove the element
227 for (unsigned i
=1; i
< row
.size(); i
++)
228 assert(row
[i
-1] < row
[i
]);
233 derived
* getDerived() {
234 return static_cast<derived
*>(this);
237 /** The matrix is the set of columns. */
238 std::vector
<row_type
> rows
;
242 /** This is boolean matrix that is a std::vector of row-vectors and in each
243 * row-vector we save the column-indices of the 1s. It is designed to handle a
244 * few 1s and row-wise operations well. */
245 template<class IT
=uint32_t>
246 class BooleanRowMatrix
: public BooleanRowMatrix_base
<IT
, BooleanRowMatrix
<IT
> > {
249 typedef IT index_type
;
250 typedef BooleanRowMatrix_base
<IT
, BooleanRowMatrix
<IT
> > base
;
252 /** Create a matrix with 'height' rows, initalized with zero entries. */
253 BooleanRowMatrix(size_t height
) :
257 /** Set the matrix entry at row 'r' and column 'c'. */
258 void _set(index_type r
, index_type c
, bool value
) {
259 base::_set(r
, c
, value
);
264 /** This is a boolean matrix that supports. It is designed to handle a
265 * few 1s and row- and column-wise operations well. */
266 template<class IT
=uint32_t>
267 class BooleanColRowMatrix
: public BooleanColMatrix_base
<IT
, BooleanColRowMatrix
<IT
> >,
268 public BooleanRowMatrix_base
<IT
, BooleanColRowMatrix
<IT
> > {
271 typedef BooleanColMatrix_base
<IT
, BooleanColRowMatrix
<IT
> > colbase
;
272 typedef BooleanRowMatrix_base
<IT
, BooleanColRowMatrix
<IT
> > rowbase
;
275 typedef IT index_type
;
277 /** Create a size x size matrix, initialized with zeros. */
278 BooleanColRowMatrix(size_t size
) :
283 /** Override implementation. */
284 void _set(index_type r
, index_type c
, bool value
) {
285 colbase::_set(r
, c
, value
);
286 rowbase::_set(r
, c
, value
);
290 /** Get height resp. width of the matrix. */
291 size_t size() const {
292 assert(colbase::width() == rowbase::height());
293 return colbase::width();
296 /** Set the matrix entry at row 'r' and column 'c'. */
297 void set(index_type r
, index_type c
, bool value
) {
298 //Calling set() for one base suffices, static polymorphism
299 //calls _set() anyhow.
300 //rowbase::set(r, c, value);
301 colbase::set(r
, c
, value
);
304 /** Get the matrix entry at row 'r' and column 'c'. */
305 bool get(index_type r
, index_type c
) const {
306 assert(colbase::get(r
, c
) == rowbase::get(r
, c
));
307 return colbase::get(r
, c
);
310 /** Two matrices are equal iff they have the same entries */
311 bool operator==(const BooleanColRowMatrix
<IT
> &m
) const {
312 assert(rowbase::operator==(m
) == colbase::operator==(m
));
313 return colbase::operator==(m
);
316 /** Two matrices are equal iff they have the same entries */
317 bool operator!=(const BooleanColRowMatrix
<IT
> &m
) const {
318 return !(*this == m
);
323 std::ostream
& operator<<(std::ostream
&os
, const BooleanColRowMatrix
<IT
> &mat
) {
324 for (unsigned r
=0; r
< mat
.size(); ++r
) {
325 for (unsigned c
=0; c
< mat
.size(); ++c
)
326 os
<< (mat
.get(r
,c
) ? "X" : ".");
328 if (r
< mat
.size() - 1)
335 std::ostream
& operator<<(std::ostream
&os
, BooleanColRowMatrix
<IT
> &mat
) {
336 const BooleanColRowMatrix
<IT
> &m
= mat
;
340 template<class IT
, class D
>
341 std::ostream
& operator<<(std::ostream
&os
, const BooleanRowMatrix_base
<IT
, D
> &mat
) {
342 for (unsigned r
=0; r
< mat
.height(); ++r
) {
343 // Get the sorted r-th row
344 std::list
<IT
> row(mat
.getRow(r
).size());
345 copy(mat
.getRow(r
).begin(), mat
.getRow(r
).end(), row
.begin());
348 // Print the elements, and remove them
349 for (unsigned c
=0; row
.size() > 0; ++c
) {
350 if (row
.front() == c
) {
357 if (r
< mat
.height() - 1)
363 template<class IT
, class D
>
364 std::ostream
& operator<<(std::ostream
&os
, BooleanRowMatrix_base
<IT
, D
> &mat
) {
365 const BooleanRowMatrix_base
<IT
, D
> &m
= mat
;
369 template<class IT
, class D
>
370 std::ostream
& operator<<(std::ostream
&os
, const BooleanColMatrix_base
<IT
, D
> &mat
) {
371 // The sorted columns
372 std::vector
<std::list
<IT
> > cols
;
373 // The max height (max. value) of all columns
376 for (unsigned c
=0; c
< mat
.width(); ++c
) {
377 // Get the sorted c-th column
378 std::list
<IT
> col(mat
.getColumn(c
).size());
379 copy(mat
.getColumn(c
).begin(), mat
.getColumn(c
).end(), col
.begin());
385 height
= std::max(height
, col
.back());
390 for (unsigned r
=0; r
<= height
; ++r
) {
391 // Print the elements, and remove them
392 for (unsigned c
=0; c
< mat
.width(); ++c
) {
393 std::list
<IT
> &col
= cols
.at(c
);
394 // This column is already empty
397 else if (col
.front() == r
) {
409 template<class IT
, class D
>
410 std::ostream
& operator<<(std::ostream
&os
, BooleanColMatrix_base
<IT
, D
> &mat
) {
411 const BooleanColMatrix_base
<IT
, D
> &m
= mat
;