20#ifndef PM_CHAIN_VINE_SWAP_H
21#define PM_CHAIN_VINE_SWAP_H
31namespace persistence_matrix {
44 [[maybe_unused]]
unsigned int columnIndex2)
60 template <
typename BirthComparatorFunction,
typename DeathComparatorFunction>
62 [[maybe_unused]]
const DeathComparatorFunction& deathComparator) {}
83template <
typename Master_matrix>
87 using ID_index =
typename Master_matrix::ID_index;
88 using Pos_index =
typename Master_matrix::Pos_index;
102 :
CP(static_cast<const
CP&>(toCopy)), pivotToPosition_(toCopy.pivotToPosition_){};
109 :
CP(
std::move(static_cast<
CP&>(other))), pivotToPosition_(
std::move(other.pivotToPosition_)){};
112 using Dictionary =
typename Master_matrix::template Dictionary<Pos_index>;
114 Dictionary pivotToPosition_;
117 if constexpr (Master_matrix::Option_list::has_map_column_container) {
118 std::swap(pivotToPosition_.at(pivot1), pivotToPosition_.at(pivot2));
120 std::swap(pivotToPosition_[pivot1], pivotToPosition_[pivot2]);
124 bool is_negative_in_pair(
ID_index pivot)
const {
125 Pos_index pos = _get_pivot_position(pivot);
126 return death(pivot) == pos;
130 Pos_index pos1 = _get_pivot_position(pivot1);
131 Pos_index pos2 = _get_pivot_position(pivot2);
135 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
139 Pos_index pos1 = _get_pivot_position(pivot1);
140 Pos_index pos2 = _get_pivot_position(pivot2);
144 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
148 Pos_index pos1 = _get_pivot_position(pivot1);
149 Pos_index pos2 = _get_pivot_position(pivot2);
153 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
157 Pos_index pos1 = _get_pivot_position(pivot1);
158 Pos_index pos2 = _get_pivot_position(pivot2);
162 std::swap(CP::indexToBar_.at(pos1), CP::indexToBar_.at(pos2));
166 Pos_index pos1 = _get_pivot_position(pivot1);
167 Pos_index pos2 = _get_pivot_position(pivot2);
168 return pos1 < pos2 ? (pos2 - pos1) == 1 : (pos1 - pos2) == 1;
173 pivotToPosition_.swap(other.pivotToPosition_);
176 swap(
static_cast<Chain_pairing<Master_matrix>&
>(swap1),
static_cast<Chain_pairing<Master_matrix>&
>(swap2));
177 swap1.pivotToPosition_.swap(swap2.pivotToPosition_);
181 Pos_index simplexIndex = _get_pivot_position(pivot);
183 if constexpr (Master_matrix::Option_list::has_removable_columns) {
184 return CP::indexToBar_.at(simplexIndex)->death;
186 return CP::barcode_.at(CP::indexToBar_.at(simplexIndex)).death;
191 Pos_index simplexIndex = _get_pivot_position(pivot);
193 if constexpr (Master_matrix::Option_list::has_removable_columns) {
194 return CP::indexToBar_.at(simplexIndex)->birth;
196 return CP::barcode_.at(CP::indexToBar_.at(simplexIndex)).birth;
202 if constexpr (Master_matrix::Option_list::has_map_column_container) {
203 return pivotToPosition_.at(
206 return pivotToPosition_[pivot];
211 if constexpr (Master_matrix::Option_list::has_removable_columns) {
212 return CP::indexToBar_.at(simplexIndex)->death;
214 return CP::barcode_.at(CP::indexToBar_.at(simplexIndex)).death;
219 if constexpr (Master_matrix::Option_list::has_removable_columns) {
220 return CP::indexToBar_.at(simplexIndex)->birth;
222 return CP::barcode_.at(CP::indexToBar_.at(simplexIndex)).birth;
235template <
class Master_matrix>
236class Chain_vine_swap :
public std::conditional<Master_matrix::Option_list::has_column_pairings,
237 Chain_barcode_swap<Master_matrix>,
238 Dummy_chain_vine_pairing
242 using Index =
typename Master_matrix::Index;
246 using Column =
typename Master_matrix::Column;
316 if constexpr (Master_matrix::Option_list::has_column_pairings) {
320 std::swap(swap1.birthComp_, swap2.birthComp_);
321 std::swap(swap1.deathComp_, swap2.deathComp_);
325 using CP =
typename std::conditional<Master_matrix::Option_list::has_column_pairings,
331 using Master_chain_matrix =
typename Master_matrix::Master_chain_matrix;
336 bool _is_negative_in_pair(Index columnIndex);
338 Index _positive_vine_swap(Index columnIndex1, Index columnIndex2);
339 Index _positive_negative_vine_swap(Index columnIndex1, Index columnIndex2);
340 Index _negative_positive_vine_swap(Index columnIndex1, Index columnIndex2);
341 Index _negative_vine_swap(Index columnIndex1, Index columnIndex2);
343 constexpr Master_chain_matrix* _matrix() {
return static_cast<Master_chain_matrix*
>(
this); }
344 constexpr const Master_chain_matrix* _matrix()
const {
return static_cast<const Master_chain_matrix*
>(
this); }
347template <
class Master_matrix>
350 static_assert(Master_matrix::Option_list::has_column_pairings,
351 "If barcode is not stored, at least a birth comparator has to be specified.");
354template <
class Master_matrix>
357 : CP(), birthComp_(
std::move(birthComparator)), deathComp_(
std::move(deathComparator))
360template <
class Master_matrix>
362 : CP(static_cast<const CP&>(matrixToCopy)),
363 birthComp_(matrixToCopy.birthComp_),
364 deathComp_(matrixToCopy.deathComp_)
367template <
class Master_matrix>
369 : CP(std::move(
static_cast<CP&
>(other))),
370 birthComp_(std::move(other.birthComp_)),
371 deathComp_(std::move(other.deathComp_))
374template <
class Master_matrix>
378 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
379 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
381 if (col1IsNeg && col2IsNeg)
return _negative_vine_swap(columnIndex1, columnIndex2);
383 if (col1IsNeg)
return _negative_positive_vine_swap(columnIndex1, columnIndex2);
385 if (col2IsNeg)
return _positive_negative_vine_swap(columnIndex1, columnIndex2);
387 return _positive_vine_swap(columnIndex1, columnIndex2);
390template <
class Master_matrix>
394 if constexpr (Master_matrix::Option_list::has_column_pairings) {
395 GUDHI_CHECK(CP::are_adjacent(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2)),
396 std::invalid_argument(
397 "Chain_vine_swap::vine_swap - Columns to be swapped need to be adjacent in the 'real' matrix."));
400 const bool col1IsNeg = _is_negative_in_pair(columnIndex1);
401 const bool col2IsNeg = _is_negative_in_pair(columnIndex2);
403 if (col1IsNeg && col2IsNeg) {
404 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
405 if constexpr (Master_matrix::Option_list::has_column_pairings) {
406 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
407 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
409 CP::negative_transpose(pivot1, pivot2);
410 CP::swap_positions(pivot1, pivot2);
414 return _negative_vine_swap(columnIndex1, columnIndex2);
418 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
419 if constexpr (Master_matrix::Option_list::has_column_pairings) {
420 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
421 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
423 CP::negative_positive_transpose(pivot1, pivot2);
424 CP::swap_positions(pivot1, pivot2);
428 return _negative_positive_vine_swap(columnIndex1, columnIndex2);
432 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
433 if constexpr (Master_matrix::Option_list::has_column_pairings) {
434 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
435 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
437 CP::positive_negative_transpose(pivot1, pivot2);
438 CP::swap_positions(pivot1, pivot2);
442 return _positive_negative_vine_swap(columnIndex1, columnIndex2);
445 if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) {
446 if constexpr (Master_matrix::Option_list::has_column_pairings) {
447 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
448 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
450 CP::positive_transpose(pivot1, pivot2);
451 CP::swap_positions(pivot1, pivot2);
455 return _positive_vine_swap(columnIndex1, columnIndex2);
458template <
class Master_matrix>
461 CP::operator=(other);
462 std::swap(birthComp_, other.birthComp_);
463 std::swap(deathComp_, other.deathComp_);
467template <
class Master_matrix>
470 if constexpr (Master_matrix::Option_list::has_column_pairings) {
471 return CP::is_negative_in_pair(_matrix()->get_pivot(columnIndex));
473 auto& col = _matrix()->get_column(columnIndex);
474 if (!col.is_paired())
return false;
475 return col.get_pivot() > _matrix()->get_pivot(col.get_paired_chain_index());
479template <
class Master_matrix>
481 Index columnIndex1, Index columnIndex2)
483 auto& col1 = _matrix()->get_column(columnIndex1);
484 auto& col2 = _matrix()->get_column(columnIndex2);
486 if constexpr (Master_matrix::Option_list::has_column_pairings) {
487 CP::swap_positions(col1.get_pivot(), col2.get_pivot());
491 if (!col1.is_paired()) {
492 bool hasSmallerBirth;
493 if constexpr (Master_matrix::Option_list::has_column_pairings) {
495 hasSmallerBirth = (CP::birth(col2.get_pivot()) < CP::birth(col1.get_pivot()));
497 hasSmallerBirth = birthComp_(columnIndex1, columnIndex2);
500 if (!col2.is_paired() && hasSmallerBirth) {
501 _matrix()->add_to(columnIndex1, columnIndex2);
502 if constexpr (Master_matrix::Option_list::has_column_pairings) {
503 CP::positive_transpose(col1.get_pivot(), col2.get_pivot());
507 _matrix()->add_to(columnIndex2, columnIndex1);
512 if (!col2.is_paired()) {
513 static_cast<Master_chain_matrix*
>(
this)->add_to(columnIndex1, columnIndex2);
514 if constexpr (Master_matrix::Option_list::has_column_pairings) {
515 CP::positive_transpose(col1.get_pivot(), col2.get_pivot());
520 bool hasSmallerDeath;
521 if constexpr (Master_matrix::Option_list::has_column_pairings) {
523 hasSmallerDeath = (CP::death(col2.get_pivot()) < CP::death(col1.get_pivot()));
525 hasSmallerDeath = deathComp_(columnIndex1, columnIndex2);
531 _matrix()->add_to(col1.get_paired_chain_index(), col2.get_paired_chain_index());
532 _matrix()->add_to(columnIndex1, columnIndex2);
533 if constexpr (Master_matrix::Option_list::has_column_pairings) {
534 CP::positive_transpose(col1.get_pivot(), col2.get_pivot());
539 _matrix()->add_to(col2.get_paired_chain_index(), col1.get_paired_chain_index());
540 _matrix()->add_to(columnIndex2, columnIndex1);
545template <
class Master_matrix>
547 Index columnIndex1, Index columnIndex2)
549 _matrix()->add_to(columnIndex1, columnIndex2);
551 if constexpr (Master_matrix::Option_list::has_column_pairings) {
552 ID_index pivot1 = _matrix()->get_pivot(columnIndex1);
553 ID_index pivot2 = _matrix()->get_pivot(columnIndex2);
555 CP::positive_negative_transpose(pivot1, pivot2);
556 CP::swap_positions(pivot1, pivot2);
562template <
class Master_matrix>
564 Index columnIndex1, Index columnIndex2)
566 _matrix()->add_to(columnIndex2, columnIndex1);
568 if constexpr (Master_matrix::Option_list::has_column_pairings) {
569 CP::swap_positions(_matrix()->get_pivot(columnIndex1), _matrix()->get_pivot(columnIndex2));
575template <
class Master_matrix>
577 Index columnIndex1, Index columnIndex2)
579 auto& col1 = _matrix()->get_column(columnIndex1);
580 auto& col2 = _matrix()->get_column(columnIndex2);
582 Index pairedIndex1 = col1.get_paired_chain_index();
583 Index pairedIndex2 = col2.get_paired_chain_index();
585 bool hasSmallerBirth;
586 if constexpr (Master_matrix::Option_list::has_column_pairings) {
587 hasSmallerBirth = (CP::birth(col1.get_pivot()) < CP::birth(col2.get_pivot()));
589 hasSmallerBirth = birthComp_(pairedIndex1, pairedIndex2);
592 if constexpr (Master_matrix::Option_list::has_column_pairings) {
593 CP::swap_positions(col1.get_pivot(), col2.get_pivot());
598 _matrix()->add_to(pairedIndex1, pairedIndex2);
599 _matrix()->add_to(columnIndex1, columnIndex2);
601 if constexpr (Master_matrix::Option_list::has_column_pairings) {
602 CP::negative_transpose(col1.get_pivot(), col2.get_pivot());
608 _matrix()->add_to(pairedIndex2, pairedIndex1);
609 _matrix()->add_to(columnIndex2, columnIndex1);
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:85
typename Master_matrix::Pos_index Pos_index
Definition: chain_vine_swap.h:88
Chain_barcode_swap()
Default constructor.
Definition: chain_vine_swap.h:95
Chain_barcode_swap(const Chain_barcode_swap &toCopy)
Copy constructor.
Definition: chain_vine_swap.h:101
typename Master_matrix::ID_index ID_index
Definition: chain_vine_swap.h:87
Chain_barcode_swap(Chain_barcode_swap &&other)
Move constructor.
Definition: chain_vine_swap.h:108
Class managing the barcode for Chain_matrix if the option was enabled.
Definition: chain_pairing.h:48
Chain_pairing & operator=(Chain_pairing other)
Assign operator.
Definition: chain_pairing.h:125
Class managing the vine swaps for Chain_matrix.
Definition: chain_vine_swap.h:240
Chain_vine_swap()
Default constructor. Only available if PersistenceMatrixOptions::has_column_pairings is true.
Definition: chain_vine_swap.h:348
typename Master_matrix::Pos_index Pos_index
Definition: chain_vine_swap.h:244
Chain_vine_swap & operator=(Chain_vine_swap other)
Assign operator.
Definition: chain_vine_swap.h:459
typename Master_matrix::Column_container Column_container
Definition: chain_vine_swap.h:245
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:391
typename Master_matrix::Index Index
Definition: chain_vine_swap.h:242
typename Master_matrix::ID_index ID_index
Definition: chain_vine_swap.h:243
friend void swap(Chain_vine_swap &swap1, Chain_vine_swap &swap2)
Swap operator.
Definition: chain_vine_swap.h:315
typename Master_matrix::Column Column
Definition: chain_vine_swap.h:246
bool(* EventCompFuncPointer)(Pos_index, Pos_index)
Definition: chain_vine_swap.h:247
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:375
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
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:72
Empty structure. Inherited instead of Chain_vine_swap, when vine swaps are not enabled.
Definition: chain_vine_swap.h:56