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> 
   30namespace persistence_matrix {
 
   44template <
class Master_matrix>
 
   48  using Index = 
typename Master_matrix::Index;                          
 
   49  using Dimension = 
typename Master_matrix::Dimension;                  
 
   55  using Row = 
typename Master_matrix::Row;                              
 
   65      : 
public Master_matrix::Column,
 
   66        public boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >
 
   69    using Base = 
typename Master_matrix::Column;
 
   72        : Base(colSettings) {}
 
   73    template <
class Container>
 
   75        : Base(nonZeroRowIndices, colSettings) {}
 
   76    template <
class Container, 
class Row_container>
 
   77    Column(
Index columnIndex, 
const Container& nonZeroRowIndices, Row_container& rowContainer,
 
   79        : Base(columnIndex, nonZeroRowIndices, rowContainer, colSettings) {}
 
   80    template <
class Container>
 
   82        : Base(nonZeroRowIndices, dimension, colSettings) {}
 
   83    template <
class Container, 
class Row_container>
 
   86        : Base(columnIndex, nonZeroRowIndices, dimension, rowContainer, colSettings) {}
 
   88        : Base(
static_cast<const Base&
>(column), colSettings) {}
 
   89    template <
class Row_container>
 
   92        : Base(
static_cast<const Base&
>(column), columnIndex, rowContainer, colSettings) {}
 
   93    Column(
Column&& column) noexcept : Base(std::move(
static_cast<Base&
>(column))) {}
 
   99    Index get_rep()
 const { 
return rep_; }
 
  100    void set_rep(
const Index& rep) { rep_ = rep; }
 
  103      size_t operator()(
const Column& c)
 const { 
return std::hash<Base>()(
static_cast<Base
>(c)); }
 
  129  template <
class Container>
 
  171  template <
class Container>
 
  182  template <
class Boundary_range>
 
  184                       Dimension dim = Master_matrix::template get_null_value<Dimension>());
 
  239  template <
class Entry_range_or_column_index>
 
  240  void add_to(
const Entry_range_or_column_index& sourceColumn, 
Index targetColumnIndex);
 
  254  template <
class Entry_range_or_column_index>
 
  257                                  Index targetColumnIndex);
 
  271  template <
class Entry_range_or_column_index>
 
  273                                  const Entry_range_or_column_index& sourceColumn,
 
  274                                  Index targetColumnIndex);
 
  300    columnToRep_.clear_and_dispose(Delete_disposer(
this));
 
  301    columnClasses_ = boost::disjoint_sets_with_storage<>();
 
  302    repToColumn_.clear();
 
  303    nextColumnIndex_ = 0;
 
  304    colSettings_ = colSettings;
 
  315    matrix1.columnToRep_.swap(matrix2.columnToRep_);
 
  316    std::swap(matrix1.columnClasses_, matrix2.columnClasses_);
 
  317    matrix1.repToColumn_.swap(matrix2.repToColumn_);
 
  318    std::swap(matrix1.nextColumnIndex_, matrix2.nextColumnIndex_);
 
  319    std::swap(matrix1.colSettings_, matrix2.colSettings_);
 
  320    std::swap(matrix1.columnPool_, matrix2.columnPool_);
 
  322    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  323      swap(
static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix1),
 
  324           static_cast<typename Master_matrix::Matrix_row_access_option&
