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;
295 std::swap(swap1.birthComp_, swap2.birthComp_);
296 std::swap(swap1.deathComp_, swap2.deathComp_);
300 using Master_chain_matrix =
typename Master_matrix::Master_chain_matrix;
305 bool _is_negative_in_pair(Index columnIndex);
306 Index _positive_vine_swap(Index columnIndex1, Index columnIndex2);
307 Index _positive_negative_vine_swap(Index columnIndex1, Index columnIndex2);
308 Index _negative_positive_vine_swap(Index columnIndex1, Index columnIndex2);
309 Index _negative_vine_swap(Index columnIndex1, Index columnIndex2);
312 constexpr Master_chain_matrix* _matrix() {
return static_cast<Master_chain_matrix*
>(
this); }
314 constexpr const Master_chain_matrix* _matrix()
const {
return static_cast<const Master_chain_matrix*
>(
this); }
317template <
class Master_matrix>
320 static_assert(Master_matrix::Option_list::has_column_pairings,
321 "If barcode is not stored, at least a birth comparator has to be specified.");
324template <
class Master_matrix>
327 : birthComp_(
std::move(birthComparator)), deathComp_(
std::move(deathComparator))
330template <
class Master_matrix>
335 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
336 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
338 if (col1IsNeg && col2IsNeg)
return _negative_vine_swap(columnIndex1, columnIndex2);
340 if (col1IsNeg)
return _negative_positive_vine_swap(columnIndex1, columnIndex2);
342 if (col2IsNeg)
return _positive_negative_vine_swap(columnIndex1, columnIndex2);
344 return _positive_vine_swap(columnIndex1, columnIndex2);
347template <
class Master_matrix>
351 if constexpr (Master_matrix::Option_list::has_column_pairings) {
352 GUDHI_CHECK(_matrix()->_are_adjacent(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2)),
353 std::invalid_argument(
354 "Chain_vine_swap::vine_swap - Columns to be swapped need to be adjacent in the 'real' matrix."));
357 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
358 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
360 if (col1IsNeg && col2IsNeg) {
361 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
362 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
363 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
364 if constexpr (Master_matrix::Option_list::has_column_pairings) {
365 _matrix()->_negative_transpose_barcode(pivot1, pivot2);
367 _swap_positions(pivot1, pivot2);
370 return _negative_vine_swap(columnIndex1, columnIndex2);
374 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
375 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
376 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
377 if constexpr (Master_matrix::Option_list::has_column_pairings) {
378 _matrix()->_negative_positive_transpose_barcode(pivot1, pivot2);
380 _swap_positions(pivot1, pivot2);
383 return _negative_positive_vine_swap(columnIndex1, columnIndex2);
387 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
388 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
389 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
390 if constexpr (Master_matrix::Option_list::has_column_pairings) {
391 _matrix()->_positive_negative_transpose_barcode(pivot1, pivot2);
393 _swap_positions(pivot1, pivot2);
396 return _positive_negative_vine_swap(columnIndex1, columnIndex2);
399 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
400 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
401 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
402 if constexpr (Master_matrix::Option_list::has_column_pairings) {
403 _matrix()->_positive_transpose_barcode(pivot1, pivot2);
405 _swap_positions(pivot1, pivot2);
408 return _positive_vine_swap(columnIndex1, columnIndex2);
411template <
class Master_matrix>
412inline bool Chain_vine_swap<Master_matrix>::_is_negative_in_pair(Index columnIndex)
414 if constexpr (Master_matrix::Option_list::has_column_pairings) {
415 return _matrix()->_is_negative_in_bar(_matrix()->get_pivot(columnIndex));
417 auto& col = _matrix()->get_column(columnIndex);
418 if (!col.is_paired())
return false;
419 return col.get_pivot() > _matrix()->get_pivot(col.get_paired_chain_index());
423template <
class Master_matrix>
428 auto& col1 = _matrix()->get_column(columnIndex1);
429 auto& col2 = _matrix()->get_column(columnIndex2);
431 _swap_positions(col1.get_pivot(), col2.get_pivot());
434 if (!col1.is_paired()) {
435 bool hasSmallerBirth;
436 if constexpr (Master_matrix::Option_list::has_column_pairings) {
438 hasSmallerBirth = (_matrix()->_birth_val(col2.get_pivot()) < _matrix()->_birth_val(col1.get_pivot()));
440 hasSmallerBirth = birthComp_(columnIndex1, columnIndex2);
443 if (!col2.is_paired() && hasSmallerBirth) {
444 _matrix()->add_to(columnIndex1, columnIndex2);
445 if constexpr (Master_matrix::Option_list::has_column_pairings) {
446 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
450 _matrix()->add_to(columnIndex2, columnIndex1);
455 if (!col2.is_paired()) {
456 static_cast<Master_chain_matrix*
>(
this)->add_to(columnIndex1, columnIndex2);
457 if constexpr (Master_matrix::Option_list::has_column_pairings) {
458 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
463 bool hasSmallerDeath;
464 if constexpr (Master_matrix::Option_list::has_column_pairings) {
466 hasSmallerDeath = (_matrix()->_death_val(col2.get_pivot()) < _matrix()->_death_val(col1.get_pivot()));
468 hasSmallerDeath = deathComp_(columnIndex1, columnIndex2);
472 if (hasSmallerDeath) {
473 _matrix()->add_to(col1.get_paired_chain_index(), col2.get_paired_chain_index());
474 _matrix()->add_to(columnIndex1, columnIndex2);
475 if constexpr (Master_matrix::Option_list::has_column_pairings) {
476 _matrix()->_positive_transpose_barcode(col1.get_pivot(), col2.get_pivot());
481 _matrix()->add_to(col2.get_paired_chain_index(), col1.get_paired_chain_index());
482 _matrix()->add_to(columnIndex2, columnIndex1);
487template <
class Master_matrix>
492 _matrix()->add_to(columnIndex1, columnIndex2);
494 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
495 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
496 if constexpr (Master_matrix::Option_list::has_column_pairings) {
497 _matrix()->_positive_negative_transpose_barcode(pivot1, pivot2);
499 _swap_positions(pivot1, pivot2);
504template <
class Master_matrix>
509 _matrix()->add_to(columnIndex2, columnIndex1);
511 _swap_positions(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2));
516template <
class Master_matrix>
521 auto& col1 = _matrix()->get_column(columnIndex1);
522 auto& col2 = _matrix()->get_column(columnIndex2);
524 Index pairedIndex1 = col1.get_paired_chain_index();
525 Index pairedIndex2 = col2.get_paired_chain_index();
527 bool hasSmallerBirth;
528 if constexpr (Master_matrix::Option_list::has_column_pairings) {
529 hasSmallerBirth = (_matrix()->_birth_val(col1.get_pivot()) < _matrix()->_birth_val(col2.get_pivot()));
531 hasSmallerBirth = birthComp_(pairedIndex1, pairedIndex2);
534 _swap_positions(col1.get_pivot(), col2.get_pivot());
536 if (hasSmallerBirth) {
537 _matrix()->add_to(pairedIndex1, pairedIndex2);
538 _matrix()->add_to(columnIndex1, columnIndex2);
540 if constexpr (Master_matrix::Option_list::has_column_pairings) {
541 _matrix()->_negative_transpose_barcode(col1.get_pivot(), col2.get_pivot());
547 _matrix()->add_to(pairedIndex2, pairedIndex1);
548 _matrix()->add_to(columnIndex2, columnIndex1);
553template <
class Master_matrix>
554inline void Chain_vine_swap<Master_matrix>::_swap_positions(ID_index pivot1, ID_index pivot2)
556 if constexpr (Master_matrix::Option_list::has_column_pairings ||
557 Master_matrix::Option_list::can_retrieve_representative_cycles) {
558 auto& map = _matrix()->map_;
559 if constexpr (Master_matrix::Option_list::has_map_column_container) {
560 std::swap(map.at(pivot1), map.at(pivot2));
562 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:318
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:293
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:348
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:331
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