base_pairing.h
Go to the documentation of this file.
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Hannah Schreiber
4 *
5 * Copyright (C) 2022-24 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
18#ifndef PM_BASE_PAIRING_H
19#define PM_BASE_PAIRING_H
20
21#include <utility> //std::swap & std::move
22#include <unordered_map>
23#include <algorithm>
24#include <vector>
25
27
28namespace Gudhi {
29namespace persistence_matrix {
30
39 friend void swap([[maybe_unused]] Dummy_base_pairing& d1, [[maybe_unused]] Dummy_base_pairing& d2) {}
40};
41
50template <class Master_matrix>
51class Base_pairing : public std::conditional<
52 Master_matrix::Option_list::has_removable_columns,
53 Cell_position_to_ID_mapper<typename Master_matrix::ID_index, typename Master_matrix::Pos_index>,
54 Dummy_pos_mapper
55 >::type
56{
57 public:
58 using Bar = typename Master_matrix::Bar;
59 using Barcode = typename Master_matrix::Barcode;
60 using Column_container = typename Master_matrix::Column_container;
61 using Index = typename Master_matrix::Index;
62 using Dimension = typename Master_matrix::Dimension;
68
79
83 friend void swap(Base_pairing& pairing1, Base_pairing& pairing2) {
84 if constexpr (Master_matrix::Option_list::has_removable_columns) {
85 swap(static_cast<Cell_position_to_ID_mapper<ID_index, Pos_index>&>(pairing1),
86 static_cast<Cell_position_to_ID_mapper<ID_index, Pos_index>&>(pairing2));
87 }
88 pairing1.barcode_.swap(pairing2.barcode_);
89 pairing1.deathToBar_.swap(pairing2.deathToBar_);
90 pairing1.idToPosition_.swap(pairing2.idToPosition_);
91 std::swap(pairing1.isReduced_, pairing2.isReduced_);
92 }
93
94 protected:
95 using Pos_index = typename Master_matrix::Pos_index;
96 using ID_index = typename Master_matrix::ID_index;
97 using Dictionary = typename Master_matrix::Bar_dictionary;
98 using Base_matrix = typename Master_matrix::Master_boundary_matrix;
99 //PIDM = Position to ID Map
100 using PIDM = typename std::conditional<Master_matrix::Option_list::has_removable_columns,
101 Cell_position_to_ID_mapper<ID_index, Pos_index>,
102 Dummy_pos_mapper
103 >::type;
104
105 Barcode barcode_;
106 Dictionary deathToBar_;
110 std::unordered_map<ID_index,Pos_index> idToPosition_; //TODO: test other map types
111 bool isReduced_;
113 void _reduce();
114 void _remove_last(Pos_index columnIndex);
115
116 //access to inheriting Boundary_matrix class
117 constexpr Base_matrix* _matrix() { return static_cast<Base_matrix*>(this); }
118 constexpr const Base_matrix* _matrix() const { return static_cast<const Base_matrix*>(this); }
119};
120
121template <class Master_matrix>
122inline Base_pairing<Master_matrix>::Base_pairing() : PIDM(), isReduced_(false)
123{}
124
125template <class Master_matrix>
127{
128 if (!isReduced_) _reduce();
129 return barcode_;
130}
131
132template <class Master_matrix>
134{
135 constexpr const Pos_index nullDeath = Master_matrix::template get_null_value<Pos_index>();
136 constexpr const Index nullIndex = Master_matrix::template get_null_value<Index>();
137
138 std::unordered_map<Index, Index> negativeColumns(_matrix()->get_number_of_columns());
139
140 auto dim = _matrix()->get_max_dimension();
141 std::vector<std::vector<Index> > columnsByDim(dim + 1);
142 for (auto& v : columnsByDim) v.reserve(_matrix()->get_number_of_columns());
143 for (unsigned int i = 0; i < _matrix()->get_number_of_columns(); i++) {
144 columnsByDim[dim - _matrix()->get_column_dimension(i)].push_back(i);
145 }
146
147 for (const auto& cols : columnsByDim) {
148 for (Index i : cols) {
149 auto& curr = _matrix()->get_column(i);
150 if (curr.is_empty()) {
151 if (negativeColumns.find(i) == negativeColumns.end()) {
152 barcode_.emplace_back(i, nullDeath, dim);
153 }
154 } else {
155 ID_index pivot = curr.get_pivot();
156 auto it = idToPosition_.find(pivot);
157 Index pivotColumnNumber = it == idToPosition_.end() ? pivot : it->second;
158 auto itNeg = negativeColumns.find(pivotColumnNumber);
159 Index pivotKiller = itNeg == negativeColumns.end() ? nullIndex : itNeg->second;
160
161 while (pivot != Master_matrix::template get_null_value<ID_index>() &&
162 pivotKiller != Master_matrix::template get_null_value<Index>()) {
163 if constexpr (Master_matrix::Option_list::is_z2) {
164 curr += _matrix()->get_column(pivotKiller);
165 } else {
166 auto& toadd = _matrix()->get_column(pivotKiller);
167 typename Master_matrix::Element coef = toadd.get_pivot_value();
168 auto& operators = _matrix()->colSettings_->operators;
169 coef = operators.get_inverse(coef);
170 operators.multiply_inplace(coef, operators.get_characteristic() - curr.get_pivot_value());
171 curr.multiply_source_and_add(toadd, coef);
172 }
173
174 pivot = curr.get_pivot();
175 it = idToPosition_.find(pivot);
176 pivotColumnNumber = it == idToPosition_.end() ? pivot : it->second;
177 itNeg = negativeColumns.find(pivotColumnNumber);
178 pivotKiller = itNeg == negativeColumns.end() ? nullIndex : itNeg->second;
179 }
180
181 if (pivot != Master_matrix::template get_null_value<ID_index>()) {
182 negativeColumns.emplace(pivotColumnNumber, i);
183 _matrix()->get_column(pivotColumnNumber).clear();
184 barcode_.emplace_back(pivotColumnNumber, i, dim - 1);
185 } else {
186 curr.clear();
187 barcode_.emplace_back(i, nullDeath, dim);
188 }
189 }
190 }
191 --dim;
192 }
193
194 if constexpr (Master_matrix::Option_list::has_removable_columns) {
195 // sort barcode by birth such that a removal is trivial
196 std::sort(barcode_.begin(), barcode_.end(), [](const Bar& b1, const Bar& b2) { return b1.birth < b2.birth; });
197 // map can only be constructed once barcode is sorted
198 for (Index i = 0; i < barcode_.size(); ++i) {
199 auto d = barcode_[i].death;
200 if (d != Master_matrix::template get_null_value<Pos_index>()) {
201 deathToBar_.emplace(d, i);
202 }
203 }
204 }
205
206 isReduced_ = true;
207}
208
209template <class Master_matrix>
210inline void Base_pairing<Master_matrix>::_remove_last(Pos_index columnIndex)
211{
212 static_assert(Master_matrix::Option_list::has_removable_columns, "remove_last not available.");
213
214 if (isReduced_) {
215 auto it = deathToBar_.find(columnIndex);
216
217 if (it == deathToBar_.end()) { // birth
218 barcode_.pop_back(); // sorted by birth and columnIndex has to be the highest one
219 } else { // death
220 barcode_[it->second].death = Master_matrix::template get_null_value<Pos_index>();
221 deathToBar_.erase(it);
222 };
223 }
224
225 auto it = PIDM::map_.find(columnIndex);
226 if (it != PIDM::map_.end()){
227 idToPosition_.erase(it->second);
228 PIDM::map_.erase(it);
229 }
230}
231
232} // namespace persistence_matrix
233} // namespace Gudhi
234
235#endif // PM_BASE_PAIRING_H
Contains the Gudhi::persistence_matrix::Cell_position_to_ID_mapper class and Gudhi::persistence_matri...
A basic matrix structure allowing to easily manipulate and access entire columns and rows,...
Definition: Base_matrix.h:39
Class managing the barcode for Boundary_matrix if the option was enabled.
Definition: base_pairing.h:56
typename Master_matrix::Bar Bar
Definition: base_pairing.h:58
typename Master_matrix::Dimension Dimension
Definition: base_pairing.h:62
friend void swap(Base_pairing &pairing1, Base_pairing &pairing2)
Swap operator.
Definition: base_pairing.h:83
typename Master_matrix::Barcode Barcode
Definition: base_pairing.h:59
Base_pairing()
Default constructor.
Definition: base_pairing.h:122
typename Master_matrix::Index Index
Definition: base_pairing.h:61
const Barcode & get_current_barcode()
Reduces the matrix stored in Boundary_matrix and computes the corresponding barcode.
Definition: base_pairing.h:126
typename Master_matrix::Column_container Column_container
Definition: base_pairing.h:60
Data structure for matrices, and in particular thought for matrices representing filtered complexes i...
Definition: Matrix.h:144
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
Empty structure. Inherited instead of Base_pairing, when the computation of the barcode was not enabl...
Definition: base_pairing.h:38