19#ifndef PM_RU_VINE_SWAP_H
20#define PM_RU_VINE_SWAP_H
31namespace persistence_matrix {
63template <
class Master_matrix>
64class RU_vine_swap :
public std::conditional<Master_matrix::Option_list::has_column_pairings,
65 RU_pairing<Master_matrix>,
68 public std::conditional<Master_matrix::Option_list::has_column_pairings &&
69 Master_matrix::Option_list::has_removable_columns,
71 Cell_position_to_ID_mapper<typename Master_matrix::ID_index,
72 typename Master_matrix::Pos_index>
76 using Index =
typename Master_matrix::Index;
77 using ID_index =
typename Master_matrix::ID_index;
78 using Pos_index =
typename Master_matrix::Pos_index;
128 if constexpr (Master_matrix::Option_list::has_column_pairings) {
131 if (!Master_matrix::Option_list::has_column_pairings || !Master_matrix::Option_list::has_removable_columns) {
132 swap(
static_cast<Cell_position_to_ID_mapper<ID_index, Pos_index>&
>(swap1),
133 static_cast<Cell_position_to_ID_mapper<ID_index, Pos_index>&
>(swap2));
139 using RUP =
typename std::conditional<Master_matrix::Option_list::has_column_pairings,
144 using RUM =
typename std::conditional<Master_matrix::Option_list::has_column_pairings &&
145 Master_matrix::Option_list::has_removable_columns,
147 Cell_position_to_ID_mapper<ID_index, Pos_index>
149 constexpr auto& _positionToRowIdx();
152 using Master_RU_matrix =
typename Master_matrix::Master_RU_matrix;
154 bool _is_paired(Index columnIndex);
156 void _swap_at_index(Index columnIndex);
157 void _add_to(Index sourceIndex, Index targetIndex);
158 void _positive_transpose(Index columnIndex);
159 void _negative_transpose(Index columnIndex);
160 void _positive_negative_transpose(Index columnIndex);
161 void _negative_positive_transpose(Index columnIndex);
162 bool _positive_vine_swap(Index columnIndex);
163 bool _negative_vine_swap(Index columnIndex);
164 bool _positive_negative_vine_swap(Index columnIndex);
165 bool _negative_positive_vine_swap(Index columnIndex);
169 Pos_index _get_death(Index simplexIndex);
170 Pos_index _get_birth(Index simplexIndex);
174 constexpr Master_RU_matrix* _matrix() {
return static_cast<Master_RU_matrix*
>(
this); }
175 constexpr const Master_RU_matrix* _matrix()
const {
return static_cast<const Master_RU_matrix*
>(
this); }
178template <
class Master_matrix>
182template <
class Master_matrix>
184 : RUP(static_cast<const RUP&>(matrixToCopy)),
185 RUM(static_cast<const RUM&>(matrixToCopy))
188template <
class Master_matrix>
190 : RUP(std::move(
static_cast<RUP&
>(other))),
191 RUM(std::move(
static_cast<RUM&
>(other)))
194template <
class Master_matrix>
197 GUDHI_CHECK(index < _matrix()->reducedMatrixR_.get_number_of_columns() - 1,
198 std::invalid_argument(
"RU_vine_swap::vine_swap_with_z_eq_1_case - Index to swap out of bound."));
200 bool iIsPositive = _matrix()->reducedMatrixR_.is_zero_column(index);
201 bool iiIsPositive = _matrix()->reducedMatrixR_.is_zero_column(index + 1);
203 if (iIsPositive && iiIsPositive) {
204 _matrix()->mirrorMatrixU_.zero_entry(index, _get_row_id_from_position(index + 1));
205 return _positive_vine_swap(index);
206 }
else if (!iIsPositive && !iiIsPositive) {
207 return _negative_vine_swap(index);
208 }
else if (iIsPositive && !iiIsPositive) {
209 return _positive_negative_vine_swap(index);
211 return _negative_positive_vine_swap(index);
215template <
class Master_matrix>
218 GUDHI_CHECK(index < _matrix()->reducedMatrixR_.get_number_of_columns() - 1,
219 std::invalid_argument(
"RU_vine_swap::vine_swap - Index to swap out of bound."));
221 bool iIsPositive = _matrix()->reducedMatrixR_.is_zero_column(index);
222 bool iiIsPositive = _matrix()->reducedMatrixR_.is_zero_column(index + 1);
224 if (iIsPositive && iiIsPositive) {
225 if (_matrix()->reducedMatrixR_.get_column_dimension(index) !=
226 _matrix()->reducedMatrixR_.get_column_dimension(index + 1)) {
227 _positive_transpose(index);
228 _swap_at_index(index);
231 if (!_matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) {
232 _matrix()->mirrorMatrixU_.zero_entry(index, _get_row_id_from_position(index + 1));
234 return _positive_vine_swap(index);
235 }
else if (!iIsPositive && !iiIsPositive) {
236 if (_matrix()->reducedMatrixR_.get_column_dimension(index) !=
237 _matrix()->reducedMatrixR_.get_column_dimension(index + 1) ||
238 _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) {
239 _negative_transpose(index);
240 _swap_at_index(index);
243 return _negative_vine_swap(index);
244 }
else if (iIsPositive && !iiIsPositive) {
245 if (_matrix()->reducedMatrixR_.get_column_dimension(index) !=
246 _matrix()->reducedMatrixR_.get_column_dimension(index + 1) ||
247 _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) {
248 _positive_negative_transpose(index);
249 _swap_at_index(index);
252 return _positive_negative_vine_swap(index);
254 if (_matrix()->reducedMatrixR_.get_column_dimension(index) !=
255 _matrix()->reducedMatrixR_.get_column_dimension(index + 1) ||
256 _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) {
257 _negative_positive_transpose(index);
258 _swap_at_index(index);
261 return _negative_positive_vine_swap(index);
265template <
class Master_matrix>
268 RUP::operator=(other);
269 RUM::operator=(other);
273template <
class Master_matrix>
276 if constexpr (Master_matrix::Option_list::has_column_pairings) {
277 return _get_death(columnIndex) != Master_matrix::template get_null_value<Pos_index>();
279 if (!_matrix()->reducedMatrixR_.is_zero_column(columnIndex))
return true;
281 if constexpr (Master_matrix::Option_list::has_map_column_container) {
282 if (_matrix()->pivotToColumnIndex_.find(columnIndex) == _matrix()->pivotToColumnIndex_.end())
return false;
284 if (_matrix()->pivotToColumnIndex_[columnIndex] == Master_matrix::template get_null_value<Index>())
292template <
class Master_matrix>
293inline void RU_vine_swap<Master_matrix>::_swap_at_index(Index columnIndex)
295 _matrix()->reducedMatrixR_.swap_columns(columnIndex, columnIndex + 1);
296 _matrix()->reducedMatrixR_.swap_rows(_get_row_id_from_position(columnIndex),
297 _get_row_id_from_position(columnIndex + 1));
298 _matrix()->mirrorMatrixU_.swap_columns(columnIndex, columnIndex + 1);
299 _matrix()->mirrorMatrixU_.swap_rows(_get_row_id_from_position(columnIndex),
300 _get_row_id_from_position(columnIndex + 1));
303template <
class Master_matrix>
304inline void RU_vine_swap<Master_matrix>::_add_to(Index sourceIndex, Index targetIndex)
306 _matrix()->reducedMatrixR_.add_to(sourceIndex, targetIndex);
307 _matrix()->mirrorMatrixU_.add_to(targetIndex, sourceIndex);
310template <
class Master_matrix>
311inline void RU_vine_swap<Master_matrix>::_positive_transpose(Index columnIndex)
313 if constexpr (Master_matrix::Option_list::has_map_column_container) {
314 if (_is_paired(columnIndex) && _is_paired(columnIndex + 1)) {
315 std::swap(_matrix()->pivotToColumnIndex_.at(columnIndex), _matrix()->pivotToColumnIndex_.at(columnIndex + 1));
316 }
else if (_is_paired(columnIndex)) {
317 _matrix()->pivotToColumnIndex_.emplace(columnIndex + 1, _matrix()->pivotToColumnIndex_.at(columnIndex));
318 _matrix()->pivotToColumnIndex_.erase(columnIndex);
319 }
else if (_is_paired(columnIndex + 1)) {
320 _matrix()->pivotToColumnIndex_.emplace(columnIndex, _matrix()->pivotToColumnIndex_.at(columnIndex + 1));
321 _matrix()->pivotToColumnIndex_.erase(columnIndex + 1);
324 std::swap(_matrix()->pivotToColumnIndex_[columnIndex],
325 _matrix()->pivotToColumnIndex_[columnIndex + 1]);
328 if constexpr (Master_matrix::Option_list::has_column_pairings) {
329 _birth(columnIndex) = columnIndex + 1;
330 _birth(columnIndex + 1) = columnIndex;
331 std::swap(RUP::indexToBar_.at(columnIndex), RUP::indexToBar_.at(columnIndex + 1));
335template <
class Master_matrix>
336inline void RU_vine_swap<Master_matrix>::_negative_transpose(Index columnIndex)
338 if constexpr (Master_matrix::Option_list::has_column_pairings) {
339 _death(columnIndex) = columnIndex + 1;
340 _death(columnIndex + 1) = columnIndex;
341 std::swap(RUP::indexToBar_.at(columnIndex), RUP::indexToBar_.at(columnIndex + 1));
343 std::swap(_matrix()->pivotToColumnIndex_.at(_get_birth(columnIndex)),
344 _matrix()->pivotToColumnIndex_.at(_get_birth(columnIndex + 1)));
347template <
class Master_matrix>
348inline void RU_vine_swap<Master_matrix>::_positive_negative_transpose(Index columnIndex)
350 _matrix()->pivotToColumnIndex_.at(_get_birth(columnIndex + 1)) = columnIndex;
351 if constexpr (Master_matrix::Option_list::has_map_column_container) {
352 if (_is_paired(columnIndex)) {
353 _matrix()->pivotToColumnIndex_.emplace(columnIndex + 1, _matrix()->pivotToColumnIndex_.at(columnIndex));
354 _matrix()->pivotToColumnIndex_.erase(columnIndex);
357 _matrix()->pivotToColumnIndex_[columnIndex + 1] = _matrix()->pivotToColumnIndex_[columnIndex];
358 _matrix()->pivotToColumnIndex_[columnIndex] = Master_matrix::template get_null_value<Index>();
361 if constexpr (Master_matrix::Option_list::has_column_pairings) {
362 _birth(columnIndex) = columnIndex + 1;
363 _death(columnIndex + 1) = columnIndex;
364 std::swap(RUP::indexToBar_.at(columnIndex), RUP::indexToBar_.at(columnIndex + 1));
368template <
class Master_matrix>
369inline void RU_vine_swap<Master_matrix>::_negative_positive_transpose(Index columnIndex)
371 _matrix()->pivotToColumnIndex_.at(_get_birth(columnIndex)) = columnIndex + 1;
372 if constexpr (Master_matrix::Option_list::has_map_column_container) {
373 if (_is_paired(columnIndex + 1)) {
374 _matrix()->pivotToColumnIndex_.emplace(columnIndex, _matrix()->pivotToColumnIndex_.at(columnIndex + 1));
375 _matrix()->pivotToColumnIndex_.erase(columnIndex + 1);
378 _matrix()->pivotToColumnIndex_[columnIndex] = _matrix()->pivotToColumnIndex_[columnIndex + 1];
379 _matrix()->pivotToColumnIndex_[columnIndex + 1] = Master_matrix::template get_null_value<Index>();
382 if constexpr (Master_matrix::Option_list::has_column_pairings) {
383 _death(columnIndex) = columnIndex + 1;
384 _birth(columnIndex + 1) = columnIndex;
385 std::swap(RUP::indexToBar_.at(columnIndex), RUP::indexToBar_.at(columnIndex + 1));
389template <
class Master_matrix>
390inline bool RU_vine_swap<Master_matrix>::_positive_vine_swap(Index columnIndex)
392 const Pos_index iDeath = _get_death(columnIndex);
393 const Pos_index iiDeath = _get_death(columnIndex + 1);
395 if (iDeath != Master_matrix::template get_null_value<Pos_index>() &&
396 iiDeath != Master_matrix::template get_null_value<Pos_index>() &&
397 !(_matrix()->reducedMatrixR_.is_zero_entry(iiDeath, _get_row_id_from_position(columnIndex)))) {
398 if (iDeath < iiDeath) {
399 _swap_at_index(columnIndex);
400 _add_to(iDeath, iiDeath);
401 _positive_transpose(columnIndex);
405 _swap_at_index(columnIndex);
406 _add_to(iiDeath, iDeath);
410 _swap_at_index(columnIndex);
412 if (iDeath != Master_matrix::template get_null_value<Pos_index>() ||
413 iiDeath == Master_matrix::template get_null_value<Pos_index>() ||
414 _matrix()->reducedMatrixR_.is_zero_entry(iiDeath, _get_row_id_from_position(columnIndex + 1))) {
415 _positive_transpose(columnIndex);
421template <
class Master_matrix>
422inline bool RU_vine_swap<Master_matrix>::_negative_vine_swap(Index columnIndex)
424 const Pos_index iBirth = _get_birth(columnIndex);
425 const Pos_index iiBirth = _get_birth(columnIndex + 1);
427 _add_to(columnIndex, columnIndex + 1);
428 _swap_at_index(columnIndex);
430 if (iBirth < iiBirth) {
431 _negative_transpose(columnIndex);
435 _add_to(columnIndex, columnIndex + 1);
440template <
class Master_matrix>
441inline bool RU_vine_swap<Master_matrix>::_positive_negative_vine_swap(Index columnIndex)
443 _matrix()->mirrorMatrixU_.zero_entry(columnIndex, _get_row_id_from_position(columnIndex + 1));
445 _swap_at_index(columnIndex);
446 _positive_negative_transpose(columnIndex);
451template <
class Master_matrix>
452inline bool RU_vine_swap<Master_matrix>::_negative_positive_vine_swap(Index columnIndex)
454 _add_to(columnIndex, columnIndex + 1);
455 _swap_at_index(columnIndex);
456 _add_to(columnIndex, columnIndex + 1);
461template <
class Master_matrix>
464 static_assert(Master_matrix::Option_list::has_column_pairings,
"Pairing necessary to modify death value.");
466 if constexpr (Master_matrix::Option_list::has_removable_columns) {
467 return RUP::indexToBar_.at(simplexIndex)->death;
469 return RUP::barcode_.at(RUP::indexToBar_.at(simplexIndex)).death;
473template <
class Master_matrix>
476 static_assert(Master_matrix::Option_list::has_column_pairings,
"Pairing necessary to modify birth value.");
478 if constexpr (Master_matrix::Option_list::has_removable_columns) {
479 return RUP::indexToBar_.at(simplexIndex)->birth;
481 return RUP::barcode_.at(RUP::indexToBar_.at(simplexIndex)).birth;
485template <
class Master_matrix>
488 if constexpr (Master_matrix::Option_list::has_column_pairings) {
489 if constexpr (Master_matrix::Option_list::has_removable_columns) {
490 return RUP::indexToBar_.at(simplexIndex)->death;
492 return RUP::barcode_.at(RUP::indexToBar_.at(simplexIndex)).death;
495 if (!_matrix()->reducedMatrixR_.is_zero_column(simplexIndex))
496 return _matrix()->reducedMatrixR_.get_column(simplexIndex).get_pivot();
498 if constexpr (Master_matrix::Option_list::has_map_column_container) {
499 auto it = _matrix()->pivotToColumnIndex_.find(simplexIndex);
500 if (it == _matrix()->pivotToColumnIndex_.end())
return Master_matrix::template get_null_value<Pos_index>();
503 return _matrix()->pivotToColumnIndex_[simplexIndex];
508template <
class Master_matrix>
510 Index negativeSimplexIndex)
512 if constexpr (Master_matrix::Option_list::has_column_pairings) {
513 if constexpr (Master_matrix::Option_list::has_removable_columns) {
514 return RUP::indexToBar_.at(negativeSimplexIndex)->birth;
516 return RUP::barcode_.at(RUP::indexToBar_.at(negativeSimplexIndex)).birth;
519 return _matrix()->reducedMatrixR_.get_pivot(negativeSimplexIndex);
523template <
class Master_matrix>
527 auto it = _positionToRowIdx().find(position);
528 return it == _positionToRowIdx().end() ? position : it->second;
531template <
class Master_matrix>
532inline constexpr auto& RU_vine_swap<Master_matrix>::_positionToRowIdx()
534 if constexpr (Master_matrix::Option_list::has_column_pairings && Master_matrix::Option_list::has_removable_columns)
535 return RUP::PIDM::map_;
Contains the Gudhi::persistence_matrix::Cell_position_to_ID_mapper class and Gudhi::persistence_matri...
Class managing the barcode for RU_matrix if the option was enabled.
Definition: ru_pairing.h:54
Class managing the vine swaps for RU_matrix.
Definition: ru_vine_swap.h:74
friend void swap(RU_vine_swap &swap1, RU_vine_swap &swap2)
Swap operator.
Definition: ru_vine_swap.h:127
RU_vine_swap & operator=(RU_vine_swap other)
Assign operator.
Definition: ru_vine_swap.h:266
typename Master_matrix::ID_index ID_index
Definition: ru_vine_swap.h:77
RU_vine_swap()
Default constructor.
Definition: ru_vine_swap.h:179
typename Master_matrix::Index Index
Definition: ru_vine_swap.h:76
bool vine_swap_with_z_eq_1_case(Pos_index index)
Does the same than vine_swap, but assumes that the swap is non trivial and therefore skips a part of ...
Definition: ru_vine_swap.h:195
typename Master_matrix::Pos_index Pos_index
Definition: ru_vine_swap.h:78
bool vine_swap(Pos_index index)
Does a vine swap between two cells which are consecutive in the filtration. Roughly,...
Definition: ru_vine_swap.h:216
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14
Contains the Gudhi::persistence_matrix::RU_pairing class and Gudhi::persistence_matrix::Dummy_ru_pair...
Empty structure. Inherited instead of RU_pairing, when the barcode is not stored.
Definition: ru_vine_swap.h:51
Empty structure. Inherited instead of RU_vine_swap, when vine swaps are not enabled.
Definition: ru_vine_swap.h:40