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(
this));
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_);
319 std::swap(matrix1.columnPool_, matrix2.columnPool_);
321 if constexpr (Master_matrix::Option_list::has_row_access) {
322 swap(
static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix1),
323 static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix2));
333 struct delete_disposer {
336 void operator()(Column_type* delete_this) { matrix_->columnPool_->destroy(delete_this); }
341 using ra_opt =
typename Master_matrix::Matrix_row_access_option;
342 using col_dict_type = boost::intrusive::set<Column_type, boost::intrusive::constant_time_size<false> >;
344 col_dict_type columnToRep_;
345 boost::disjoint_sets_with_storage<> columnClasses_;
347 std::vector<Column_type*> repToColumn_;
349 index nextColumnIndex_;
355 std::unique_ptr<Simple_object_pool<Column_type> > columnPool_;
356 inline static const Column_type empty_column_;
358 void _insert_column(
index columnIndex);
359 void _insert_double_column(
index columnIndex,
typename col_dict_type::iterator& doubleIt);
362 template <
class Master_matrix>
365 : ra_opt(), nextColumnIndex_(0), colSettings_(colSettings), columnPool_(new Simple_object_pool<
Column_type>)
368 template <
class Master_matrix>
369 template <
class Container_type>
371 const std::vector<Container_type>& columns,
Column_settings* colSettings)
372 : ra_opt(columns.size()),
373 columnClasses_(columns.size()),
374 repToColumn_(columns.size(), nullptr),
376 colSettings_(colSettings),
379 for (
const Container_type& c : columns) {
384 template <
class Master_matrix>
387 : ra_opt(numberOfColumns),
388 columnClasses_(numberOfColumns),
389 repToColumn_(numberOfColumns, nullptr),
391 colSettings_(colSettings),
395 template <
class Master_matrix>
398 : ra_opt(static_cast<const ra_opt&>(matrixToCopy)),
399 columnClasses_(matrixToCopy.columnClasses_),
400 repToColumn_(matrixToCopy.repToColumn_.size(), nullptr),
402 colSettings_(colSettings == nullptr ? matrixToCopy.colSettings_ : colSettings),
405 for (
const Column_type* col : matrixToCopy.repToColumn_) {
406 if (col !=
nullptr) {
407 if constexpr (Master_matrix::Option_list::has_row_access) {
408 repToColumn_[nextColumnIndex_] =
409 columnPool_->construct(*col, col->get_column_index(), ra_opt::rows_, colSettings_);
411 repToColumn_[nextColumnIndex_] = columnPool_->construct(*col, colSettings_);
413 columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
414 repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
420 template <
class Master_matrix>
423 : ra_opt(std::move(
static_cast<ra_opt&
>(other))),
424 columnToRep_(std::move(other.columnToRep_)),
425 columnClasses_(std::move(other.columnClasses_)),
426 repToColumn_(std::move(other.repToColumn_)),
427 nextColumnIndex_(std::exchange(other.nextColumnIndex_, 0)),
428 colSettings_(std::exchange(other.colSettings_,
nullptr)),
429 columnPool_(std::exchange(other.columnPool_,
nullptr))
432 template <
class Master_matrix>
435 columnToRep_.clear_and_dispose(delete_disposer(
this));
438 template <
class Master_matrix>
439 template <
class Container_type>
442 insert_boundary(column);
445 template <
class Master_matrix>
446 template <
class Boundary_type>
453 if (dim == -1) dim = boundary.size() == 0 ? 0 : boundary.size() - 1;
455 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_removable_rows) {
456 if (boundary.begin() != boundary.end()) {
458 if constexpr (Master_matrix::Option_list::is_z2) {
459 pivot = *std::prev(boundary.end());
461 pivot = std::prev(boundary.end())->first;
463 if (ra_opt::rows_->size() <= pivot) ra_opt::rows_->resize(pivot + 1);
467 if (repToColumn_.size() == nextColumnIndex_) {
469 columnClasses_.link(nextColumnIndex_, nextColumnIndex_);
470 if constexpr (Master_matrix::Option_list::has_row_access) {
471 repToColumn_.push_back(
472 columnPool_->construct(nextColumnIndex_, boundary, dim, ra_opt::rows_, colSettings_));
474 repToColumn_.push_back(columnPool_->construct(boundary, dim, colSettings_));
477 if constexpr (Master_matrix::Option_list::has_row_access) {
478 repToColumn_[nextColumnIndex_] =
479 columnPool_->construct(nextColumnIndex_, boundary, dim, ra_opt::rows_, colSettings_);
481 repToColumn_[nextColumnIndex_] = columnPool_->construct(boundary, dim, colSettings_);
484 _insert_column(nextColumnIndex_);
489 template <
class Master_matrix>
493 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
494 if (col ==
nullptr)
return empty_column_;
498 template <
class Master_matrix>
502 static_assert(Master_matrix::Option_list::has_row_access,
"Row access has to be enabled for this method.");
504 return ra_opt::get_row(rowIndex);
507 template <
class Master_matrix>
510 if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_removable_rows) {
511 ra_opt::erase_empty_row(rowIndex);
515 template <
class Master_matrix>
519 return nextColumnIndex_;
522 template <
class Master_matrix>
523 template <
class Cell_range_or_column_index>
525 index targetColumnIndex)
528 index targetRep = columnClasses_.find_set(targetColumnIndex);
530 columnToRep_.erase(target);
531 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
532 target += get_column(sourceColumn);
534 target += sourceColumn;
536 _insert_column(targetRep);
539 template <
class Master_matrix>
540 template <
class Cell_range_or_column_index>
542 const Cell_range_or_column_index& sourceColumn,
const Field_element_type& coefficient,
index targetColumnIndex)
545 index targetRep = columnClasses_.find_set(targetColumnIndex);
547 columnToRep_.erase(target);
548 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
549 target.multiply_target_and_add(coefficient, get_column(sourceColumn));
551 target.multiply_target_and_add(coefficient, sourceColumn);
553 _insert_column(targetRep);
556 template <
class Master_matrix>
557 template <
class Cell_range_or_column_index>
559 const Field_element_type& coefficient,
const Cell_range_or_column_index& sourceColumn,
index targetColumnIndex)
562 index targetRep = columnClasses_.find_set(targetColumnIndex);
564 columnToRep_.erase(target);
565 if constexpr (std::is_integral_v<Cell_range_or_column_index>) {
566 target.multiply_source_and_add(get_column(sourceColumn), coefficient);
568 target.multiply_source_and_add(sourceColumn, coefficient);
570 _insert_column(targetRep);
573 template <
class Master_matrix>
576 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
577 if (col ==
nullptr)
return true;
578 return !col->is_non_zero(rowIndex);
581 template <
class Master_matrix>
584 auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
585 if (col ==
nullptr)
return true;
586 return col->is_empty();
589 template <
class Master_matrix>
593 for (
auto col : repToColumn_) {
594 if (col !=
nullptr) {
595 columnPool_->destroy(col);
599 ra_opt::operator=(other);
600 columnClasses_ = other.columnClasses_;
601 columnToRep_.reserve(other.columnToRep_.size());
602 repToColumn_.resize(other.repToColumn_.size(),
nullptr);
603 nextColumnIndex_ = 0;
604 colSettings_ = other.colSettings_;
605 for (
const Column_type* col : other.repToColumn_) {
606 if constexpr (Master_matrix::Option_list::has_row_access) {
607 repToColumn_[nextColumnIndex_] =
608 columnPool_->construct(*col, col->get_column_index(), ra_opt::rows_, colSettings_);
610 repToColumn_[nextColumnIndex_] = columnPool_->construct(*col, colSettings_);
612 columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
613 repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
619 template <
class Master_matrix>
622 std::cout <<
"Compressed_matrix:\n";
623 for (Column_type& col : columnToRep_) {
624 for (
auto e : col->get_content(nextColumnIndex_)) {
628 std::cout << e <<
" ";
631 for (index i = 0; i < nextColumnIndex_; ++i) {
632 if (columnClasses_.find_set(i) == col.get_rep()) std::cout << i <<
" ";
637 std::cout <<
"Row Matrix:\n";
638 for (index i = 0; i < ra_opt::rows_->size(); ++i) {
639 const Row_type& row = ra_opt::rows_[i];
640 for (
const auto& cell : row) {
641 std::cout << cell.get_column_index() <<
" ";
643 std::cout <<
"(" << i <<
")\n";
648 template <
class Master_matrix>
649 inline void Base_matrix_with_column_compression<Master_matrix>::_insert_column(index columnIndex)
651 Column_type& col = *repToColumn_[columnIndex];
653 if (col.is_empty()) {
654 columnPool_->destroy(&col);
655 repToColumn_[columnIndex] =
nullptr;
659 col.set_rep(columnIndex);
660 auto res = columnToRep_.insert(col);
661 if (res.first->get_rep() != columnIndex) {
662 _insert_double_column(columnIndex, res.first);
666 template <
class Master_matrix>
667 inline void Base_matrix_with_column_compression<Master_matrix>::_insert_double_column(
668 index columnIndex,
typename col_dict_type::iterator& doubleIt)
670 index doubleRep = doubleIt->get_rep();
671 columnClasses_.link(columnIndex, doubleRep);
672 index newRep = columnClasses_.find_set(columnIndex);
674 columnPool_->destroy(repToColumn_[columnIndex]);
675 repToColumn_[columnIndex] =
nullptr;
677 if (newRep == columnIndex) {
678 std::swap(repToColumn_[doubleRep], repToColumn_[columnIndex]);
679 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:574
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:582
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:491
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:508
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:558
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:524
Base_matrix_with_column_compression(Column_settings *colSettings)
Constructs an empty matrix.
Definition: base_matrix_with_column_compression.h:363
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:440
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:447
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:541
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:500
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:433
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:517
Base_matrix_with_column_compression & operator=(const Base_matrix_with_column_compression &other)
Assign operator.
Definition: base_matrix_with_column_compression.h:591
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14