Loading...
Searching...
No Matches
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 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
17
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) noexcept {}
40};
41
50template <class Master_matrix>
52 : protected std::conditional_t<
53 Master_matrix::Option_list::has_removable_columns,
54 Index_mapper<std::unordered_map<typename Master_matrix::Pos_index, typename Master_matrix::ID_index> >,
55 Dummy_index_mapper>
56{
57 protected:
58 using Pos_index = typename Master_matrix::Pos_index;
59 using ID_index = typename Master_matrix::ID_index;
60 // PIDM = Position to ID Map
61 using PIDM = std::conditional_t<Master_matrix::Option_list::has_removable_columns,
62 Index_mapper<std::unordered_map<Pos_index, ID_index> >,
63 Dummy_index_mapper>;
64
65 public:
66 using Bar = typename Master_matrix::Bar;
67 using Barcode = typename Master_matrix::Barcode;
68 using Column = typename Master_matrix::Column;
69 using Index = typename Master_matrix::Index;
70
75
86
90 friend void swap(Base_pairing& pairing1, Base_pairing& pairing2) noexcept
91 {
92 if constexpr (Master_matrix::Option_list::has_removable_columns) {
93 swap(static_cast<PIDM&>(pairing1), static_cast<PIDM&>(pairing2));
94 }
95 pairing1.barcode_.swap(pairing2.barcode_);
96 pairing1.deathToBar_.swap(pairing2.deathToBar_);
97 pairing1.idToPosition_.swap(pairing2.idToPosition_);
98 std::swap(pairing1.isReduced_, pairing2.isReduced_);
99 }
100
101 protected:
102 void _remove_last(Pos_index columnIndex);
103 void _insert_id_position(ID_index id, Pos_index pos);
104 void _reset();
105
106 private:
107 using Dictionary = typename Master_matrix::Bar_dictionary;
108 using Base_matrix = typename Master_matrix::Master_boundary_matrix;
109
110 Barcode barcode_;
111 Dictionary deathToBar_;
112 bool isReduced_;
116 std::unordered_map<ID_index, Pos_index> idToPosition_; // TODO: test other map types
117
118 void _reduce();
119 void _reduce_column_with(Column& toReduce, Column& toAdd);
120
121 // access to inheriting Boundary_matrix class
122 constexpr Base_matrix* _matrix() { return static_cast<Base_matrix*>(this); }
123
124 constexpr const Base_matrix* _matrix() const { return static_cast<const Base_matrix*>(this); }
125};
126
127template <class Master_matrix>
128inline Base_pairing<Master_matrix>::Base_pairing() : PIDM(), isReduced_(false)
129{}
130
131template <class Master_matrix>
133{
134 if (!isReduced_) _reduce();
135 return barcode_;
136}
137
138template <class Master_matrix>
139inline void Base_pairing<Master_matrix>::_reduce()
140{
141 constexpr const Pos_index nullDeath = Master_matrix::template get_null_value<Pos_index>();
142 constexpr const Index nullIndex = Master_matrix::template get_null_value<Index>();
143 constexpr const ID_index nullPivot = Master_matrix::template get_null_value<ID_index>();
144
145 std::unordered_map<Index, Index> negativeColumns(_matrix()->get_number_of_columns());
146
147 auto dim = _matrix()->get_max_dimension();
148 std::vector<std::vector<Index> > columnsByDim(dim + 1);
149 for (auto& v : columnsByDim) v.reserve(_matrix()->get_number_of_columns());
150 for (unsigned int i = 0; i < _matrix()->get_number_of_columns(); i++) {
151 columnsByDim[dim - _matrix()->get_column_dimension(i)].push_back(i);
152 }
153
154 for (const auto& cols : columnsByDim) {
155 for (Index i : cols) {
156 auto& curr = _matrix()->get_column(i);
157 if (curr.is_empty()) {
158 if (negativeColumns.find(i) == negativeColumns.end()) {
159 barcode_.emplace_back(i, nullDeath, dim);
160 }
161 } else {
162 ID_index pivot = curr.get_pivot();
163 auto it = idToPosition_.find(pivot);
164 Index pivotColumnNumber = it == idToPosition_.end() ? pivot : it->second;
165 auto itNeg = negativeColumns.find(pivotColumnNumber);
166 Index pivotKiller = itNeg == negativeColumns.end() ? nullIndex : itNeg->second;
167
168 while (pivot != nullPivot && pivotKiller != nullIndex) {
169 _reduce_column_with(curr, _matrix()->get_column(pivotKiller));
170 pivot = curr.get_pivot();
171 it = idToPosition_.find(pivot);
172 pivotColumnNumber = it == idToPosition_.end() ? pivot : it->second;
173 itNeg = negativeColumns.find(pivotColumnNumber);
174 pivotKiller = itNeg == negativeColumns.end() ? nullIndex : itNeg->second;
175 }
176
177 if (pivot != nullPivot) {
178 negativeColumns.emplace(pivotColumnNumber, i);
179 _matrix()->get_column(pivotColumnNumber).clear();
180 barcode_.emplace_back(pivotColumnNumber, i, dim - 1);
181 } else {
182 curr.clear();
183 barcode_.emplace_back(i, nullDeath, dim);
184 }
185 }
186 }
187 --dim;
188 }
189
190 if constexpr (Master_matrix::Option_list::has_removable_columns) {
191 // sort barcode by birth such that a removal is trivial
192 std::sort(barcode_.begin(), barcode_.end(), [](const Bar& b1, const Bar& b2) { return b1.birth < b2.birth; });
193 // map can only be constructed once barcode is sorted
194 for (Index i = 0; i < barcode_.size(); ++i) {
195 auto d = barcode_[i].death;
196 if (d != Master_matrix::template get_null_value<Pos_index>()) {
197 deathToBar_.emplace(d, i);
198 }
199 }
200 }
201
202 isReduced_ = true;
203}
204
205template <class Master_matrix>
206inline void Base_pairing<Master_matrix>::_reduce_column_with(Column& toReduce, Column& toAdd)
207{
208 if constexpr (Master_matrix::Option_list::is_z2) {
209 toReduce += toAdd;
210 } else {
211 typename Master_matrix::Element coeff = toAdd.get_pivot_value();
212 auto& operators = _matrix()->colSettings_->operators;
213 coeff = operators.get_inverse(coeff);
214 operators.multiply_inplace(coeff, operators.get_characteristic() - toReduce.get_pivot_value());
215 toReduce.multiply_source_and_add(toAdd, coeff);
216 }
217}
218
219template <class Master_matrix>
220inline void Base_pairing<Master_matrix>::_remove_last(Pos_index columnIndex)
221{
222 static_assert(Master_matrix::Option_list::has_removable_columns, "remove_last not available.");
223
224 if (isReduced_) {
225 auto it = deathToBar_.find(columnIndex);
226
227 if (it == deathToBar_.end()) { // birth
228 barcode_.pop_back(); // sorted by birth and columnIndex has to be the highest one
229 } else { // death
230 barcode_[it->second].death = Master_matrix::template get_null_value<Pos_index>();
231 deathToBar_.erase(it);
232 };
233 }
234
235 auto it = PIDM::map_.find(columnIndex);
236 if (it != PIDM::map_.end()) {
237 idToPosition_.erase(it->second);
238 PIDM::map_.erase(it);
239 }
240}
241
242template <class Master_matrix>
243inline void Base_pairing<Master_matrix>::_insert_id_position(ID_index id, Pos_index pos)
244{
245 idToPosition_.emplace(id, pos);
246}
247
248template <class Master_matrix>
249inline void Base_pairing<Master_matrix>::_reset()
250{
251 barcode_.clear();
252 deathToBar_.clear();
253 isReduced_ = false;
254 idToPosition_.clear();
255}
256
257} // namespace persistence_matrix
258} // namespace Gudhi
259
260#endif // PM_BASE_PAIRING_H
A basic matrix structure allowing to easily manipulate and access entire columns and rows,...
Definition Base_matrix.h:39
typename Master_matrix::Bar Bar
Definition base_pairing.h:66
typename Master_matrix::Column Column
Definition base_pairing.h:68
typename Master_matrix::Barcode Barcode
Definition base_pairing.h:67
friend void swap(Base_pairing &pairing1, Base_pairing &pairing2) noexcept
Swap operator.
Definition base_pairing.h:90
Base_pairing()
Default constructor.
Definition base_pairing.h:128
typename Master_matrix::Index Index
Definition base_pairing.h:69
const Barcode & get_current_barcode()
Reduces the matrix stored in Boundary_matrix and computes the corresponding barcode.
Definition base_pairing.h:132
Contains the Gudhi::persistence_matrix::Index_mapper class and Gudhi::persistence_matrix::Dummy_index...
Persistence matrix namespace.
Definition FieldOperators.h:18
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