>(matrix2));
 
  334  struct Delete_disposer {
 
  337    void operator()(Column* delete_this) { matrix_->columnPool_->destroy(delete_this); }
 
  342  using RA_opt = 
typename Master_matrix::Matrix_row_access_option;
 
  343  using Col_dict = boost::intrusive::set<Column, boost::intrusive::constant_time_size<false> >;
 
  345  Col_dict columnToRep_;                              
 
  346  boost::disjoint_sets_with_storage<> columnClasses_; 
 
  348  std::vector<Column*> repToColumn_;                  
 
  350  Index nextColumnIndex_;                             
 
  356  std::unique_ptr<Simple_object_pool<Column> > columnPool_;
 
  357  inline static const Column empty_column_;           
 
  359  void _insert_column(Index columnIndex);
 
  360  void _insert_double_column(Index columnIndex, 
typename Col_dict::iterator& doubleIt);
 
  363template <
class Master_matrix>
 
  366    : RA_opt(), nextColumnIndex_(0), colSettings_(colSettings), columnPool_(new Simple_object_pool<
Column>)
 
  369template <
class Master_matrix>
 
  370template <
class Container>
 
  373    : RA_opt(columns.size()),
 
  374      columnClasses_(columns.size()),
 
  375      repToColumn_(columns.size(), nullptr),
 
  377      colSettings_(colSettings),
 
  378      columnPool_(new Simple_object_pool<
Column>)
 
  380  for (
const Container& c : columns) {
 
  385template <
class Master_matrix>
 
  388    : RA_opt(numberOfColumns),
 
  389      columnClasses_(numberOfColumns),
 
  390      repToColumn_(numberOfColumns, nullptr),
 
  392      colSettings_(colSettings),
 
  393      columnPool_(new Simple_object_pool<
Column>)
 
  396template <
class Master_matrix>
 
  399    : RA_opt(static_cast<const RA_opt&>(matrixToCopy)),
 
  400      columnClasses_(matrixToCopy.columnClasses_),
 
  401      repToColumn_(matrixToCopy.repToColumn_.size(), nullptr),
 
  403      colSettings_(colSettings == nullptr ? matrixToCopy.colSettings_ : colSettings),
 
  404      columnPool_(new Simple_object_pool<
Column>)
 
  406  for (
const Column* col : matrixToCopy.repToColumn_) {
 
  407    if (col != 
nullptr) {
 
  408      if constexpr (Master_matrix::Option_list::has_row_access) {
 
  409        repToColumn_[nextColumnIndex_] =
 
  410            columnPool_->construct(*col, col->get_column_index(), RA_opt::rows_, colSettings_);
 
  412        repToColumn_[nextColumnIndex_] = columnPool_->construct(*col, colSettings_);
 
  414      columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
 
  415      repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
 
  421template <
class Master_matrix>
 
  424    : RA_opt(std::move(
static_cast<RA_opt&
>(other))),
 
  425      columnToRep_(std::move(other.columnToRep_)),
 
  426      columnClasses_(std::move(other.columnClasses_)),
 
  427      repToColumn_(std::move(other.repToColumn_)),
 
  428      nextColumnIndex_(std::exchange(other.nextColumnIndex_, 0)),
 
  429      colSettings_(std::exchange(other.colSettings_, 
nullptr)),
 
  430      columnPool_(std::exchange(other.columnPool_, 
nullptr))
 
  433template <
class Master_matrix>
 
  436  columnToRep_.clear_and_dispose(Delete_disposer(
this));
 
  439template <
class Master_matrix>
 
  440template <
class Container>
 
  443  insert_boundary(column);
 
  446template <
class Master_matrix>
 
  447template <
class Boundary_range>
 
  454  if (dim == Master_matrix::template get_null_value<Dimension>()) dim = boundary.size() == 0 ? 0 : boundary.size() - 1;
 
  456  if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_removable_rows) {
 
  457    if (boundary.begin() != boundary.end()) {
 
  459      if constexpr (Master_matrix::Option_list::is_z2) {
 
  460        pivot = *std::prev(boundary.end());
 
  462        pivot = std::prev(boundary.end())->first;
 
  464      if (RA_opt::rows_->size() <= pivot) RA_opt::rows_->resize(pivot + 1);
 
  468  if (repToColumn_.size() == nextColumnIndex_) {
 
  470    columnClasses_.link(nextColumnIndex_, nextColumnIndex_);
 
  471    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  472      repToColumn_.push_back(
 
  473          columnPool_->construct(nextColumnIndex_, boundary, dim, RA_opt::rows_, colSettings_));
 
  475      repToColumn_.push_back(columnPool_->construct(boundary, dim, colSettings_));
 
  478    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  479      repToColumn_[nextColumnIndex_] =
 
  480          columnPool_->construct(nextColumnIndex_, boundary, dim, RA_opt::rows_, colSettings_);
 
  482      repToColumn_[nextColumnIndex_] = columnPool_->construct(boundary, dim, colSettings_);
 
  485  _insert_column(nextColumnIndex_);
 
  490template <
class Master_matrix>
 
  494  auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
 
  495  if (col == 
nullptr) 
return empty_column_;
 
  499template <
class Master_matrix>
 
  503  static_assert(Master_matrix::Option_list::has_row_access, 
"Row access has to be enabled for this method.");
 
  505  return RA_opt::get_row(rowIndex);
 
  508template <
class Master_matrix>
 
  511  if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_removable_rows) {
 
  512    RA_opt::erase_empty_row(rowIndex);
 
  516template <
class Master_matrix>
 
  520  return nextColumnIndex_;
 
  523template <
class Master_matrix>
 
  524template <
class Entry_range_or_column_index>
 
  526                                                                       Index targetColumnIndex)
 
  529  Index targetRep = columnClasses_.find_set(targetColumnIndex);
 
  530  Column& target = *repToColumn_[targetRep];
 
  531  columnToRep_.erase(target);
 
  532  if constexpr (std::is_integral_v<Entry_range_or_column_index>) {
 
  533    target += get_column(sourceColumn);
 
  535    target += sourceColumn;
 
  537  _insert_column(targetRep);
 
  540template <
class Master_matrix>
 
  541template <
class Entry_range_or_column_index>
 
  543    const Entry_range_or_column_index& sourceColumn, 
const Field_element& coefficient, 
Index targetColumnIndex)
 
  546  Index targetRep = columnClasses_.find_set(targetColumnIndex);
 
  547  Column& target = *repToColumn_[targetRep];
 
  548  columnToRep_.erase(target);
 
  549  if constexpr (std::is_integral_v<Entry_range_or_column_index>) {
 
  550    target.multiply_target_and_add(coefficient, get_column(sourceColumn));
 
  552    target.multiply_target_and_add(coefficient, sourceColumn);
 
  554  _insert_column(targetRep);
 
  557template <
class Master_matrix>
 
  558template <
class Entry_range_or_column_index>
 
  560    const Field_element& coefficient, 
const Entry_range_or_column_index& sourceColumn, 
Index targetColumnIndex)
 
  563  Index targetRep = columnClasses_.find_set(targetColumnIndex);
 
  564  Column& target = *repToColumn_[targetRep];
 
  565  columnToRep_.erase(target);
 
  566  if constexpr (std::is_integral_v<Entry_range_or_column_index>) {
 
  567    target.multiply_source_and_add(get_column(sourceColumn), coefficient);
 
  569    target.multiply_source_and_add(sourceColumn, coefficient);
 
  571  _insert_column(targetRep);
 
  574template <
class Master_matrix>
 
  577  auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
 
  578  if (col == 
nullptr) 
return true;
 
  579  return !col->is_non_zero(rowIndex);
 
  582template <
class Master_matrix>
 
  585  auto col = repToColumn_[columnClasses_.find_set(columnIndex)];
 
  586  if (col == 
nullptr) 
return true;
 
  587  return col->is_empty();
 
  590template <
class Master_matrix>
 
  594  for (
auto col : repToColumn_) {
 
  595    if (col != 
nullptr) {
 
  596      columnPool_->destroy(col);
 
  600  RA_opt::operator=(other);
 
  601  columnClasses_ = other.columnClasses_;
 
  602  columnToRep_.reserve(other.columnToRep_.size());
 
  603  repToColumn_.resize(other.repToColumn_.size(), 
nullptr);
 
  604  nextColumnIndex_ = 0;
 
  605  colSettings_ = other.colSettings_;
 
  606  for (
const Column* col : other.repToColumn_) {
 
  607    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  608      repToColumn_[nextColumnIndex_] =
 
  609          columnPool_->construct(*col, col->get_column_index(), RA_opt::rows_, colSettings_);
 
  611      repToColumn_[nextColumnIndex_] = columnPool_->construct(*col, colSettings_);
 
  613    columnToRep_.insert(columnToRep_.end(), *repToColumn_[nextColumnIndex_]);
 
  614    repToColumn_[nextColumnIndex_]->set_rep(nextColumnIndex_);
 
  620template <
class Master_matrix>
 
  623  std::cout << 
"Compressed_matrix:\n";
 
  624  for (Column& col : columnToRep_) {
 
  625    for (
auto e : col->get_content(nextColumnIndex_)) {
 
  629        std::cout << e << 
" ";
 
  632    for (Index i = 0; i < nextColumnIndex_; ++i) {
 
  633      if (columnClasses_.find_set(i) == col.get_rep()) std::cout << i << 
" ";
 
  638  std::cout << 
"Row Matrix:\n";
 
  639  for (Index i = 0; i < RA_opt::rows_->size(); ++i) {
 
  640    const Row& row = RA_opt::rows_[i];
 
  641    for (
const auto& entry : row) {
 
  642      std::cout << entry.get_column_index() << 
" ";
 
  644    std::cout << 
"(" << i << 
")\n";
 
  649template <
class Master_matrix>
 
  650inline void Base_matrix_with_column_compression<Master_matrix>::_insert_column(Index columnIndex)
 
  652  Column& col = *repToColumn_[columnIndex];
 
  654  if (col.is_empty()) {
 
  655    columnPool_->destroy(&col);  
 
  656    repToColumn_[columnIndex] = 
nullptr;
 
  660  col.set_rep(columnIndex);
 
  661  auto res = columnToRep_.insert(col);
 
  662  if (res.first->get_rep() != columnIndex) {  
 
  663    _insert_double_column(columnIndex, res.first);
 
  667template <
class Master_matrix>
 
  668inline void Base_matrix_with_column_compression<Master_matrix>::_insert_double_column(
 
  669    Index columnIndex, 
typename Col_dict::iterator& doubleIt)
 
  671  Index doubleRep = doubleIt->get_rep();
 
  672  columnClasses_.link(columnIndex, doubleRep);  
 
  673  Index newRep = columnClasses_.find_set(columnIndex);
 
  675  columnPool_->destroy(repToColumn_[columnIndex]);
 
  676  repToColumn_[columnIndex] = 
nullptr;
 
  678  if (newRep == columnIndex) {
 
  679    std::swap(repToColumn_[doubleRep], repToColumn_[columnIndex]);
 
  680    doubleIt->set_rep(columnIndex);
 
Type for columns. Only one for each "column class" is explicitly 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
 
typename Master_matrix::Index Index
Definition: Base_matrix_with_column_compression.h:48
 
typename Master_matrix::Row Row
Definition: Base_matrix_with_column_compression.h:56
 
void reset(Column_settings *colSettings)
Resets the matrix to an empty matrix.
Definition: Base_matrix_with_column_compression.h:299
 
typename Master_matrix::Column_settings Column_settings
Definition: Base_matrix_with_column_compression.h:59
 
typename Master_matrix::Dimension Dimension
Definition: Base_matrix_with_column_compression.h:49
 
const Row & 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:501
 
void add_to(const Entry_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:525
 
Base_matrix_with_column_compression(Column_settings *colSettings)
Constructs an empty matrix.
Definition: Base_matrix_with_column_compression.h:364
 
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
 
bool is_zero_column(Index columnIndex)
Indicates if the column at given index has value zero.
Definition: Base_matrix_with_column_compression.h:583
 
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:518
 
void multiply_source_and_add_to(const Field_element &coefficient, const Entry_range_or_column_index &sourceColumn, Index targetColumnIndex)
Multiplies the source column with the coefficient before adding it to the target column....
Definition: Base_matrix_with_column_compression.h:559
 
void multiply_target_and_add_to(const Entry_range_or_column_index &sourceColumn, const Field_element &coefficient, Index targetColumnIndex)
Multiplies the target column with the coefficient and then adds the source column to it....
Definition: Base_matrix_with_column_compression.h:542
 
friend void swap(Base_matrix_with_column_compression &matrix1, Base_matrix_with_column_compression &matrix2)
Swap operator.
Definition: Base_matrix_with_column_compression.h:314
 
~Base_matrix_with_column_compression()
Destructor.
Definition: Base_matrix_with_column_compression.h:434
 
void insert_column(const Container &column)
Inserts a new ordered column at the end of the matrix by copying the given range of Matrix::Entry_rep...
Definition: Base_matrix_with_column_compression.h:441
 
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:509
 
typename Master_matrix::Entry_constructor Entry_constructor
Definition: Base_matrix_with_column_compression.h:57
 
typename Master_matrix::Element Field_element
Definition: Base_matrix_with_column_compression.h:54
 
const Column & get_column(Index columnIndex)
Returns the column at the given MatIdx index. The type of the column depends on the chosen options,...
Definition: Base_matrix_with_column_compression.h:492
 
void insert_boundary(const Boundary_range &boundary, Dimension dim=Master_matrix::template get_null_value< Dimension >())
Same as insert_column, only for interface purposes. The given dimension is ignored and not stored.
Definition: Base_matrix_with_column_compression.h:448
 
Base_matrix_with_column_compression & operator=(const Base_matrix_with_column_compression &other)
Assign operator.
Definition: Base_matrix_with_column_compression.h:592
 
bool is_zero_entry(Index columnIndex, Index rowIndex)
Indicates if the entry at given coordinates has value zero.
Definition: Base_matrix_with_column_compression.h:575
 
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14