20#ifndef ZIGZAG_PERSISTENCE_H_
21#define ZIGZAG_PERSISTENCE_H_
28#include <boost/iterator/indirect_iterator.hpp>
29#if BOOST_VERSION >= 108100
30#include <boost/unordered/unordered_flat_map.hpp>
33#include <unordered_map>
39namespace zigzag_persistence {
48template <Gudhi::persistence_matrix::Column_types column_type>
50 static const bool has_row_access =
true;
51 static const bool has_column_pairings =
false;
52 static const bool has_vine_update =
true;
53 static const bool is_of_boundary_type =
false;
54 static const bool has_map_column_container =
true;
55 static const bool has_removable_columns =
true;
56 static const bool has_removable_rows =
true;
147template <
class ZigzagOptions = Default_zigzag_options>
156#if BOOST_VERSION >= 108100
157 using Birth_dictionary = boost::unordered_flat_map<Index, Index>;
160 using Birth_dictionary = std::unordered_map<Index, Index>;
185 struct Birth_ordering {
189 Birth_ordering() : birthToPos_(), maxBirthPos_(0), minBirthPos_(-1) {}
198 void add_birth_forward(
Index arrowNumber) {
199 birthToPos_.emplace_hint(birthToPos_.end(), arrowNumber, maxBirthPos_);
209 void add_birth_backward(
Index arrowNumber) {
210 birthToPos_.emplace_hint(birthToPos_.end(), arrowNumber, minBirthPos_);
221 void remove_birth(
Index birth) { birthToPos_.erase(birth); }
229 bool birth_order(
Index k1,
Index k2)
const {
return birthToPos_.at(k1) < birthToPos_.at(k2); }
237 bool reverse_birth_order(
Index k1,
Index k2)
const {
return birthToPos_.at(k1) > birthToPos_.at(k2); }
240 Birth_dictionary birthToPos_;
264 unsigned int preallocationSize = 0)
267 [this](Matrix_index columnIndex1, Matrix_index columnIndex2) -> bool {
268 if (matrix_.get_column(columnIndex1).is_paired()) {
271 return birthOrdering_.birth_order(births_.at(columnIndex1), births_.at(columnIndex2));
273 [
this](Matrix_index columnIndex1, Matrix_index columnIndex2) ->
bool {
return false; }),
275 stream_interval_(std::move(stream_interval)) {}
287 template <
class BoundaryRange = std::initializer_list<Index> >
290 _process_forward_arrow(boundary, dimension);
302 _process_backward_arrow(arrowNumber);
322 template <
typename F>
324 for (
auto& p : births_) {
325 auto& col = matrix_.get_column(p.first);
326 stream_infinite_interval(col.get_dimension(), p.second);
339 template <
class BoundaryRange>
340 void _process_forward_arrow(
const BoundaryRange& boundary, Dimension dim) {
341 std::vector<Matrix_index> chainsInF = matrix_.insert_boundary(numArrow_, boundary, dim);
343 if (!chainsInF.empty()) {
344 _apply_surjective_reflection_diamond(dim, chainsInF);
346 birthOrdering_.add_birth_forward(numArrow_);
347 births_[matrix_.get_column_with_pivot(numArrow_)] = numArrow_;
362 void _apply_surjective_reflection_diamond(Dimension dim,
const std::vector<Matrix_index>& chainsInF) {
365 auto chainFp = chainsInF[0];
373 auto cmp_birth = [
this](Index k1, Index k2) ->
bool {
374 return birthOrdering_.reverse_birth_order(k1, k2);
379 std::set<Index,
decltype(cmp_birth)> availableBirth(cmp_birth);
381 for (
auto& chainF : chainsInF) {
382 availableBirth.insert(births_.at(chainF));
385 auto maxbIt = availableBirth.begin();
387 availableBirth.erase(maxbIt);
389 auto lastModifiedChainIt = chainsInF.rbegin();
392 for (
auto chainFIt = chainsInF.rbegin();
393 *chainFIt != chainFp; ++chainFIt)
395 auto birthIt = availableBirth.find(births_.at(*chainFIt));
396 if (birthIt == availableBirth.end())
412 for (
auto chainPassedIt = lastModifiedChainIt; chainPassedIt != chainFIt; ++chainPassedIt) {
414 matrix_.add_to(*chainPassedIt, *chainFIt);
416 lastModifiedChainIt = chainFIt;
418 auto maxAvailBirthIt = availableBirth.begin();
419 Index maxAvailBirth = *maxAvailBirthIt;
421 births_.at(*chainFIt) = maxAvailBirth;
422 availableBirth.erase(maxAvailBirthIt);
424 availableBirth.erase(birthIt);
428 birthOrdering_.remove_birth(maxb);
429 births_.erase(chainFp);
432 stream_interval_(dim - 1, maxb, numArrow_);
440 void _process_backward_arrow(Index cellID) {
442 Matrix_index currCol = matrix_.get_column_with_pivot(cellID);
445 std::vector<Matrix_index> modifiedColumns;
446 const auto& row = matrix_.get_row(cellID);
447 modifiedColumns.reserve(row.size());
448 std::transform(row.begin(), row.end(), std::back_inserter(modifiedColumns),
449 [](
const auto& cell) { return cell.get_column_index(); });
451 std::stable_sort(modifiedColumns.begin(), modifiedColumns.end(), [
this](Matrix_index i1, Matrix_index i2) {
452 return matrix_.get_pivot(i1) < matrix_.get_pivot(i2);
456 for (
auto otherColIt = std::next(modifiedColumns.begin()); otherColIt != modifiedColumns.end(); ++otherColIt) {
457 currCol = matrix_.vine_swap_with_z_eq_1_case(currCol, *otherColIt);
461 auto& col = matrix_.get_column(currCol);
462 if (!col.is_paired()) {
463 auto it = births_.find(currCol);
464 stream_interval_(col.get_dimension(), it->second, numArrow_);
465 birthOrdering_.remove_birth(it->second);
469 birthOrdering_.add_birth_backward(numArrow_);
470 births_[col.get_paired_chain_index()] = numArrow_;
474 matrix_.remove_maximal_cell(cellID, {});
479 Birth_dictionary births_;
480 Birth_ordering birthOrdering_;
482 std::function<void(Dimension, Index, Index)> stream_interval_;
Contains Gudhi::persistence_matrix::Matrix class.
ID_index get_pivot(Index columnIndex)
Returns the row index of the pivot of the given column. Only available for non-basic matrices.
Definition: Matrix.h:1930
typename PersistenceMatrixOptions::Index Index
Definition: Matrix.h:147
Class computing the zigzag persistent homology of a zigzag sequence. Algorithm based on .
Definition: zigzag_persistence.h:149
Zigzag_persistence(std::function< void(Dimension, Index, Index)> stream_interval, unsigned int preallocationSize=0)
Constructor of the Zigzag_persistence class.
Definition: zigzag_persistence.h:263
Index remove_cell(Index arrowNumber)
Updates the zigzag persistence diagram after the removal of the given cell.
Definition: zigzag_persistence.h:300
Index insert_cell(const BoundaryRange &boundary, Dimension dimension)
Updates the zigzag persistence diagram after the insertion of the given cell.
Definition: zigzag_persistence.h:288
Index apply_identity()
To use when a cell is neither inserted nor removed, but the filtration moves along the identity opera...
Definition: zigzag_persistence.h:312
typename Options::Dimension Dimension
Definition: zigzag_persistence.h:153
typename Options::Internal_key Index
Definition: zigzag_persistence.h:152
void get_current_infinite_intervals(F &&stream_infinite_interval)
Outputs through the given callback method all birth indices which are currently not paired with a dea...
Definition: zigzag_persistence.h:323
Column_types
List of column types.
Definition: persistence_matrix_options.h:30
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
Default option structure for Matrix class. See the PersistenceMatrixOptions concept for a more detail...
Definition: persistence_matrix_options.h:79
Default options for Zigzag_persistence.
Definition: zigzag_persistence.h:64
int Internal_key
Definition: zigzag_persistence.h:65
int Dimension
Definition: zigzag_persistence.h:66
static const Gudhi::persistence_matrix::Column_types column_type
Column type use by the internal matrix.
Definition: zigzag_persistence.h:70
unspecified Dimension
Type for the dimension values.
Definition: ZigzagOptions.h:47
unspecified Internal_key
Numerical type for the cell IDs used internally and other indexations. It must be signed.
Definition: ZigzagOptions.h:31
Options for the internal matrix of Zigzag_persistence.
Definition: zigzag_persistence.h:49
List of options used for the zigzag persistence computation.
Definition: ZigzagOptions.h:60