20#ifndef PM_CHAIN_VINE_SWAP_H
21#define PM_CHAIN_VINE_SWAP_H
44 [[maybe_unused]]
unsigned int columnIndex2)
55struct Dummy_chain_vine_swap {
58 friend void swap([[maybe_unused]] Dummy_chain_vine_swap& d1, [[maybe_unused]] Dummy_chain_vine_swap& d2)
noexcept {}
60 Dummy_chain_vine_swap() =
default;
62 template <
typename BirthComparatorFunction,
typename DeathComparatorFunction>
63 Dummy_chain_vine_swap([[maybe_unused]]
const BirthComparatorFunction& birthComparator,
64 [[maybe_unused]]
const DeathComparatorFunction& deathComparator)
87template <
typename Master_matrix>
91 using ID_index =
typename Master_matrix::ID_index;
92 using Pos_index =
typename Master_matrix::Pos_index;
117 CP::operator=(other);
123 CP::operator=(std::move(other));
129 swap(
static_cast<CP&
>(swap1),
static_cast<CP&
>(swap2));
133 bool _is_negative_in_bar(
ID_index pivot)
const
135 Pos_index pos = _get_pivot_position(pivot);
136 return _death_val(pivot) == pos;
141 Pos_index pos1 = _get_pivot_position(pivot1);
142 Pos_index pos2 = _get_pivot_position(pivot2);
146 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
151 Pos_index pos1 = _get_pivot_position(pivot1);
152 Pos_index pos2 = _get_pivot_position(pivot2);
156 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
161 Pos_index pos1 = _get_pivot_position(pivot1);
162 Pos_index pos2 = _get_pivot_position(pivot2);
166 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
171 Pos_index pos1 = _get_pivot_position(pivot1);
172 Pos_index pos2 = _get_pivot_position(pivot2);
176 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
181 Pos_index pos1 = _get_pivot_position(pivot1);
182 Pos_index pos2 = _get_pivot_position(pivot2);
183 return pos1 < pos2 ? (pos2 - pos1) == 1 : (pos1 - pos2) == 1;
186 Pos_index _death_val(
ID_index pivot)
const {
return CP::_death(_get_pivot_position(pivot)); }
188 Pos_index _birth_val(
ID_index pivot)
const {
return CP::_birth(_get_pivot_position(pivot)); }
190 void _reset() { CP::_reset(); }
193 using Master_chain_matrix =
typename Master_matrix::Master_chain_matrix;
197 const auto& map =
static_cast<const Master_chain_matrix*
>(
this)->map_;
198 if constexpr (Master_matrix::Option_list::has_map_column_container) {
200 return map.at(pivot);
208 if constexpr (Master_matrix::Option_list::has_removable_columns) {
209 return CP::indexToBar_.at(index)->death;
211 return CP::barcode_.at(CP::indexToBar_.at(index)).death;
217 if constexpr (Master_matrix::Option_list::has_removable_columns) {
218 return CP::indexToBar_.at(index)->birth;
220 return CP::barcode_.at(CP::indexToBar_.at(index)).birth;
233template <
class Master_matrix>
237 using Index =
typename Master_matrix::Index;
241 using Column =
typename Master_matrix::Column;
296 std::swap(swap1.birthComp_, swap2.birthComp_);
297 std::swap(swap1.deathComp_, swap2.deathComp_);
301 using Master_chain_matrix =
typename Master_matrix::Master_chain_matrix;
306 bool _is_negative_in_pair(Index columnIndex);
307 Index _positive_vine_swap(Index columnIndex1, Index columnIndex2);
308 Index _positive_negative_vine_swap(Index columnIndex1, Index columnIndex2);
309 Index _negative_positive_vine_swap(Index columnIndex1, Index columnIndex2);
310 Index _negative_vine_swap(Index columnIndex1, Index columnIndex2);
313 constexpr Master_chain_matrix* _matrix() {
return static_cast<Master_chain_matrix*
>(
this); }
315 constexpr const Master_chain_matrix* _matrix()
const {
return static_cast<const Master_chain_matrix*
>(
this); }
318template <
class Master_matrix>
321 static_assert(Master_matrix::Option_list::has_column_pairings,
322 "If barcode is not stored, at least a birth comparator has to be specified.");
325template <
class Master_matrix>
328 : birthComp_(
std::move(birthComparator)), deathComp_(
std::move(deathComparator))
331template <
class Master_matrix>
336 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
337 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
339 if (col1IsNeg && col2IsNeg)
return _negative_vine_swap(columnIndex1, columnIndex2);
341 if (col1IsNeg)
return _negative_positive_vine_swap(columnIndex1, columnIndex2);
343 if (col2IsNeg)
return _positive_negative_vine_swap(columnIndex1, columnIndex2);
345 return _positive_vine_swap(columnIndex1, columnIndex2);
348template <
class Master_matrix>
352 if constexpr (Master_matrix::Option_list::has_column_pairings) {
353 GUDHI_CHECK(_matrix()->_are_adjacent(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2)),
354 std::invalid_argument(
355 "Chain_vine_swap::vine_swap - Columns to be swapped need to be adjacent in the 'real' matrix."));
358 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
359 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
361 if (col1IsNeg && col2IsNeg) {
362 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
363 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
364 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
365 if constexpr (Master_matrix::Option_list::has_column_pairings) {
366 _matrix()->_negative_transpose_barcode(pivot1, pivot2);
368 _swap_positions(pivot1, pivot2);
371 return _negative_vine_swap(columnIndex1, columnIndex2);
375 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
376 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
377 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
378 if constexpr (Master_matrix::Option_list::has_column_pairings) {
379 _matrix()->_negative_positive_transpose_barcode(pivot1, pivot2);
381 _swap_positions(pivot1, pivot2);
384 return _negative_positive_vine_swap(columnIndex1, columnIndex2);
388 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
389 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
390 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
391 if constexpr (Master_matrix::Option_list::has_column_pairings) {
392 _matrix()->_positive_negative_transpose_barcode(pivot1, pivot2);
394 _swap_positions(pivot1, pivot2);
397 return _positive_negative_vine_swap(columnIndex1, columnIndex2);
400 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
401 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
402 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
403 if constexpr (Master_matrix::Option_list::has_column_pairings) {
404 _matrix()->_positive_transpose_barcode(pivot1, pivot2);
406 _swap_positions(pivot1, pivot2);
409 return _positive_vine_swap(columnIndex1, columnIndex2);
412template <
class Master_matrix>
413inline bool Chain_vine_swap<Master_matrix>::_is_negative_in_pair(Index columnIndex)
415 if constexpr (Master_matrix::Option_list::has_column_pairings) {
416 return _matrix()->_is_negative_in_bar(_matrix()->get_pivot(columnIndex));
418 auto& col = _matrix()->get_column(columnIndex);
419 if (!col.is_paired())
return false;
420 return col.get_pivot() > _matrix()->get_pivot(col.get_paired_chain_index());
424template <
class Master_matrix>
429 auto& col1 = _matrix()->get_column(columnIndex1);
430 auto& col2 = _matrix()->get_column(columnIndex2);
432 _swap_positions(col1.get_pivot(), col2.get_pivot());
435 if (!col1.is_paired()) {
436 bool hasSmallerBirth;
437 if constexpr (Master_matrix::Option_list::has_column_pairings) {
439 hasSmallerBirth = (_matrix()->_birth_val(col2.get_pivot()) < _matrix()->_birth_val(col1.get_pivot()));
441 hasSmallerBirth = birthComp_(columnIndex1, columnIndex2);
444 if (!col2.is_paired() && hasSmallerBirth) {
445 _matrix()->add_to(columnIndex1, columnIndex2);
446 if constexpr (Master_matrix::Option_list::has_column_pairings) {
447 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
451 _matrix()->add_to(columnIndex2, columnIndex1);
456 if (!col2.is_paired()) {
457 static_cast<Master_chain_matrix*
>(
this)->add_to(columnIndex1, columnIndex2);
458 if constexpr (Master_matrix::Option_list::has_column_pairings) {
459 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
464 bool hasSmallerDeath;
465 if constexpr (Master_matrix::Option_list::has_column_pairings) {
467 hasSmallerDeath = (_matrix()->_death_val(col2.get_pivot()) < _matrix()->_death_val(col1.get_pivot()));
469 hasSmallerDeath = deathComp_(columnIndex1, columnIndex2);
473 if (hasSmallerDeath) {
474 _matrix()->add_to(col1.get_paired_chain_index(), col2.get_paired_chain_index());
475 _matrix()->add_to(columnIndex1, columnIndex2);
476 if constexpr (Master_matrix::Option_list::has_column_pairings) {
477 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
482 _matrix()->add_to(col2.get_paired_chain_index(), col1.get_paired_chain_index());
483 _matrix()->add_to(columnIndex2, columnIndex1);
488template <
class Master_matrix>
493 _matrix()->add_to(columnIndex1, columnIndex2);
495 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
496 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
497 if constexpr (Master_matrix::Option_list::has_column_pairings) {
498 _matrix()->_positive_negative_transpose_barcode(pivot1, pivot2);
500 _swap_positions(pivot1, pivot2);
505template <
class Master_matrix>
510 _matrix()->add_to(columnIndex2, columnIndex1);
512 _swap_positions(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2));
517template <
class Master_matrix>
522 auto& col1 = _matrix()->get_column(columnIndex1);
523 auto& col2 = _matrix()->get_column(columnIndex2);
525 Index pairedIndex1 = col1.get_paired_chain_index();
526 Index pairedIndex2 = col2.get_paired_chain_index();
528 bool hasSmallerBirth;
529 if constexpr (Master_matrix::Option_list::has_column_pairings) {
530 hasSmallerBirth = (_matrix()->_birth_val(col1.get_pivot()) < _matrix()->_birth_val(col2.get_pivot()));
532 hasSmallerBirth = birthComp_(pairedIndex1, pairedIndex2);
535 _swap_positions(col1.get_pivot(), col2.get_pivot());
537 if (hasSmallerBirth) {
538 _matrix()->add_to(pairedIndex1, pairedIndex2);
539 _matrix()->add_to(columnIndex1, columnIndex2);
541 if constexpr (Master_matrix::Option_list::has_column_pairings) {
542 _matrix()->_negative_transpose_barcode(col1.get_pivot(), col2.get_pivot());
548 _matrix()->add_to(pairedIndex2, pairedIndex1);
549 _matrix()->add_to(columnIndex2, columnIndex1);
554template <
class Master_matrix>
555inline void Chain_vine_swap<Master_matrix>::_swap_positions(ID_index pivot1, ID_index pivot2)
557 if constexpr (Master_matrix::Option_list::has_column_pairings ||
558 Master_matrix::Option_list::can_retrieve_representative_cycles) {
559 auto& map = _matrix()->map_;
560 if constexpr (Master_matrix::Option_list::has_map_column_container) {
561 std::swap(map.at(pivot1), map.at(pivot2));
563 std::swap(map[pivot1], map[pivot2]);
Contains the Gudhi::persistence_matrix::Chain_pairing class and Gudhi::persistence_matrix::Dummy_chai...
Class managing the barcode for Chain_vine_swap.
Definition chain_vine_swap.h:89
typename Master_matrix::Pos_index Pos_index
Definition chain_vine_swap.h:92
Chain_barcode_swap()=default
Default constructor.
Chain_barcode_swap(Chain_barcode_swap &&other) noexcept
Move constructor.
Definition chain_vine_swap.h:111
Chain_barcode_swap(const Chain_barcode_swap &toCopy)
Copy constructor.
Definition chain_vine_swap.h:105
typename Master_matrix::ID_index ID_index
Definition chain_vine_swap.h:91
Chain_pairing()=default
Default constructor.
Chain_vine_swap()
Default constructor. Only available if PersistenceMatrixOptions::has_column_pairings is true.
Definition chain_vine_swap.h:319
typename Master_matrix::Pos_index Pos_index
Definition chain_vine_swap.h:239
typename Master_matrix::Column_container Column_container
Definition chain_vine_swap.h:240
friend void swap(Chain_vine_swap &swap1, Chain_vine_swap &swap2) noexcept
Swap operator.
Definition chain_vine_swap.h:294
Index vine_swap(Index columnIndex1, Index columnIndex2)
Does a vine swap between two cells which are consecutive in the filtration. Roughly,...
Definition chain_vine_swap.h:349
typename Master_matrix::Index Index
Definition chain_vine_swap.h:237
typename Master_matrix::ID_index ID_index
Definition chain_vine_swap.h:238
typename Master_matrix::Column Column
Definition chain_vine_swap.h:241
bool(*)(Pos_index, Pos_index) EventCompFuncPointer
Definition chain_vine_swap.h:242
Index vine_swap_with_z_eq_1_case(Index columnIndex1, Index columnIndex2)
Does the same than vine_swap, but assumes that the swap is non trivial and therefore skips a part of ...
Definition chain_vine_swap.h:332
constexpr bool _no_G_death_comparator(unsigned int columnIndex1, unsigned int columnIndex2)
Default death comparator. Simply assumes that two positive paired columns are never swapped....
Definition chain_vine_swap.h:43
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14
Empty structure. Inherited instead of Chain_barcode_swap, when the barcode is not stored.
Definition chain_vine_swap.h:74