17 #ifndef PM_BASE_MATRIX_COMPRESSION_H
18 #define PM_BASE_MATRIX_COMPRESSION_H
24 #include <boost/intrusive/set.hpp>
25 #include <boost/pending/disjoint_sets.hpp>
27 #include <gudhi/Simple_object_pool.h>
30 namespace persistence_matrix {
44 template <
class Master_matrix>
48 using index =
typename Master_matrix::index;
55 using Row_type =
typename Master_matrix::Row_type;
65 :
public Master_matrix::Column_type,
66 public boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >
69 using Base =
typename Master_matrix::Column_type;
72 : Base(colSettings) {}
73 template <
class Container_type>
75 : Base(nonZeroRowIndices, colSettings) {}
76 template <
class Container_type,
class Row_container_type>
77 Column_type(
index columnIndex,
const Container_type& nonZeroRowIndices, Row_container_type& rowContainer,
79 : Base(columnIndex, nonZeroRowIndices, rowContainer, colSettings) {}
80 template <
class Container_type>
82 : Base(nonZeroRowIndices, dimension, colSettings) {}
83 template <
class Container_type,
class Row_container_type>
86 : Base(columnIndex, nonZeroRowIndices, dimension, rowContainer, colSettings) {}
88 : Base(
static_cast<const Base&
>(column), colSettings) {}
89 template <
class Row_container_type>
92 : Base(
static_cast<const Base&
>(column), columnIndex, rowContainer, colSettings) {}
99 index get_rep()
const {
return rep_; }
100 void set_rep(
const index& rep) { rep_ = rep; }
103 size_t operator()(
const Column_type& c)
const {
return std::hash<Base>()(
static_cast<Base
>(c)); }
129 template <
class Container_type>
171 template <
class Container_type>
181 template <
class Boundary_type>
237 template <
class Cell_range_or_column_index>
238 void add_to(
const Cell_range_or_column_index& sourceColumn,
index targetColumnIndex);
252 template <
class Cell_range_or_column_index>
255 index targetColumnIndex);
269 template <
class Cell_range_or_column_index>
271 const Cell_range_or_column_index& sourceColumn,
272 index targetColumnIndex);
299 columnToRep_.clear_and_dispose(delete_disposer());
300 columnClasses_ = boost::disjoint_sets_with_storage<>();
301 repToColumn_.clear();
302 nextColumnIndex_ = 0;
303 colSettings_ = colSettings;
314 matrix1.columnToRep_.swap(matrix2.columnToRep_);
315 std::swap(matrix1.columnClasses_, matrix2.columnClasses_);
316 matrix1.repToColumn_.swap(matrix2.repToColumn_);
317 std::swap(matrix1.nextColumnIndex_, matrix2.nextColumnIndex_);
318 std::swap(matrix1.colSettings_, matrix2.colSettings_);
320 if constexpr (Master_matrix::Option_list::has_row_access) {
321 swap(
static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix1),
322 static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix2));
332 struct delete_disposer {
333 void operator()(Column_type* delete_this) { columnPool_.destroy(delete_this); }
336 using ra_opt =
typename Master_matrix::Matrix_row_access_option;
337 using col_dict_type = boost::intrusive::set<Column_type, boost::intrusive::constant_time_size<false> >;
339 col_dict_type columnToRep_;
340 boost::disjoint_sets_with_storage<> columnClasses_;
342 std::vector<Column_type*> repToColumn_;
344 index nextColumnIndex_;
351 inline static Simple_object_pool<Column_type> columnPool_;
352 inline static const Column_type empty_column_;
354 void _insert_column(
index columnIndex);
355 void _insert_double_column(
index columnIndex,
typename col_dict_type::iterator& doubleIt);
358 template <
class Master_matrix>
361 : ra_opt(), nextColumnIndex_(0), colSettings_(colSettings)
364 template <
class Master_matrix>
365 template <
class Container_type>
367 const std::vector<Container_type>& columns,
Column_settings* colSettings)
368 : ra_opt(columns.size()),
369 columnClasses_(columns.size()),
370 repToColumn_(columns.size(), nullptr),
372 colSettings_(colSettings)
374 for (
const Container_type& c : columns) {
379 template <
class Master_matrix>
382 : ra_opt(numberOfColumns),
383 columnClasses_(numberOfColumns),
384 repToColumn_(numberOfColumns, nullptr),
386 colSettings_(colSettings)
389 template <
class Master_matrix>
392 : ra_opt(static_cast<const ra_opt&>(matrixToCopy)),
393 columnClasses_(matrixToCopy.columnClasses_),
394 repToColumn_(matrixToCopy.repToColumn_.size(), nullptr),
396 colSettings_(colSettings == nullptr ? matrixToCopy.colSettings_ : colSettings)
398 for (
const Column_type* col : matrixToCopy.repToColumn_) {
399 if (col !=
nullptr) {
400 if constexpr (Master_matrix::Option_list::has_row_access) {
401 repToColumn_[nextColumnIndex_] =
402 columnPool_.construct(*col, col->get_column_index(), ra_opt::rows_, colSettings_);
404 repToColumn_[nextColumnIndex_] = columnPool_.construct(*col, colSettings_);
406 columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
407 repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
413 template <
class Master_matrix>
416 : ra_opt(std::move(
static_cast<ra_opt&
>(other))),
417 columnToRep_(std::move(other.columnToRep_)),
418 columnClasses_(std::move(other.columnClasses_)),
419 repToColumn_(std::move(other.repToColumn_)),
420 nextColumnIndex_(std::exchange(other.nextColumnIndex_, 0)),
421 colSettings_(std::exchange(other.colSettings_,
nullptr))
424 template <
class Master_matrix>
427 columnToRep_.clear_and_dispose(delete_disposer());
430 template <
class Master_matrix>
431 template <
class Container_type>
434 insert_boundary(column);
437 template <
class Master_matrix>
438 template <
class Boundary_type>
445 if (dim == -1) dim = boundary.size() == 0 ? 0 : boundary.size() - 1;
447 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_removable_rows) {
448 if (boundary.begin() != boundary.end()) {
450 if constexpr (Master_matrix::Option_list::is_z2) {
451 pivot = *std::prev(boundary.end());
453 pivot = std::prev(boundary.end())->first;
455 if (ra_opt::rows_->size() <= pivot) ra_opt::rows_->resize(pivot + 1);
459 if (repToColumn_.size() == nextColumnIndex_) {
461 columnClasses_.link(nextColumnIndex_, nextColumnIndex_);
462 if constexpr (Master_matrix::Option_list::has_row_access) {
463 repToColumn_.push_back(
464 columnPool_.construct(nextColumnIndex_, boundary, dim, ra_opt::rows_, colSettings_));
466 repToColumn_.push_back(columnPool_.construct(boundary, dim, colSettings_));
469 if constexpr (Master_matrix::Option_list::has_row_access) {
470 repToColumn_[nextColumnIndex_] =
471 columnPool_.construct(nextColumnIndex_, boundary, dim, ra_opt::rows_, colSettings_);
473 repToColumn_[nextColumnIndex_] = columnPool_.construct(boundary, dim, colSettings_);
476 _insert_column(nextColumnIndex_);
481 template <
class Master_matrix>
485 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
486 if (col ==
nullptr)
return empty_column_;
490 template <
class Master_matrix>
494 static_assert(Master_matrix::Option_list::has_row_access,
"Row access has to be enabled for this method.");
496 return ra_opt::get_row(rowIndex);
499 template <
class Master_matrix>
502 if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_removable_rows) {
503 ra_opt::erase_empty_row(rowIndex);
507 template <
class Master_matrix>
511 return nextColumnIndex_;
514 template <
class Master_matrix>
515 template <
class Cell_range_or_column_index>
517 index targetColumnIndex)
520 index targetRep = columnClasses_.find_set(targetColumnIndex);
522 columnToRep_.erase(target);
523 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
524 target += get_column(sourceColumn);
526 target += sourceColumn;
528 _insert_column(targetRep);
531 template <
class Master_matrix>
532 template <
class Cell_range_or_column_index>
534 const Cell_range_or_column_index& sourceColumn,
const Field_element_type& coefficient,
index targetColumnIndex)
537 index targetRep = columnClasses_.find_set(targetColumnIndex);
539 columnToRep_.erase(target);
540 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
541 target.multiply_target_and_add(coefficient, get_column(sourceColumn));
543 target.multiply_target_and_add(coefficient, sourceColumn);
545 _insert_column(targetRep);
548 template <
class Master_matrix>
549 template <
class Cell_range_or_column_index>
551 const Field_element_type& coefficient,
const Cell_range_or_column_index& sourceColumn,
index targetColumnIndex)
554 index targetRep = columnClasses_.find_set(targetColumnIndex);
556 columnToRep_.erase(target);
557 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
558 target.multiply_source_and_add(get_column(sourceColumn), coefficient);
560 target.multiply_source_and_add(sourceColumn, coefficient);
562 _insert_column(targetRep);
565 template <
class Master_matrix>
568 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
569 if (col ==
nullptr)
return true;
570 return !col->is_non_zero(rowIndex);
573 template <
class Master_matrix>
576 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
577 if (col ==
nullptr)
return true;
578 return col->is_empty();
581 template <
class Master_matrix>
585 for (
auto col : repToColumn_) {
586 if (col !=
nullptr) {
587 columnPool_.destroy(col);
591 ra_opt::operator=(other);
592 columnClasses_ = other.columnClasses_;
593 columnToRep_.reserve(other.columnToRep_.size());
594 repToColumn_.resize(other.repToColumn_.size(),
nullptr);
595 nextColumnIndex_ = 0;
596 colSettings_ = other.colSettings_;
597 for (
const Column_type* col : other.repToColumn_) {
598 if constexpr (Master_matrix::Option_list::has_row_access) {
599 repToColumn_[nextColumnIndex_] =
600 columnPool_.construct(*col, col->get_column_index(), ra_opt::rows_, colSettings_);
602 repToColumn_[nextColumnIndex_] = columnPool_.construct(*col, colSettings_);
604 columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
605 repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
611 template <
class Master_matrix>
614 std::cout <<
"Compressed_matrix:\n";
615 for (Column_type& col : columnToRep_) {
616 for (
auto e : col->get_content(nextColumnIndex_)) {
620 std::cout << e <<
" ";
623 for (index i = 0; i < nextColumnIndex_; ++i) {
624 if (columnClasses_.find_set(i) == col.get_rep()) std::cout << i <<
" ";
629 std::cout <<
"Row Matrix:\n";
630 for (index i = 0; i < ra_opt::rows_->size(); ++i) {
631 const Row_type& row = ra_opt::rows_[i];
632 for (
const auto& cell : row) {
633 std::cout << cell.get_column_index() <<
" ";
635 std::cout <<
"(" << i <<
")\n";
640 template <
class Master_matrix>
641 inline void Base_matrix_with_column_compression<Master_matrix>::_insert_column(index columnIndex)
643 Column_type& col = *repToColumn_[columnIndex];
645 if (col.is_empty()) {
646 columnPool_.destroy(&col);
647 repToColumn_[columnIndex] =
nullptr;
651 col.set_rep(columnIndex);
652 auto res = columnToRep_.insert(col);
653 if (res.first->get_rep() != columnIndex) {
654 _insert_double_column(columnIndex, res.first);
658 template <
class Master_matrix>
659 inline void Base_matrix_with_column_compression<Master_matrix>::_insert_double_column(
660 index columnIndex,
typename col_dict_type::iterator& doubleIt)
662 index doubleRep = doubleIt->get_rep();
663 columnClasses_.link(columnIndex, doubleRep);
664 index newRep = columnClasses_.find_set(columnIndex);
666 columnPool_.destroy(repToColumn_[columnIndex]);
667 repToColumn_[columnIndex] =
nullptr;
669 if (newRep == columnIndex) {
670 std::swap(repToColumn_[doubleRep], repToColumn_[columnIndex]);
671 doubleIt->set_rep(columnIndex);
Type for columns. Only one for each "column class" is explicitely constructed.
Definition: base_matrix_with_column_compression.h:67
A base matrix (also see Base_matrix), but with column compression. That is, all identical columns in ...
Definition: base_matrix_with_column_compression.h:46
bool is_zero_cell(index columnIndex, index rowIndex)
Indicates if the cell at given coordinates has value zero.
Definition: base_matrix_with_column_compression.h:566
void reset(Column_settings *colSettings)
Resets the matrix to an empty matrix.
Definition: base_matrix_with_column_compression.h:298
typename Master_matrix::Column_settings Column_settings
Definition: base_matrix_with_column_compression.h:59
bool is_zero_column(index columnIndex)
Indicates if the column at given index has value zero.
Definition: base_matrix_with_column_compression.h:574
const Column_type & get_column(index columnIndex)
Returns the column at the given MatIdx index. The type of the column depends on the choosen options,...
Definition: base_matrix_with_column_compression.h:483
void erase_empty_row(index rowIndex)
If PersistenceMatrixOptions::has_row_access and PersistenceMatrixOptions::has_removable_rows are true...
Definition: base_matrix_with_column_compression.h:500
typename Master_matrix::dimension_type dimension_type
Definition: base_matrix_with_column_compression.h:49
void multiply_source_and_add_to(const Field_element_type &coefficient, const Cell_range_or_column_index &sourceColumn, index targetColumnIndex)
Multiplies the source column with the coefficiant before adding it to the target column....
Definition: base_matrix_with_column_compression.h:550
void add_to(const Cell_range_or_column_index &sourceColumn, index targetColumnIndex)
Adds column represented by sourceColumn onto the column at targetColumnIndex in the matrix.
Definition: base_matrix_with_column_compression.h:516
Base_matrix_with_column_compression(Column_settings *colSettings)
Constructs an empty matrix.
Definition: base_matrix_with_column_compression.h:359
typename Master_matrix::Field_operators Field_operators
Field operators class. Necessary only if PersistenceMatrixOptions::is_z2 is false.
Definition: base_matrix_with_column_compression.h:53
void insert_column(const Container_type &column)
Inserts a new ordered column at the end of the matrix by copying the given range of Matrix::cell_rep_...
Definition: base_matrix_with_column_compression.h:432
void insert_boundary(const Boundary_type &boundary, dimension_type dim=-1)
Same as insert_column, only for interface purposes. The given dimension is ignored and not stored.
Definition: base_matrix_with_column_compression.h:439
typename Master_matrix::Cell_constructor Cell_constructor
Definition: base_matrix_with_column_compression.h:57
void multiply_target_and_add_to(const Cell_range_or_column_index &sourceColumn, const Field_element_type &coefficient, index targetColumnIndex)
Multiplies the target column with the coefficiant and then adds the source column to it....
Definition: base_matrix_with_column_compression.h:533
typename Master_matrix::Row_type Row_type
Definition: base_matrix_with_column_compression.h:56
friend void swap(Base_matrix_with_column_compression &matrix1, Base_matrix_with_column_compression &matrix2)
Swap operator.
Definition: base_matrix_with_column_compression.h:313
const Row_type & get_row(index rowIndex) const
Only available if PersistenceMatrixOptions::has_row_access is true. Returns the row at the given row ...
Definition: base_matrix_with_column_compression.h:492
typename Master_matrix::index index
Definition: base_matrix_with_column_compression.h:48
~Base_matrix_with_column_compression()
Destructor.
Definition: base_matrix_with_column_compression.h:425
typename Master_matrix::element_type Field_element_type
Definition: base_matrix_with_column_compression.h:54
index get_number_of_columns() const
Returns the current number of columns in the matrix, counting also the redundant columns.
Definition: base_matrix_with_column_compression.h:509
Base_matrix_with_column_compression & operator=(const Base_matrix_with_column_compression &other)
Assign operator.
Definition: base_matrix_with_column_compression.h:583
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14