multipers 2.3.3b6__cp313-cp313-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- multipers/.dylibs/libc++.1.0.dylib +0 -0
- multipers/.dylibs/libtbb.12.16.dylib +0 -0
- multipers/__init__.py +33 -0
- multipers/_signed_measure_meta.py +453 -0
- multipers/_slicer_meta.py +211 -0
- multipers/array_api/__init__.py +45 -0
- multipers/array_api/numpy.py +41 -0
- multipers/array_api/torch.py +58 -0
- multipers/data/MOL2.py +458 -0
- multipers/data/UCR.py +18 -0
- multipers/data/__init__.py +1 -0
- multipers/data/graphs.py +466 -0
- multipers/data/immuno_regions.py +27 -0
- multipers/data/minimal_presentation_to_st_bf.py +0 -0
- multipers/data/pytorch2simplextree.py +91 -0
- multipers/data/shape3d.py +101 -0
- multipers/data/synthetic.py +113 -0
- multipers/distances.py +202 -0
- multipers/filtration_conversions.pxd +229 -0
- multipers/filtration_conversions.pxd.tp +84 -0
- multipers/filtrations/__init__.py +18 -0
- multipers/filtrations/density.py +574 -0
- multipers/filtrations/filtrations.py +361 -0
- multipers/filtrations.pxd +224 -0
- multipers/function_rips.cpython-313-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-313-darwin.so +0 -0
- multipers/grids.pyx +433 -0
- multipers/gudhi/Persistence_slices_interface.h +132 -0
- multipers/gudhi/Simplex_tree_interface.h +239 -0
- multipers/gudhi/Simplex_tree_multi_interface.h +551 -0
- multipers/gudhi/cubical_to_boundary.h +59 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
- multipers/gudhi/gudhi/Debug_utils.h +45 -0
- multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
- multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
- multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
- multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
- multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
- multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
- multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
- multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
- multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
- multipers/gudhi/gudhi/Matrix.h +2107 -0
- multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
- multipers/gudhi/gudhi/Multi_persistence/Box.h +174 -0
- multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
- multipers/gudhi/gudhi/Off_reader.h +173 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +1441 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
- multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
- multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
- multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
- multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
- multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
- multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
- multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
- multipers/gudhi/gudhi/Points_off_io.h +171 -0
- multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
- multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
- multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
- multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
- multipers/gudhi/gudhi/Simplex_tree_multi.h +152 -0
- multipers/gudhi/gudhi/distance_functions.h +62 -0
- multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
- multipers/gudhi/gudhi/persistence_interval.h +253 -0
- multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
- multipers/gudhi/gudhi/reader_utils.h +367 -0
- multipers/gudhi/mma_interface_coh.h +256 -0
- multipers/gudhi/mma_interface_h0.h +223 -0
- multipers/gudhi/mma_interface_matrix.h +293 -0
- multipers/gudhi/naive_merge_tree.h +536 -0
- multipers/gudhi/scc_io.h +310 -0
- multipers/gudhi/truc.h +1403 -0
- multipers/io.cpython-313-darwin.so +0 -0
- multipers/io.pyx +644 -0
- multipers/ml/__init__.py +0 -0
- multipers/ml/accuracies.py +90 -0
- multipers/ml/invariants_with_persistable.py +79 -0
- multipers/ml/kernels.py +176 -0
- multipers/ml/mma.py +713 -0
- multipers/ml/one.py +472 -0
- multipers/ml/point_clouds.py +352 -0
- multipers/ml/signed_measures.py +1589 -0
- multipers/ml/sliced_wasserstein.py +461 -0
- multipers/ml/tools.py +113 -0
- multipers/mma_structures.cpython-313-darwin.so +0 -0
- multipers/mma_structures.pxd +128 -0
- multipers/mma_structures.pyx +2786 -0
- multipers/mma_structures.pyx.tp +1094 -0
- multipers/multi_parameter_rank_invariant/diff_helpers.h +84 -0
- multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
- multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
- multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
- multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
- multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
- multipers/multiparameter_edge_collapse.py +41 -0
- multipers/multiparameter_module_approximation/approximation.h +2330 -0
- multipers/multiparameter_module_approximation/combinatory.h +129 -0
- multipers/multiparameter_module_approximation/debug.h +107 -0
- multipers/multiparameter_module_approximation/euler_curves.h +0 -0
- multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
- multipers/multiparameter_module_approximation/heap_column.h +238 -0
- multipers/multiparameter_module_approximation/images.h +79 -0
- multipers/multiparameter_module_approximation/list_column.h +174 -0
- multipers/multiparameter_module_approximation/list_column_2.h +232 -0
- multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
- multipers/multiparameter_module_approximation/set_column.h +135 -0
- multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
- multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
- multipers/multiparameter_module_approximation/utilities.h +403 -0
- multipers/multiparameter_module_approximation/vector_column.h +223 -0
- multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
- multipers/multiparameter_module_approximation/vineyards.h +464 -0
- multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
- multipers/multiparameter_module_approximation.cpython-313-darwin.so +0 -0
- multipers/multiparameter_module_approximation.pyx +235 -0
- multipers/pickle.py +90 -0
- multipers/plots.py +456 -0
- multipers/point_measure.cpython-313-darwin.so +0 -0
- multipers/point_measure.pyx +395 -0
- multipers/simplex_tree_multi.cpython-313-darwin.so +0 -0
- multipers/simplex_tree_multi.pxd +134 -0
- multipers/simplex_tree_multi.pyx +10840 -0
- multipers/simplex_tree_multi.pyx.tp +2009 -0
- multipers/slicer.cpython-313-darwin.so +0 -0
- multipers/slicer.pxd +3034 -0
- multipers/slicer.pxd.tp +234 -0
- multipers/slicer.pyx +20481 -0
- multipers/slicer.pyx.tp +1088 -0
- multipers/tensor/tensor.h +672 -0
- multipers/tensor.pxd +13 -0
- multipers/test.pyx +44 -0
- multipers/tests/__init__.py +62 -0
- multipers/torch/__init__.py +1 -0
- multipers/torch/diff_grids.py +240 -0
- multipers/torch/rips_density.py +310 -0
- multipers-2.3.3b6.dist-info/METADATA +128 -0
- multipers-2.3.3b6.dist-info/RECORD +183 -0
- multipers-2.3.3b6.dist-info/WHEEL +6 -0
- multipers-2.3.3b6.dist-info/licenses/LICENSE +21 -0
- multipers-2.3.3b6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1350 @@
|
|
|
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-24 Inria
|
|
6
|
+
*
|
|
7
|
+
* Modification(s):
|
|
8
|
+
* - YYYY/MM Author: Description of the modification
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @file Chain_matrix.h
|
|
13
|
+
* @author Hannah Schreiber
|
|
14
|
+
* @brief Contains the @ref Gudhi::persistence_matrix::Chain_matrix class.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#ifndef PM_CHAIN_MATRIX_H
|
|
18
|
+
#define PM_CHAIN_MATRIX_H
|
|
19
|
+
|
|
20
|
+
#include <iostream> //print() only
|
|
21
|
+
#include <set>
|
|
22
|
+
#include <map>
|
|
23
|
+
#include <stdexcept>
|
|
24
|
+
#include <vector>
|
|
25
|
+
#include <utility> //std::swap, std::move & std::exchange
|
|
26
|
+
#include <algorithm> //std::sort
|
|
27
|
+
|
|
28
|
+
#include <gudhi/Persistence_matrix/Id_to_index_overlay.h> //friend
|
|
29
|
+
|
|
30
|
+
namespace Gudhi {
|
|
31
|
+
namespace persistence_matrix {
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @class Chain_matrix Chain_matrix.h gudhi/Persistence_matrix/Chain_matrix.h
|
|
35
|
+
* @ingroup persistence_matrix
|
|
36
|
+
*
|
|
37
|
+
* @brief %Matrix structure storing a compatible base of a filtered chain complex. See @cite zigzag.
|
|
38
|
+
* The base is constructed from the boundaries of the cells in the complex. Allows the persistent homology to be
|
|
39
|
+
* computed, as well as representative cycles. Supports vineyards (see @cite vineyards) and the removal
|
|
40
|
+
* of maximal cells while maintaining a valid barcode. Provides an access to its columns and rows.
|
|
41
|
+
*
|
|
42
|
+
* @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced.
|
|
43
|
+
*/
|
|
44
|
+
template <class Master_matrix>
|
|
45
|
+
class Chain_matrix : public Master_matrix::Matrix_dimension_option,
|
|
46
|
+
public Master_matrix::Chain_pairing_option,
|
|
47
|
+
public Master_matrix::Chain_vine_swap_option,
|
|
48
|
+
public Master_matrix::Chain_representative_cycles_option,
|
|
49
|
+
public Master_matrix::Matrix_row_access_option
|
|
50
|
+
{
|
|
51
|
+
public:
|
|
52
|
+
/**
|
|
53
|
+
* @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false.
|
|
54
|
+
*/
|
|
55
|
+
using Field_operators = typename Master_matrix::Field_operators;
|
|
56
|
+
using Field_element = typename Master_matrix::Element; /**< Type of an field element. */
|
|
57
|
+
using Column = typename Master_matrix::Column; /**< Column type. */
|
|
58
|
+
using Row = typename Master_matrix::Row; /**< Row type, only necessary with row
|
|
59
|
+
access option. */
|
|
60
|
+
using Entry = typename Master_matrix::Matrix_entry; /**< @ref Entry "Matrix entry" type. */
|
|
61
|
+
using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */
|
|
62
|
+
using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns
|
|
63
|
+
to necessary external classes. */
|
|
64
|
+
using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */
|
|
65
|
+
using Entry_representative = typename Master_matrix::Entry_representative; /**< %Entry content representative. */
|
|
66
|
+
using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */
|
|
67
|
+
using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */
|
|
68
|
+
using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */
|
|
69
|
+
using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @brief Constructs an empty matrix. Only available if @ref PersistenceMatrixOptions::has_column_pairings is
|
|
73
|
+
* true or @ref PersistenceMatrixOptions::has_vine_update is false. Otherwise, birth and death comparators have
|
|
74
|
+
* to be provided.
|
|
75
|
+
*
|
|
76
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
77
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
78
|
+
*/
|
|
79
|
+
Chain_matrix(Column_settings* colSettings);
|
|
80
|
+
/**
|
|
81
|
+
* @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds
|
|
82
|
+
* to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by
|
|
83
|
+
* increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting
|
|
84
|
+
* with 0. Only available if @ref PersistenceMatrixOptions::has_column_pairings is true or
|
|
85
|
+
* @ref PersistenceMatrixOptions::has_vine_update is false. Otherwise, birth and death
|
|
86
|
+
* comparators have to be provided.
|
|
87
|
+
*
|
|
88
|
+
* @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges.
|
|
89
|
+
* Assumed to have a begin(), end() and size() method.
|
|
90
|
+
* @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a
|
|
91
|
+
* filtered **simplicial** complex, whose boundaries are ordered by filtration order.
|
|
92
|
+
* Therefore, `orderedBoundaries[i]` should store the boundary of the \f$ i^{th} \f$ simplex in the filtration,
|
|
93
|
+
* as an ordered list of indices of its facets (again those indices correspond to their respective position
|
|
94
|
+
* in the matrix). That is why the indices of the simplices are assumed to be consecutive and starting with 0
|
|
95
|
+
* (an empty boundary is interpreted as a vertex boundary and not as a non existing simplex).
|
|
96
|
+
* All dimensions up to the maximal dimension of interest have to be present. If only a higher dimension is of
|
|
97
|
+
* interest and not everything should be stored, then use the @ref insert_boundary method instead
|
|
98
|
+
* (after creating the matrix with the
|
|
99
|
+
* @ref Chain_matrix(unsigned int numberOfColumns, Column_settings* colSettings)
|
|
100
|
+
* constructor preferably).
|
|
101
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
102
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
103
|
+
*/
|
|
104
|
+
template <class Boundary_range = Boundary>
|
|
105
|
+
Chain_matrix(const std::vector<Boundary_range>& orderedBoundaries,
|
|
106
|
+
Column_settings* colSettings);
|
|
107
|
+
/**
|
|
108
|
+
* @brief Constructs a new empty matrix and reserves space for the given number of columns. Only available
|
|
109
|
+
* if @ref PersistenceMatrixOptions::has_column_pairings is true or @ref PersistenceMatrixOptions::has_vine_update
|
|
110
|
+
* is false. Otherwise, birth and death comparators have to be provided.
|
|
111
|
+
*
|
|
112
|
+
* @param numberOfColumns Number of columns to reserve space for.
|
|
113
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
114
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
115
|
+
*/
|
|
116
|
+
Chain_matrix(unsigned int numberOfColumns, Column_settings* colSettings);
|
|
117
|
+
/**
|
|
118
|
+
* @brief Constructs an empty matrix and stores the given comparators.
|
|
119
|
+
*
|
|
120
|
+
* @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used.
|
|
121
|
+
* And if @ref PersistenceMatrixOptions::has_vine_update is true, but
|
|
122
|
+
* @ref PersistenceMatrixOptions::has_column_pairings is also true, the comparators are ignored and
|
|
123
|
+
* the current barcode is used to compare birth and deaths. Therefore it is useless to provide them in those cases.
|
|
124
|
+
*
|
|
125
|
+
* @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
126
|
+
* @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
127
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
128
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
129
|
+
* @param birthComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
130
|
+
* the birth associated to the first position is strictly less than birth associated to
|
|
131
|
+
* the second one with respect to some self defined order. It is used while swapping two unpaired or
|
|
132
|
+
* two negative columns.
|
|
133
|
+
* @param deathComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
134
|
+
* the death associated to the first position is strictly less than death associated to
|
|
135
|
+
* the second one with respect to some self defined order. It is used while swapping two positive but paired
|
|
136
|
+
* columns.
|
|
137
|
+
*/
|
|
138
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction>
|
|
139
|
+
Chain_matrix(Column_settings* colSettings,
|
|
140
|
+
const BirthComparatorFunction& birthComparator,
|
|
141
|
+
const DeathComparatorFunction& deathComparator);
|
|
142
|
+
/**
|
|
143
|
+
* @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds
|
|
144
|
+
* to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by
|
|
145
|
+
* increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting
|
|
146
|
+
* with 0.
|
|
147
|
+
*
|
|
148
|
+
* @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used.
|
|
149
|
+
* And if @ref PersistenceMatrixOptions::has_vine_update is true, but
|
|
150
|
+
* @ref PersistenceMatrixOptions::has_column_pairings is also true, the comparators are ignored and
|
|
151
|
+
* the current barcode is used to compare birth and deaths. Therefore it is useless to provide them in those cases.
|
|
152
|
+
*
|
|
153
|
+
* @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
154
|
+
* @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
155
|
+
* @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges.
|
|
156
|
+
* Assumed to have a begin(), end() and size() method.
|
|
157
|
+
* @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a
|
|
158
|
+
* filtered **simplicial** complex, whose boundaries are ordered by filtration order.
|
|
159
|
+
* Therefore, `orderedBoundaries[i]` should store the boundary of the \f$ i^{th} \f$ simplex in the filtration,
|
|
160
|
+
* as an ordered list of indices of its facets (again those indices correspond to their respective position
|
|
161
|
+
* in the matrix). That is why the indices of the simplices are assumed to be consecutive and starting with 0
|
|
162
|
+
* (an empty boundary is interpreted as a vertex boundary and not as a non existing simplex).
|
|
163
|
+
* All dimensions up to the maximal dimension of interest have to be present. If only a higher dimension is of
|
|
164
|
+
* interest and not everything should be stored, then use the @ref insert_boundary method instead
|
|
165
|
+
* (after creating the matrix with the @ref Chain_matrix(unsigned int, Column_settings*,
|
|
166
|
+
* const BirthComparatorFunction&, const DeathComparatorFunction&) constructor preferably).
|
|
167
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
168
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
169
|
+
* @param birthComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
170
|
+
* the birth associated to the first position is strictly less than birth associated to
|
|
171
|
+
* the second one with respect to some self defined order. It is used while swapping two unpaired or
|
|
172
|
+
* two negative columns.
|
|
173
|
+
* @param deathComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
174
|
+
* the death associated to the first position is strictly less than death associated to
|
|
175
|
+
* the second one with respect to some self defined order. It is used while swapping two positive but paired
|
|
176
|
+
* columns.
|
|
177
|
+
*/
|
|
178
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction, class Boundary_range = Boundary>
|
|
179
|
+
Chain_matrix(const std::vector<Boundary_range>& orderedBoundaries,
|
|
180
|
+
Column_settings* colSettings,
|
|
181
|
+
const BirthComparatorFunction& birthComparator,
|
|
182
|
+
const DeathComparatorFunction& deathComparator);
|
|
183
|
+
/**
|
|
184
|
+
* @brief Constructs a new empty matrix and reserves space for the given number of columns.
|
|
185
|
+
*
|
|
186
|
+
* @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used.
|
|
187
|
+
* And if @ref PersistenceMatrixOptions::has_vine_update is true, but
|
|
188
|
+
* @ref PersistenceMatrixOptions::has_column_pairings is also true, the comparators are ignored and
|
|
189
|
+
* the current barcode is used to compare birth and deaths. Therefore it is useless to provide them in those cases.
|
|
190
|
+
*
|
|
191
|
+
* @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
192
|
+
* @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool
|
|
193
|
+
* @param numberOfColumns Number of columns to reserve space for.
|
|
194
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
195
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
196
|
+
* @param birthComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
197
|
+
* the birth associated to the first position is strictly less than birth associated to
|
|
198
|
+
* the second one with respect to some self defined order. It is used while swapping two unpaired or
|
|
199
|
+
* two negative columns.
|
|
200
|
+
* @param deathComparator Method taking two @ref PosIdx indices as input and returning true if and only if
|
|
201
|
+
* the death associated to the first position is strictly less than death associated to
|
|
202
|
+
* the second one with respect to some self defined order. It is used while swapping two positive but paired
|
|
203
|
+
* columns.
|
|
204
|
+
*/
|
|
205
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction>
|
|
206
|
+
Chain_matrix(unsigned int numberOfColumns,
|
|
207
|
+
Column_settings* colSettings,
|
|
208
|
+
const BirthComparatorFunction& birthComparator,
|
|
209
|
+
const DeathComparatorFunction& deathComparator);
|
|
210
|
+
/**
|
|
211
|
+
* @brief Copy constructor. If @p colSettings is not a null pointer, its value is kept
|
|
212
|
+
* instead of the one in the copied matrix.
|
|
213
|
+
*
|
|
214
|
+
* @param matrixToCopy Matrix to copy.
|
|
215
|
+
* @param colSettings Either a pointer to an existing setting structure for the columns or a null pointer.
|
|
216
|
+
* The structure should contain all the necessary external classes specifically necessary for the choosen column type,
|
|
217
|
+
* such as custom allocators. If null pointer, the pointer stored in @p matrixToCopy is used instead.
|
|
218
|
+
*/
|
|
219
|
+
Chain_matrix(const Chain_matrix& matrixToCopy,
|
|
220
|
+
Column_settings* colSettings = nullptr);
|
|
221
|
+
/**
|
|
222
|
+
* @brief Move constructor.
|
|
223
|
+
*
|
|
224
|
+
* @param other Matrix to move.
|
|
225
|
+
*/
|
|
226
|
+
Chain_matrix(Chain_matrix&& other) noexcept;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary.
|
|
230
|
+
* This means that it is assumed that this method is called on boundaries in the order of the filtration.
|
|
231
|
+
* It also assumes that the cells in the given boundary are identified by their relative position in the filtration,
|
|
232
|
+
* starting at 0. If it is not the case, use the other
|
|
233
|
+
* @ref insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary"
|
|
234
|
+
* instead by indicating the cell ID used in the boundaries when the cell is inserted.
|
|
235
|
+
*
|
|
236
|
+
* Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from
|
|
237
|
+
* a more general entry complex. This includes cubical complexes or Morse complexes for example.
|
|
238
|
+
*
|
|
239
|
+
* When inserted, the given boundary is reduced and from the reduction process, the column is deduced in the form of:
|
|
240
|
+
* `IDIdx + linear combination of older column IDIdxs`. If the barcode is stored, it will be updated.
|
|
241
|
+
*
|
|
242
|
+
* @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size()
|
|
243
|
+
* method.
|
|
244
|
+
* @param boundary Boundary generating the new column. The content should be ordered by ID.
|
|
245
|
+
* @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
|
|
246
|
+
* this parameter can be omitted as it can be deduced from the size of the boundary.
|
|
247
|
+
* @return The @ref MatIdx indices of the unpaired chains used to reduce the boundary.
|
|
248
|
+
*/
|
|
249
|
+
template <class Boundary_range = Boundary>
|
|
250
|
+
std::vector<Entry_representative> insert_boundary(const Boundary_range& boundary, Dimension dim = -1);
|
|
251
|
+
/**
|
|
252
|
+
* @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions
|
|
253
|
+
* except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then
|
|
254
|
+
* to use the other insertion method to avoid overwriting IDs.
|
|
255
|
+
*
|
|
256
|
+
* As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that
|
|
257
|
+
* the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted.
|
|
258
|
+
*
|
|
259
|
+
* @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size()
|
|
260
|
+
* method.
|
|
261
|
+
* @param cellID @ref IDIdx index to use to identify the new cell.
|
|
262
|
+
* @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the
|
|
263
|
+
* @p cellID values of precedent calls of the method for the corresponding cells and should be ordered in
|
|
264
|
+
* increasing order.
|
|
265
|
+
* @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
|
|
266
|
+
* this parameter can be omitted as it can be deduced from the size of the boundary.
|
|
267
|
+
* @return The @ref MatIdx index of the inserted boundary.
|
|
268
|
+
*/
|
|
269
|
+
template <class Boundary_range = Boundary>
|
|
270
|
+
std::vector<Entry_representative> insert_boundary(ID_index cellID,
|
|
271
|
+
const Boundary_range& boundary,
|
|
272
|
+
Dimension dim = -1);
|
|
273
|
+
/**
|
|
274
|
+
* @brief Returns the column at the given @ref MatIdx index.
|
|
275
|
+
* The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type.
|
|
276
|
+
*
|
|
277
|
+
* @param columnIndex @ref MatIdx index of the column to return.
|
|
278
|
+
* @return Reference to the column.
|
|
279
|
+
*/
|
|
280
|
+
Column& get_column(Index columnIndex);
|
|
281
|
+
/**
|
|
282
|
+
* @brief Returns the column at the given @ref MatIdx index.
|
|
283
|
+
* The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type.
|
|
284
|
+
*
|
|
285
|
+
* @param columnIndex @ref MatIdx index of the column to return.
|
|
286
|
+
* @return Const reference to the column.
|
|
287
|
+
*/
|
|
288
|
+
const Column& get_column(Index columnIndex) const;
|
|
289
|
+
/**
|
|
290
|
+
* @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns and
|
|
291
|
+
* @ref PersistenceMatrixOptions::has_vine_update are true, as well as,
|
|
292
|
+
* @ref PersistenceMatrixOptions::has_map_column_container and @ref PersistenceMatrixOptions::has_column_pairings.
|
|
293
|
+
* Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent
|
|
294
|
+
* (i.e., the matrix is still a compatible bases of the chain complex in the sense of @cite zigzag).
|
|
295
|
+
* The maximality of the cell is not verified.
|
|
296
|
+
* Also updates the barcode if it is stored.
|
|
297
|
+
*
|
|
298
|
+
* Note that using the other version of the method could perform better depending on how the data is
|
|
299
|
+
* maintained on the side of the user, that is, if providing the second parameter is easy.
|
|
300
|
+
*
|
|
301
|
+
* See also @ref remove_last.
|
|
302
|
+
*
|
|
303
|
+
* @param cellID @ref IDIdx index of the cell to remove
|
|
304
|
+
*/
|
|
305
|
+
void remove_maximal_cell(ID_index cellID);
|
|
306
|
+
/**
|
|
307
|
+
* @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns,
|
|
308
|
+
* @ref PersistenceMatrixOptions::has_vine_update and @ref PersistenceMatrixOptions::has_map_column_container
|
|
309
|
+
* are true.
|
|
310
|
+
* Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent
|
|
311
|
+
* (i.e., it is still a compatible bases of the chain complex in the sense of @cite zigzag).
|
|
312
|
+
* The maximality of the cell is not verified.
|
|
313
|
+
* Also updates the barcode if it is stored.
|
|
314
|
+
*
|
|
315
|
+
* To maintain the compatibility, vine swaps are done to move the cell up to the end of the filtration. Once at
|
|
316
|
+
* the end, the removal is trivial. But for @ref chainmatrix "chain matrices", swaps do not actually swap the position
|
|
317
|
+
* of the column every time, so the cells appearing after @p cellID in the filtration have to be searched first within
|
|
318
|
+
* the matrix. If the user has an easy access to the @ref IDIdx of the cells in the order of filtration, passing them
|
|
319
|
+
* by argument with @p columnsToSwap allows to skip a linear search process. Typically, if the user knows that the
|
|
320
|
+
* cell he wants to remove is already the last cell of the filtration, calling
|
|
321
|
+
* @ref remove_maximal_cell(ID_index cellIndex, const std::vector<ID_index>& columnsToSwap)
|
|
322
|
+
* "remove_maximal_cell(cellID, {})" will be faster than @ref remove_last().
|
|
323
|
+
*
|
|
324
|
+
* See also @ref remove_last.
|
|
325
|
+
*
|
|
326
|
+
* @param cellID @ref IDIdx index of the cell to remove
|
|
327
|
+
* @param columnsToSwap Vector of @ref IDIdx indices of the cells coming after @p cellID in the filtration.
|
|
328
|
+
*/
|
|
329
|
+
void remove_maximal_cell(ID_index cellID, const std::vector<ID_index>& columnsToSwap);
|
|
330
|
+
/**
|
|
331
|
+
* @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true and,
|
|
332
|
+
* if @ref PersistenceMatrixOptions::has_map_column_container is true or
|
|
333
|
+
* @ref PersistenceMatrixOptions::has_vine_update is false.
|
|
334
|
+
* Removes the last cell in the filtration from the matrix and updates the barcode if it is stored.
|
|
335
|
+
*
|
|
336
|
+
* See also @ref remove_maximal_cell.
|
|
337
|
+
*
|
|
338
|
+
* @warning If @ref PersistenceMatrixOptions::has_vine_update is true, the last cell does not have to
|
|
339
|
+
* be at the end of the matrix container and therefore has to be searched first. In this case, if the user
|
|
340
|
+
* already knows the @ref IDIdx of the last cell, calling
|
|
341
|
+
* @ref remove_maximal_cell(ID_index cellIndex, const std::vector<ID_index>& columnsToSwap)
|
|
342
|
+
* "remove_maximal_cell(cellID, {})" instead allows to skip the search.
|
|
343
|
+
*/
|
|
344
|
+
void remove_last();
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* @brief Returns the current number of columns in the matrix.
|
|
348
|
+
*
|
|
349
|
+
* @return The number of columns.
|
|
350
|
+
*/
|
|
351
|
+
Index get_number_of_columns() const;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @brief Returns the dimension of the given column.
|
|
355
|
+
*
|
|
356
|
+
* @param columnIndex @ref MatIdx index of the column representing the cell.
|
|
357
|
+
* @return Dimension of the cell.
|
|
358
|
+
*/
|
|
359
|
+
Dimension get_column_dimension(Index columnIndex) const;
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @brief Adds column at @p sourceColumnIndex onto the column at @p targetColumnIndex in the matrix.
|
|
363
|
+
*
|
|
364
|
+
* @warning They will be no verification to ensure that the addition makes sense for the validity of a
|
|
365
|
+
* @ref chainmatrix "chain matrix". For example, a right-to-left addition could corrupt the computation
|
|
366
|
+
* of the barcode if done blindly. So should be used with care.
|
|
367
|
+
*
|
|
368
|
+
* @param sourceColumnIndex @ref MatIdx index of the source column.
|
|
369
|
+
* @param targetColumnIndex @ref MatIdx index of the target column.
|
|
370
|
+
*/
|
|
371
|
+
void add_to(Index sourceColumnIndex, Index targetColumnIndex);
|
|
372
|
+
/**
|
|
373
|
+
* @brief Multiplies the target column with the coefficient and then adds the source column to it.
|
|
374
|
+
* That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`.
|
|
375
|
+
*
|
|
376
|
+
* @warning They will be no verification to ensure that the addition makes sense for the validity of a
|
|
377
|
+
* @ref chainmatrix "chain matrix". For example, a right-to-left addition could corrupt the computation
|
|
378
|
+
* of the barcode if done blindly. So should be used with care.
|
|
379
|
+
*
|
|
380
|
+
* @param sourceColumnIndex @ref MatIdx index of the source column.
|
|
381
|
+
* @param coefficient Value to multiply.
|
|
382
|
+
* @param targetColumnIndex @ref MatIdx index of the target column.
|
|
383
|
+
*/
|
|
384
|
+
void multiply_target_and_add_to(Index sourceColumnIndex,
|
|
385
|
+
const Field_element& coefficient,
|
|
386
|
+
Index targetColumnIndex);
|
|
387
|
+
/**
|
|
388
|
+
* @brief Multiplies the source column with the coefficient before adding it to the target column.
|
|
389
|
+
* That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified.
|
|
390
|
+
*
|
|
391
|
+
* @warning They will be no verification to ensure that the addition makes sense for the validity of a
|
|
392
|
+
* @ref chainmatrix "chain matrix". For example, a right-to-left addition could corrupt the computation
|
|
393
|
+
* of the barcode if done blindly. So should be used with care.
|
|
394
|
+
*
|
|
395
|
+
* @param coefficient Value to multiply.
|
|
396
|
+
* @param sourceColumnIndex @ref MatIdx index of the source column.
|
|
397
|
+
* @param targetColumnIndex @ref MatIdx index of the target column.
|
|
398
|
+
*/
|
|
399
|
+
void multiply_source_and_add_to(const Field_element& coefficient,
|
|
400
|
+
Index sourceColumnIndex,
|
|
401
|
+
Index targetColumnIndex);
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @brief Indicates if the entry at given coordinates has value zero.
|
|
405
|
+
*
|
|
406
|
+
* @param columnIndex @ref MatIdx index of the column of the entry.
|
|
407
|
+
* @param rowIndex @ref rowindex "Row index" of the row of the entry.
|
|
408
|
+
* @return true If the entry has value zero.
|
|
409
|
+
* @return false Otherwise.
|
|
410
|
+
*/
|
|
411
|
+
bool is_zero_entry(Index columnIndex, ID_index rowIndex) const;
|
|
412
|
+
/**
|
|
413
|
+
* @brief Indicates if the column at given index has value zero. Note that if the matrix is valid, this method
|
|
414
|
+
* should always return false.
|
|
415
|
+
*
|
|
416
|
+
* @param columnIndex @ref MatIdx index of the column.
|
|
417
|
+
* @return true If the column has value zero.
|
|
418
|
+
* @return false Otherwise.
|
|
419
|
+
*/
|
|
420
|
+
bool is_zero_column(Index columnIndex);
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* @brief Returns the column with given @ref rowindex "row index" as pivot. Assumes that the pivot exists.
|
|
424
|
+
*
|
|
425
|
+
* @param cellID @ref rowindex "Row index" of the pivot.
|
|
426
|
+
* @return @ref MatIdx index of the column with the given pivot.
|
|
427
|
+
*/
|
|
428
|
+
Index get_column_with_pivot(ID_index cellID) const;
|
|
429
|
+
/**
|
|
430
|
+
* @brief Returns the @ref rowindex "row index" of the pivot of the given column.
|
|
431
|
+
*
|
|
432
|
+
* @param columnIndex @ref MatIdx index of the column
|
|
433
|
+
* @return The @ref rowindex "row index" of the pivot.
|
|
434
|
+
*/
|
|
435
|
+
ID_index get_pivot(Index columnIndex);
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @brief Resets the matrix to an empty matrix.
|
|
439
|
+
*
|
|
440
|
+
* @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
|
|
441
|
+
* the necessary external classes specifically necessary for the choosen column type, such as custom allocators.
|
|
442
|
+
*/
|
|
443
|
+
void reset(Column_settings* colSettings) {
|
|
444
|
+
matrix_.clear();
|
|
445
|
+
pivotToColumnIndex_.clear();
|
|
446
|
+
nextIndex_ = 0;
|
|
447
|
+
colSettings_ = colSettings;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @brief Assign operator.
|
|
452
|
+
*/
|
|
453
|
+
Chain_matrix& operator=(const Chain_matrix& other);
|
|
454
|
+
/**
|
|
455
|
+
* @brief Swap operator.
|
|
456
|
+
*/
|
|
457
|
+
friend void swap(Chain_matrix& matrix1, Chain_matrix& matrix2) {
|
|
458
|
+
swap(static_cast<typename Master_matrix::Matrix_dimension_option&>(matrix1),
|
|
459
|
+
static_cast<typename Master_matrix::Matrix_dimension_option&>(matrix2));
|
|
460
|
+
swap(static_cast<typename Master_matrix::Chain_pairing_option&>(matrix1),
|
|
461
|
+
static_cast<typename Master_matrix::Chain_pairing_option&>(matrix2));
|
|
462
|
+
swap(static_cast<typename Master_matrix::Chain_vine_swap_option&>(matrix1),
|
|
463
|
+
static_cast<typename Master_matrix::Chain_vine_swap_option&>(matrix2));
|
|
464
|
+
swap(static_cast<typename Master_matrix::Chain_representative_cycles_option&>(matrix1),
|
|
465
|
+
static_cast<typename Master_matrix::Chain_representative_cycles_option&>(matrix2));
|
|
466
|
+
matrix1.matrix_.swap(matrix2.matrix_);
|
|
467
|
+
matrix1.pivotToColumnIndex_.swap(matrix2.pivotToColumnIndex_);
|
|
468
|
+
std::swap(matrix1.nextIndex_, matrix2.nextIndex_);
|
|
469
|
+
std::swap(matrix1.colSettings_, matrix2.colSettings_);
|
|
470
|
+
|
|
471
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
472
|
+
swap(static_cast<typename Master_matrix::Matrix_row_access_option&>(matrix1),
|
|
473
|
+
static_cast<typename Master_matrix::Matrix_row_access_option&>(matrix2));
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
void print() const; // for debug
|
|
478
|
+
|
|
479
|
+
friend class Id_to_index_overlay<Chain_matrix<Master_matrix>, Master_matrix>;
|
|
480
|
+
|
|
481
|
+
private:
|
|
482
|
+
using Dim_opt = typename Master_matrix::Matrix_dimension_option;
|
|
483
|
+
using Swap_opt = typename Master_matrix::Chain_vine_swap_option;
|
|
484
|
+
using Pair_opt = typename Master_matrix::Chain_pairing_option;
|
|
485
|
+
using Rep_opt = typename Master_matrix::Chain_representative_cycles_option;
|
|
486
|
+
using RA_opt = typename Master_matrix::Matrix_row_access_option;
|
|
487
|
+
using Column_container = typename Master_matrix::Column_container;
|
|
488
|
+
using Dictionary = typename Master_matrix::template Dictionary<Index>;
|
|
489
|
+
using Barcode = typename Master_matrix::Barcode;
|
|
490
|
+
using Bar_dictionary = typename Master_matrix::Bar_dictionary;
|
|
491
|
+
using Tmp_column = typename std::conditional<Master_matrix::Option_list::is_z2,
|
|
492
|
+
std::set<ID_index>,
|
|
493
|
+
std::map<ID_index, Field_element>
|
|
494
|
+
>::type;
|
|
495
|
+
|
|
496
|
+
Column_container matrix_; /**< Column container. */
|
|
497
|
+
Dictionary pivotToColumnIndex_; /**< Map from @ref IDIdx to @ref MatIdx index. */
|
|
498
|
+
Index nextIndex_; /**< Next unused column index. */
|
|
499
|
+
Column_settings* colSettings_; /**< Entry factory. */
|
|
500
|
+
|
|
501
|
+
template <class Boundary_range>
|
|
502
|
+
std::vector<Entry_representative> _reduce_boundary(ID_index cellID, const Boundary_range& boundary, Dimension dim);
|
|
503
|
+
void _reduce_by_G(Tmp_column& column, std::vector<Entry_representative>& chainsInH, Index currentPivot);
|
|
504
|
+
void _reduce_by_F(Tmp_column& column, std::vector<Entry_representative>& chainsInF, Index currentPivot);
|
|
505
|
+
void _build_from_H(ID_index cellID, Tmp_column& column, std::vector<Entry_representative>& chainsInH);
|
|
506
|
+
void _update_largest_death_in_F(const std::vector<Entry_representative>& chainsInF);
|
|
507
|
+
void _insert_chain(const Tmp_column& column, Dimension dimension);
|
|
508
|
+
void _insert_chain(const Tmp_column& column, Dimension dimension, Index pair);
|
|
509
|
+
void _add_to(const Column& column, Tmp_column& set, unsigned int coef);
|
|
510
|
+
template <typename F>
|
|
511
|
+
void _add_to(Column& target, F&& addition);
|
|
512
|
+
void _remove_last(Index lastIndex);
|
|
513
|
+
void _update_barcode(Pos_index birth);
|
|
514
|
+
void _add_bar(Dimension dim);
|
|
515
|
+
template <class Container>
|
|
516
|
+
void _container_insert(const Container& column, Index pos, Dimension dim);
|
|
517
|
+
void _container_insert(const Column& column, [[maybe_unused]] Index pos = 0);
|
|
518
|
+
|
|
519
|
+
constexpr Barcode& _barcode();
|
|
520
|
+
constexpr Bar_dictionary& _indexToBar();
|
|
521
|
+
constexpr Pos_index& _nextPosition();
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
template <class Master_matrix>
|
|
525
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(Column_settings* colSettings)
|
|
526
|
+
: Dim_opt(-1),
|
|
527
|
+
Pair_opt(),
|
|
528
|
+
Swap_opt(),
|
|
529
|
+
Rep_opt(),
|
|
530
|
+
RA_opt(),
|
|
531
|
+
nextIndex_(0),
|
|
532
|
+
colSettings_(colSettings)
|
|
533
|
+
{}
|
|
534
|
+
|
|
535
|
+
template <class Master_matrix>
|
|
536
|
+
template <class Boundary_range>
|
|
537
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(const std::vector<Boundary_range>& orderedBoundaries,
|
|
538
|
+
Column_settings* colSettings)
|
|
539
|
+
: Dim_opt(-1),
|
|
540
|
+
Pair_opt(),
|
|
541
|
+
Swap_opt(),
|
|
542
|
+
Rep_opt(),
|
|
543
|
+
RA_opt(orderedBoundaries.size()),
|
|
544
|
+
nextIndex_(0),
|
|
545
|
+
colSettings_(colSettings)
|
|
546
|
+
{
|
|
547
|
+
matrix_.reserve(orderedBoundaries.size());
|
|
548
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
549
|
+
pivotToColumnIndex_.reserve(orderedBoundaries.size());
|
|
550
|
+
} else {
|
|
551
|
+
pivotToColumnIndex_.resize(orderedBoundaries.size(), -1);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
for (const Boundary_range& b : orderedBoundaries) {
|
|
555
|
+
insert_boundary(b);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
template <class Master_matrix>
|
|
560
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(unsigned int numberOfColumns,
|
|
561
|
+
Column_settings* colSettings)
|
|
562
|
+
: Dim_opt(-1),
|
|
563
|
+
Pair_opt(),
|
|
564
|
+
Swap_opt(),
|
|
565
|
+
Rep_opt(),
|
|
566
|
+
RA_opt(numberOfColumns),
|
|
567
|
+
nextIndex_(0),
|
|
568
|
+
colSettings_(colSettings)
|
|
569
|
+
{
|
|
570
|
+
matrix_.reserve(numberOfColumns);
|
|
571
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
572
|
+
pivotToColumnIndex_.reserve(numberOfColumns);
|
|
573
|
+
} else {
|
|
574
|
+
pivotToColumnIndex_.resize(numberOfColumns, -1);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
template <class Master_matrix>
|
|
579
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction>
|
|
580
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(Column_settings* colSettings,
|
|
581
|
+
const BirthComparatorFunction& birthComparator,
|
|
582
|
+
const DeathComparatorFunction& deathComparator)
|
|
583
|
+
: Dim_opt(-1),
|
|
584
|
+
Pair_opt(),
|
|
585
|
+
Swap_opt(birthComparator, deathComparator),
|
|
586
|
+
Rep_opt(),
|
|
587
|
+
RA_opt(),
|
|
588
|
+
nextIndex_(0),
|
|
589
|
+
colSettings_(colSettings)
|
|
590
|
+
{}
|
|
591
|
+
|
|
592
|
+
template <class Master_matrix>
|
|
593
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction, class Boundary_range>
|
|
594
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(const std::vector<Boundary_range>& orderedBoundaries,
|
|
595
|
+
Column_settings* colSettings,
|
|
596
|
+
const BirthComparatorFunction& birthComparator,
|
|
597
|
+
const DeathComparatorFunction& deathComparator)
|
|
598
|
+
: Dim_opt(-1),
|
|
599
|
+
Pair_opt(),
|
|
600
|
+
Swap_opt(birthComparator, deathComparator),
|
|
601
|
+
Rep_opt(),
|
|
602
|
+
RA_opt(orderedBoundaries.size()),
|
|
603
|
+
nextIndex_(0),
|
|
604
|
+
colSettings_(colSettings)
|
|
605
|
+
{
|
|
606
|
+
matrix_.reserve(orderedBoundaries.size());
|
|
607
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
608
|
+
pivotToColumnIndex_.reserve(orderedBoundaries.size());
|
|
609
|
+
} else {
|
|
610
|
+
pivotToColumnIndex_.resize(orderedBoundaries.size(), -1);
|
|
611
|
+
}
|
|
612
|
+
for (const Boundary_range& b : orderedBoundaries) {
|
|
613
|
+
insert_boundary(b);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
template <class Master_matrix>
|
|
618
|
+
template <typename BirthComparatorFunction, typename DeathComparatorFunction>
|
|
619
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(unsigned int numberOfColumns,
|
|
620
|
+
Column_settings* colSettings,
|
|
621
|
+
const BirthComparatorFunction& birthComparator,
|
|
622
|
+
const DeathComparatorFunction& deathComparator)
|
|
623
|
+
: Dim_opt(-1),
|
|
624
|
+
Pair_opt(),
|
|
625
|
+
Swap_opt(birthComparator, deathComparator),
|
|
626
|
+
Rep_opt(),
|
|
627
|
+
RA_opt(numberOfColumns),
|
|
628
|
+
nextIndex_(0),
|
|
629
|
+
colSettings_(colSettings)
|
|
630
|
+
{
|
|
631
|
+
matrix_.reserve(numberOfColumns);
|
|
632
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
633
|
+
pivotToColumnIndex_.reserve(numberOfColumns);
|
|
634
|
+
} else {
|
|
635
|
+
pivotToColumnIndex_.resize(numberOfColumns, -1);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
template <class Master_matrix>
|
|
640
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(const Chain_matrix& matrixToCopy, Column_settings* colSettings)
|
|
641
|
+
: Dim_opt(static_cast<const Dim_opt&>(matrixToCopy)),
|
|
642
|
+
Pair_opt(static_cast<const Pair_opt&>(matrixToCopy)),
|
|
643
|
+
Swap_opt(static_cast<const Swap_opt&>(matrixToCopy)),
|
|
644
|
+
Rep_opt(static_cast<const Rep_opt&>(matrixToCopy)),
|
|
645
|
+
RA_opt(static_cast<const RA_opt&>(matrixToCopy)),
|
|
646
|
+
pivotToColumnIndex_(matrixToCopy.pivotToColumnIndex_),
|
|
647
|
+
nextIndex_(matrixToCopy.nextIndex_),
|
|
648
|
+
colSettings_(colSettings == nullptr ? matrixToCopy.colSettings_ : colSettings)
|
|
649
|
+
{
|
|
650
|
+
matrix_.reserve(matrixToCopy.matrix_.size());
|
|
651
|
+
for (const auto& cont : matrixToCopy.matrix_){
|
|
652
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container){
|
|
653
|
+
_container_insert(cont.second, cont.first);
|
|
654
|
+
} else {
|
|
655
|
+
_container_insert(cont);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
template <class Master_matrix>
|
|
661
|
+
inline Chain_matrix<Master_matrix>::Chain_matrix(Chain_matrix&& other) noexcept
|
|
662
|
+
: Dim_opt(std::move(static_cast<Dim_opt&>(other))),
|
|
663
|
+
Pair_opt(std::move(static_cast<Pair_opt&>(other))),
|
|
664
|
+
Swap_opt(std::move(static_cast<Swap_opt&>(other))),
|
|
665
|
+
Rep_opt(std::move(static_cast<Rep_opt&>(other))),
|
|
666
|
+
RA_opt(std::move(static_cast<RA_opt&>(other))),
|
|
667
|
+
matrix_(std::move(other.matrix_)),
|
|
668
|
+
pivotToColumnIndex_(std::move(other.pivotToColumnIndex_)),
|
|
669
|
+
nextIndex_(std::exchange(other.nextIndex_, 0)),
|
|
670
|
+
colSettings_(std::exchange(other.colSettings_, nullptr))
|
|
671
|
+
{}
|
|
672
|
+
|
|
673
|
+
template <class Master_matrix>
|
|
674
|
+
template <class Boundary_range>
|
|
675
|
+
inline std::vector<typename Master_matrix::Entry_representative> Chain_matrix<Master_matrix>::insert_boundary(
|
|
676
|
+
const Boundary_range& boundary, Dimension dim)
|
|
677
|
+
{
|
|
678
|
+
return insert_boundary(nextIndex_, boundary, dim);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
template <class Master_matrix>
|
|
682
|
+
template <class Boundary_range>
|
|
683
|
+
inline std::vector<typename Master_matrix::Entry_representative> Chain_matrix<Master_matrix>::insert_boundary(
|
|
684
|
+
ID_index cellID, const Boundary_range& boundary, Dimension dim)
|
|
685
|
+
{
|
|
686
|
+
if constexpr (!Master_matrix::Option_list::has_map_column_container) {
|
|
687
|
+
if (pivotToColumnIndex_.size() <= cellID) {
|
|
688
|
+
pivotToColumnIndex_.resize(cellID * 2 + 1, -1);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if constexpr (Master_matrix::Option_list::has_vine_update && Master_matrix::Option_list::has_column_pairings) {
|
|
693
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
694
|
+
Swap_opt::CP::pivotToPosition_.try_emplace(cellID, _nextPosition());
|
|
695
|
+
} else {
|
|
696
|
+
if (Swap_opt::CP::pivotToPosition_.size() <= cellID)
|
|
697
|
+
Swap_opt::CP::pivotToPosition_.resize(pivotToColumnIndex_.size(), -1);
|
|
698
|
+
Swap_opt::CP::pivotToPosition_[cellID] = _nextPosition();
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if constexpr (Master_matrix::Option_list::has_matrix_maximal_dimension_access) {
|
|
703
|
+
Dim_opt::update_up(dim == static_cast<Dimension>(-1) ? (boundary.size() == 0 ? 0 : boundary.size() - 1) : dim);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
return _reduce_boundary(cellID, boundary, dim);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
template <class Master_matrix>
|
|
710
|
+
inline typename Chain_matrix<Master_matrix>::Column& Chain_matrix<Master_matrix>::get_column(Index columnIndex)
|
|
711
|
+
{
|
|
712
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
713
|
+
return matrix_.at(columnIndex);
|
|
714
|
+
} else {
|
|
715
|
+
return matrix_[columnIndex];
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
template <class Master_matrix>
|
|
720
|
+
inline const typename Chain_matrix<Master_matrix>::Column& Chain_matrix<Master_matrix>::get_column(
|
|
721
|
+
Index columnIndex) const
|
|
722
|
+
{
|
|
723
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
724
|
+
return matrix_.at(columnIndex);
|
|
725
|
+
} else {
|
|
726
|
+
return matrix_[columnIndex];
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
template <class Master_matrix>
|
|
731
|
+
inline void Chain_matrix<Master_matrix>::remove_maximal_cell(ID_index cellID)
|
|
732
|
+
{
|
|
733
|
+
static_assert(Master_matrix::Option_list::has_removable_columns,
|
|
734
|
+
"'remove_maximal_cell' is not implemented for the chosen options.");
|
|
735
|
+
static_assert(Master_matrix::Option_list::has_map_column_container &&
|
|
736
|
+
Master_matrix::Option_list::has_vine_update &&
|
|
737
|
+
Master_matrix::Option_list::has_column_pairings,
|
|
738
|
+
"'remove_maximal_cell' is not implemented for the chosen options.");
|
|
739
|
+
|
|
740
|
+
// TODO: find simple test to verify that col at columnIndex is maximal even without row access.
|
|
741
|
+
|
|
742
|
+
const auto& pivotToPosition = Swap_opt::CP::pivotToPosition_;
|
|
743
|
+
auto it = pivotToPosition.find(cellID);
|
|
744
|
+
if (it == pivotToPosition.end()) return; // cell does not exists. TODO: put an assert instead?
|
|
745
|
+
Pos_index startPos = it->second;
|
|
746
|
+
Index startIndex = pivotToColumnIndex_.at(cellID);
|
|
747
|
+
|
|
748
|
+
if (startPos != _nextPosition() - 1) {
|
|
749
|
+
std::vector<Index> colToSwap;
|
|
750
|
+
colToSwap.reserve(matrix_.size());
|
|
751
|
+
|
|
752
|
+
for (auto& p : pivotToPosition) {
|
|
753
|
+
if (p.second > startPos) colToSwap.push_back(pivotToColumnIndex_.at(p.first));
|
|
754
|
+
}
|
|
755
|
+
std::sort(colToSwap.begin(), colToSwap.end(), [&](Index c1, Index c2) {
|
|
756
|
+
return pivotToPosition.at(get_pivot(c1)) < pivotToPosition.at(get_pivot(c2));
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
for (Index i : colToSwap) {
|
|
760
|
+
startIndex = Swap_opt::vine_swap(startIndex, i);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
_remove_last(startIndex);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
template <class Master_matrix>
|
|
768
|
+
inline void Chain_matrix<Master_matrix>::remove_maximal_cell(ID_index cellID,
|
|
769
|
+
const std::vector<ID_index>& columnsToSwap)
|
|
770
|
+
{
|
|
771
|
+
static_assert(Master_matrix::Option_list::has_removable_columns,
|
|
772
|
+
"'remove_maximal_cell' is not implemented for the chosen options.");
|
|
773
|
+
static_assert(Master_matrix::Option_list::has_map_column_container && Master_matrix::Option_list::has_vine_update,
|
|
774
|
+
"'remove_maximal_cell' is not implemented for the chosen options.");
|
|
775
|
+
|
|
776
|
+
// TODO: find simple test to verify that col at columnIndex is maximal even without row access.
|
|
777
|
+
|
|
778
|
+
Index startIndex = pivotToColumnIndex_.at(cellID);
|
|
779
|
+
|
|
780
|
+
for (ID_index i : columnsToSwap) {
|
|
781
|
+
startIndex = Swap_opt::vine_swap(startIndex, pivotToColumnIndex_.at(i));
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
_remove_last(startIndex);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
template <class Master_matrix>
|
|
788
|
+
inline void Chain_matrix<Master_matrix>::remove_last()
|
|
789
|
+
{
|
|
790
|
+
static_assert(Master_matrix::Option_list::has_removable_columns,
|
|
791
|
+
"'remove_last' is not implemented for the chosen options.");
|
|
792
|
+
static_assert(Master_matrix::Option_list::has_map_column_container || !Master_matrix::Option_list::has_vine_update,
|
|
793
|
+
"'remove_last' is not implemented for the chosen options.");
|
|
794
|
+
|
|
795
|
+
if (nextIndex_ == 0 || matrix_.empty()) return; // empty matrix
|
|
796
|
+
|
|
797
|
+
if constexpr (Master_matrix::Option_list::has_vine_update) {
|
|
798
|
+
// careful: linear because of the search of the last index. It is better to keep track of the @ref IDIdx index
|
|
799
|
+
// of the last column while performing swaps (or the @ref MatIdx with the return values of `vine_swap` + get_pivot)
|
|
800
|
+
// and then call `remove_maximal_cell` with it and an empty `columnsToSwap`.
|
|
801
|
+
|
|
802
|
+
ID_index pivot = 0;
|
|
803
|
+
Index colIndex = 0;
|
|
804
|
+
for (auto& p : pivotToColumnIndex_) {
|
|
805
|
+
if (p.first > pivot) { // pivots have to be strictly increasing in order of filtration
|
|
806
|
+
pivot = p.first;
|
|
807
|
+
colIndex = p.second;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
_remove_last(colIndex);
|
|
811
|
+
} else {
|
|
812
|
+
_remove_last(nextIndex_ - 1);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
template <class Master_matrix>
|
|
817
|
+
inline typename Chain_matrix<Master_matrix>::Index Chain_matrix<Master_matrix>::get_number_of_columns() const
|
|
818
|
+
{
|
|
819
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
820
|
+
return matrix_.size();
|
|
821
|
+
} else {
|
|
822
|
+
return nextIndex_; // matrix could have been resized much bigger while insert
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
template <class Master_matrix>
|
|
827
|
+
inline typename Chain_matrix<Master_matrix>::Dimension Chain_matrix<Master_matrix>::get_column_dimension(
|
|
828
|
+
Index columnIndex) const
|
|
829
|
+
{
|
|
830
|
+
return get_column(columnIndex).get_dimension();
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
template <class Master_matrix>
|
|
834
|
+
inline void Chain_matrix<Master_matrix>::add_to(Index sourceColumnIndex, Index targetColumnIndex)
|
|
835
|
+
{
|
|
836
|
+
auto& col = get_column(targetColumnIndex);
|
|
837
|
+
_add_to(col, [&]() { col += get_column(sourceColumnIndex); });
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
template <class Master_matrix>
|
|
841
|
+
inline void Chain_matrix<Master_matrix>::multiply_target_and_add_to(Index sourceColumnIndex,
|
|
842
|
+
const Field_element& coefficient,
|
|
843
|
+
Index targetColumnIndex)
|
|
844
|
+
{
|
|
845
|
+
auto& col = get_column(targetColumnIndex);
|
|
846
|
+
_add_to(col, [&]() { col.multiply_target_and_add(coefficient, get_column(sourceColumnIndex)); });
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
template <class Master_matrix>
|
|
850
|
+
inline void Chain_matrix<Master_matrix>::multiply_source_and_add_to(const Field_element& coefficient,
|
|
851
|
+
Index sourceColumnIndex,
|
|
852
|
+
Index targetColumnIndex)
|
|
853
|
+
{
|
|
854
|
+
auto& col = get_column(targetColumnIndex);
|
|
855
|
+
_add_to(col, [&]() { col.multiply_source_and_add(get_column(sourceColumnIndex), coefficient); });
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
template <class Master_matrix>
|
|
859
|
+
inline bool Chain_matrix<Master_matrix>::is_zero_entry(Index columnIndex, ID_index rowIndex) const
|
|
860
|
+
{
|
|
861
|
+
return !get_column(columnIndex).is_non_zero(rowIndex);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
template <class Master_matrix>
|
|
865
|
+
inline bool Chain_matrix<Master_matrix>::is_zero_column(Index columnIndex)
|
|
866
|
+
{
|
|
867
|
+
return get_column(columnIndex).is_empty();
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
template <class Master_matrix>
|
|
871
|
+
inline typename Chain_matrix<Master_matrix>::Index Chain_matrix<Master_matrix>::get_column_with_pivot(
|
|
872
|
+
ID_index cellID) const
|
|
873
|
+
{
|
|
874
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
875
|
+
return pivotToColumnIndex_.at(cellID);
|
|
876
|
+
} else {
|
|
877
|
+
return pivotToColumnIndex_[cellID];
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
template <class Master_matrix>
|
|
882
|
+
inline typename Chain_matrix<Master_matrix>::ID_index Chain_matrix<Master_matrix>::get_pivot(Index columnIndex)
|
|
883
|
+
{
|
|
884
|
+
return get_column(columnIndex).get_pivot();
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
template <class Master_matrix>
|
|
888
|
+
inline Chain_matrix<Master_matrix>& Chain_matrix<Master_matrix>::operator=(const Chain_matrix& other)
|
|
889
|
+
{
|
|
890
|
+
Dim_opt::operator=(other);
|
|
891
|
+
Swap_opt::operator=(other);
|
|
892
|
+
Pair_opt::operator=(other);
|
|
893
|
+
Rep_opt::operator=(other);
|
|
894
|
+
matrix_.clear();
|
|
895
|
+
pivotToColumnIndex_ = other.pivotToColumnIndex_;
|
|
896
|
+
nextIndex_ = other.nextIndex_;
|
|
897
|
+
colSettings_ = other.colSettings_;
|
|
898
|
+
|
|
899
|
+
matrix_.reserve(other.matrix_.size());
|
|
900
|
+
for (const auto& cont : other.matrix_){
|
|
901
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container){
|
|
902
|
+
_container_insert(cont.second, cont.first);
|
|
903
|
+
} else {
|
|
904
|
+
_container_insert(cont);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
return *this;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
template <class Master_matrix>
|
|
912
|
+
inline void Chain_matrix<Master_matrix>::print() const
|
|
913
|
+
{
|
|
914
|
+
std::cout << "Column Matrix:\n";
|
|
915
|
+
if constexpr (!Master_matrix::Option_list::has_map_column_container) {
|
|
916
|
+
for (ID_index i = 0; i < pivotToColumnIndex_.size() && pivotToColumnIndex_[i] != static_cast<Index>(-1); ++i) {
|
|
917
|
+
Index pos = pivotToColumnIndex_[i];
|
|
918
|
+
const Column& col = matrix_[pos];
|
|
919
|
+
for (const auto& entry : col) {
|
|
920
|
+
std::cout << entry.get_row_index() << " ";
|
|
921
|
+
}
|
|
922
|
+
std::cout << "(" << i << ", " << pos << ")\n";
|
|
923
|
+
}
|
|
924
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
925
|
+
std::cout << "\n";
|
|
926
|
+
std::cout << "Row Matrix:\n";
|
|
927
|
+
for (ID_index i = 0; i < pivotToColumnIndex_.size() && pivotToColumnIndex_[i] != static_cast<Index>(-1); ++i) {
|
|
928
|
+
Index pos = pivotToColumnIndex_[i];
|
|
929
|
+
const Row& row = RA_opt::get_row(pos);
|
|
930
|
+
for (const auto& entry : row) {
|
|
931
|
+
std::cout << entry.get_column_index() << " ";
|
|
932
|
+
}
|
|
933
|
+
std::cout << "(" << i << ", " << pos << ")\n";
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
} else {
|
|
937
|
+
for (const auto& p : pivotToColumnIndex_) {
|
|
938
|
+
const Column& col = matrix_.at(p.second);
|
|
939
|
+
for (const auto& entry : col) {
|
|
940
|
+
std::cout << entry.get_row_index() << " ";
|
|
941
|
+
}
|
|
942
|
+
std::cout << "(" << p.first << ", " << p.second << ")\n";
|
|
943
|
+
}
|
|
944
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
945
|
+
std::cout << "\n";
|
|
946
|
+
std::cout << "Row Matrix:\n";
|
|
947
|
+
for (const auto& p : pivotToColumnIndex_) {
|
|
948
|
+
const Row& row = RA_opt::get_row(p.first);
|
|
949
|
+
for (const auto& entry : row) {
|
|
950
|
+
std::cout << entry.get_column_index() << " ";
|
|
951
|
+
}
|
|
952
|
+
std::cout << "(" << p.first << ", " << p.second << ")\n";
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
std::cout << "\n";
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
template <class Master_matrix>
|
|
960
|
+
template <class Boundary_range>
|
|
961
|
+
inline std::vector<typename Master_matrix::Entry_representative> Chain_matrix<Master_matrix>::_reduce_boundary(
|
|
962
|
+
ID_index cellID, const Boundary_range& boundary, Dimension dim)
|
|
963
|
+
{
|
|
964
|
+
Tmp_column column(boundary.begin(), boundary.end());
|
|
965
|
+
if (dim == static_cast<Dimension>(-1)) dim = boundary.begin() == boundary.end() ? 0 : boundary.size() - 1;
|
|
966
|
+
std::vector<Entry_representative> chainsInH; // for corresponding indices in H (paired columns)
|
|
967
|
+
std::vector<Entry_representative> chainsInF; // for corresponding indices in F (unpaired, essential columns)
|
|
968
|
+
|
|
969
|
+
auto get_last = [&column]() {
|
|
970
|
+
if constexpr (Master_matrix::Option_list::is_z2)
|
|
971
|
+
return *(column.rbegin());
|
|
972
|
+
else
|
|
973
|
+
return column.rbegin()->first;
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
if (boundary.begin() == boundary.end()) {
|
|
977
|
+
if constexpr (Master_matrix::Option_list::is_z2)
|
|
978
|
+
column.insert(cellID);
|
|
979
|
+
else
|
|
980
|
+
column.emplace(cellID, 1);
|
|
981
|
+
_insert_chain(column, dim);
|
|
982
|
+
return chainsInF;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
Index currentIndex = get_column_with_pivot(get_last());
|
|
986
|
+
|
|
987
|
+
while (get_column(currentIndex).is_paired()) {
|
|
988
|
+
_reduce_by_G(column, chainsInH, currentIndex);
|
|
989
|
+
|
|
990
|
+
if (column.empty()) {
|
|
991
|
+
// produce the sum of all col_h in chains_in_H
|
|
992
|
+
_build_from_H(cellID, column, chainsInH);
|
|
993
|
+
// create a new cycle (in F) sigma - \sum col_h
|
|
994
|
+
_insert_chain(column, dim);
|
|
995
|
+
return chainsInF;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
currentIndex = get_column_with_pivot(get_last());
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
while (!column.empty()) {
|
|
1002
|
+
currentIndex = get_column_with_pivot(get_last());
|
|
1003
|
+
|
|
1004
|
+
if (!get_column(currentIndex).is_paired()) {
|
|
1005
|
+
// only fills currentEssentialCycleIndices if Z2 coefficients, so chainsInF remains empty
|
|
1006
|
+
_reduce_by_F(column, chainsInF, currentIndex);
|
|
1007
|
+
} else {
|
|
1008
|
+
_reduce_by_G(column, chainsInH, currentIndex);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
_update_largest_death_in_F(chainsInF);
|
|
1013
|
+
|
|
1014
|
+
// Compute the new column cellID + \sum col_h, for col_h in chains_in_H
|
|
1015
|
+
_build_from_H(cellID, column, chainsInH);
|
|
1016
|
+
|
|
1017
|
+
// Create and insert (\sum col_h) + sigma (in H, paired with chain_fp) in matrix_
|
|
1018
|
+
if constexpr (Master_matrix::Option_list::is_z2)
|
|
1019
|
+
_insert_chain(column, dim, chainsInF[0]);
|
|
1020
|
+
else
|
|
1021
|
+
_insert_chain(column, dim, chainsInF[0].first);
|
|
1022
|
+
|
|
1023
|
+
return chainsInF;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
template <class Master_matrix>
|
|
1027
|
+
inline void Chain_matrix<Master_matrix>::_reduce_by_G(Tmp_column& column,
|
|
1028
|
+
std::vector<Entry_representative>& chainsInH,
|
|
1029
|
+
Index currentIndex)
|
|
1030
|
+
{
|
|
1031
|
+
Column& col = get_column(currentIndex);
|
|
1032
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1033
|
+
_add_to(col, column, 1u); // Reduce with the column col_g
|
|
1034
|
+
chainsInH.push_back(col.get_paired_chain_index()); // keep the col_h with which col_g is paired
|
|
1035
|
+
} else {
|
|
1036
|
+
Field_element coef = col.get_pivot_value();
|
|
1037
|
+
auto& operators = colSettings_->operators;
|
|
1038
|
+
coef = operators.get_inverse(coef);
|
|
1039
|
+
operators.multiply_inplace(coef, operators.get_characteristic() - column.rbegin()->second);
|
|
1040
|
+
|
|
1041
|
+
_add_to(col, column, coef); // Reduce with the column col_g
|
|
1042
|
+
chainsInH.emplace_back(col.get_paired_chain_index(), coef); // keep the col_h with which col_g is paired
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
template <class Master_matrix>
|
|
1047
|
+
inline void Chain_matrix<Master_matrix>::_reduce_by_F(Tmp_column& column,
|
|
1048
|
+
std::vector<Entry_representative>& chainsInF,
|
|
1049
|
+
Index currentIndex)
|
|
1050
|
+
{
|
|
1051
|
+
Column& col = get_column(currentIndex);
|
|
1052
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1053
|
+
_add_to(col, column, 1u); // Reduce with the column col_g
|
|
1054
|
+
chainsInF.push_back(currentIndex);
|
|
1055
|
+
} else {
|
|
1056
|
+
Field_element coef = col.get_pivot_value();
|
|
1057
|
+
auto& operators = colSettings_->operators;
|
|
1058
|
+
coef = operators.get_inverse(coef);
|
|
1059
|
+
operators.multiply_inplace(coef, operators.get_characteristic() - column.rbegin()->second);
|
|
1060
|
+
|
|
1061
|
+
_add_to(col, column, coef); // Reduce with the column col_g
|
|
1062
|
+
chainsInF.emplace_back(currentIndex, operators.get_characteristic() - coef);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
template <class Master_matrix>
|
|
1067
|
+
inline void Chain_matrix<Master_matrix>::_build_from_H(ID_index cellID,
|
|
1068
|
+
Tmp_column& column,
|
|
1069
|
+
std::vector<Entry_representative>& chainsInH)
|
|
1070
|
+
{
|
|
1071
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1072
|
+
column.insert(cellID);
|
|
1073
|
+
for (Index idx_h : chainsInH) {
|
|
1074
|
+
_add_to(get_column(idx_h), column, 1u);
|
|
1075
|
+
}
|
|
1076
|
+
} else {
|
|
1077
|
+
column.emplace(cellID, 1);
|
|
1078
|
+
for (std::pair<Index, Field_element>& idx_h : chainsInH) {
|
|
1079
|
+
_add_to(get_column(idx_h.first), column, idx_h.second);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
template <class Master_matrix>
|
|
1085
|
+
inline void Chain_matrix<Master_matrix>::_update_largest_death_in_F(const std::vector<Entry_representative>& chainsInF)
|
|
1086
|
+
{
|
|
1087
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1088
|
+
Index toUpdate = chainsInF[0];
|
|
1089
|
+
for (auto other_col_it = chainsInF.begin() + 1; other_col_it != chainsInF.end(); ++other_col_it) {
|
|
1090
|
+
add_to(*other_col_it, toUpdate);
|
|
1091
|
+
}
|
|
1092
|
+
} else {
|
|
1093
|
+
Index toUpdate = chainsInF[0].first;
|
|
1094
|
+
get_column(toUpdate) *= chainsInF[0].second;
|
|
1095
|
+
for (auto other_col_it = chainsInF.begin() + 1; other_col_it != chainsInF.end(); ++other_col_it) {
|
|
1096
|
+
multiply_source_and_add_to(other_col_it->second, other_col_it->first, toUpdate);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
template <class Master_matrix>
|
|
1102
|
+
inline void Chain_matrix<Master_matrix>::_insert_chain(const Tmp_column& column, Dimension dimension)
|
|
1103
|
+
{
|
|
1104
|
+
_container_insert(column, nextIndex_, dimension);
|
|
1105
|
+
_add_bar(dimension);
|
|
1106
|
+
|
|
1107
|
+
++nextIndex_;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
template <class Master_matrix>
|
|
1111
|
+
inline void Chain_matrix<Master_matrix>::_insert_chain(const Tmp_column& column, Dimension dimension, Index pair)
|
|
1112
|
+
{
|
|
1113
|
+
// true when no vine updates and if nextIndex_ is updated in remove_last for special case of no vines
|
|
1114
|
+
// because then @ref PosIdx == @ref MatIdx
|
|
1115
|
+
Pos_index pairPos = pair;
|
|
1116
|
+
|
|
1117
|
+
_container_insert(column, nextIndex_, dimension);
|
|
1118
|
+
|
|
1119
|
+
get_column(nextIndex_).assign_paired_chain(pair);
|
|
1120
|
+
auto& pairCol = get_column(pair);
|
|
1121
|
+
pairCol.assign_paired_chain(nextIndex_);
|
|
1122
|
+
|
|
1123
|
+
if constexpr (Master_matrix::Option_list::has_column_pairings && Master_matrix::Option_list::has_vine_update) {
|
|
1124
|
+
pairPos = Swap_opt::CP::pivotToPosition_[pairCol.get_pivot()];
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
_update_barcode(pairPos);
|
|
1128
|
+
|
|
1129
|
+
++nextIndex_;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
template <class Master_matrix>
|
|
1133
|
+
inline void Chain_matrix<Master_matrix>::_add_to(const Column& column,
|
|
1134
|
+
Tmp_column& set,
|
|
1135
|
+
[[maybe_unused]] unsigned int coef)
|
|
1136
|
+
{
|
|
1137
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1138
|
+
std::pair<typename std::set<Index>::iterator, bool> res_insert;
|
|
1139
|
+
for (const Entry& entry : column) {
|
|
1140
|
+
res_insert = set.insert(entry.get_row_index());
|
|
1141
|
+
if (!res_insert.second) {
|
|
1142
|
+
set.erase(res_insert.first);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
} else {
|
|
1146
|
+
auto& operators = colSettings_->operators;
|
|
1147
|
+
for (const Entry& entry : column) {
|
|
1148
|
+
auto res = set.emplace(entry.get_row_index(), entry.get_element());
|
|
1149
|
+
if (res.second){
|
|
1150
|
+
operators.multiply_inplace(res.first->second, coef);
|
|
1151
|
+
} else {
|
|
1152
|
+
operators.multiply_and_add_inplace_back(entry.get_element(), coef, res.first->second);
|
|
1153
|
+
if (res.first->second == Field_operators::get_additive_identity()) {
|
|
1154
|
+
set.erase(res.first);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
template <class Master_matrix>
|
|
1162
|
+
template <typename F>
|
|
1163
|
+
inline void Chain_matrix<Master_matrix>::_add_to(Column& target, F&& addition)
|
|
1164
|
+
{
|
|
1165
|
+
auto pivot = target.get_pivot();
|
|
1166
|
+
addition();
|
|
1167
|
+
|
|
1168
|
+
if (pivot != target.get_pivot()) {
|
|
1169
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
1170
|
+
std::swap(pivotToColumnIndex_.at(pivot), pivotToColumnIndex_.at(target.get_pivot()));
|
|
1171
|
+
} else {
|
|
1172
|
+
std::swap(pivotToColumnIndex_[pivot], pivotToColumnIndex_[target.get_pivot()]);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
template <class Master_matrix>
|
|
1178
|
+
inline void Chain_matrix<Master_matrix>::_remove_last(Index lastIndex)
|
|
1179
|
+
{
|
|
1180
|
+
static_assert(Master_matrix::Option_list::has_removable_columns,
|
|
1181
|
+
"'_remove_last' is not implemented for the chosen options.");
|
|
1182
|
+
static_assert(Master_matrix::Option_list::has_map_column_container || !Master_matrix::Option_list::has_vine_update,
|
|
1183
|
+
"'_remove_last' is not implemented for the chosen options.");
|
|
1184
|
+
|
|
1185
|
+
ID_index pivot;
|
|
1186
|
+
|
|
1187
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
1188
|
+
auto itToErase = matrix_.find(lastIndex);
|
|
1189
|
+
Column& colToErase = itToErase->second;
|
|
1190
|
+
pivot = colToErase.get_pivot();
|
|
1191
|
+
|
|
1192
|
+
if constexpr (Master_matrix::Option_list::has_matrix_maximal_dimension_access) {
|
|
1193
|
+
Dim_opt::update_down(colToErase.get_dimension());
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
if (colToErase.is_paired()) matrix_.at(colToErase.get_paired_chain_index()).unassign_paired_chain();
|
|
1197
|
+
pivotToColumnIndex_.erase(pivot);
|
|
1198
|
+
matrix_.erase(itToErase);
|
|
1199
|
+
} else {
|
|
1200
|
+
GUDHI_CHECK(lastIndex == nextIndex_ - 1 && nextIndex_ == matrix_.size(),
|
|
1201
|
+
std::logic_error("Chain_matrix::_remove_last - Indexation problem."));
|
|
1202
|
+
|
|
1203
|
+
Column& colToErase = matrix_[lastIndex];
|
|
1204
|
+
pivot = colToErase.get_pivot();
|
|
1205
|
+
|
|
1206
|
+
if constexpr (Master_matrix::Option_list::has_matrix_maximal_dimension_access) {
|
|
1207
|
+
Dim_opt::update_down(colToErase.get_dimension());
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
if (colToErase.is_paired()) matrix_.at(colToErase.get_paired_chain_index()).unassign_paired_chain();
|
|
1211
|
+
pivotToColumnIndex_[pivot] = -1;
|
|
1212
|
+
matrix_.pop_back();
|
|
1213
|
+
// TODO: resize matrix_ when a lot is removed? Could be not the best strategy if user inserts a lot back afterwards.
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
if constexpr (!Master_matrix::Option_list::has_vine_update) {
|
|
1217
|
+
--nextIndex_; // should not be updated when there are vine updates, as possibly lastIndex != nextIndex - 1
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
if constexpr (Master_matrix::Option_list::has_column_pairings) {
|
|
1221
|
+
auto it = _indexToBar().find(--_nextPosition());
|
|
1222
|
+
typename Barcode::iterator bar = it->second;
|
|
1223
|
+
|
|
1224
|
+
if (bar->death == static_cast<Pos_index>(-1))
|
|
1225
|
+
_barcode().erase(bar);
|
|
1226
|
+
else
|
|
1227
|
+
bar->death = -1;
|
|
1228
|
+
|
|
1229
|
+
_indexToBar().erase(it);
|
|
1230
|
+
if constexpr (Master_matrix::Option_list::has_vine_update) Swap_opt::CP::pivotToPosition_.erase(pivot);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
1234
|
+
GUDHI_CHECK(
|
|
1235
|
+
RA_opt::get_row(pivot).size() == 0,
|
|
1236
|
+
std::invalid_argument(
|
|
1237
|
+
"Chain_matrix::_remove_last - Column asked to be removed does not corresponds to a maximal simplex."));
|
|
1238
|
+
if constexpr (Master_matrix::Option_list::has_removable_rows) {
|
|
1239
|
+
RA_opt::erase_empty_row(pivot);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
template <class Master_matrix>
|
|
1245
|
+
inline void Chain_matrix<Master_matrix>::_update_barcode(Pos_index birth)
|
|
1246
|
+
{
|
|
1247
|
+
if constexpr (Master_matrix::Option_list::has_column_pairings) {
|
|
1248
|
+
if constexpr (Master_matrix::Option_list::has_removable_columns) {
|
|
1249
|
+
auto& barIt = _indexToBar().at(birth);
|
|
1250
|
+
barIt->death = _nextPosition();
|
|
1251
|
+
_indexToBar().try_emplace(_nextPosition(), barIt); // list so iterators are stable
|
|
1252
|
+
} else {
|
|
1253
|
+
_barcode()[_indexToBar()[birth]].death = _nextPosition();
|
|
1254
|
+
_indexToBar().push_back(_indexToBar()[birth]);
|
|
1255
|
+
}
|
|
1256
|
+
++_nextPosition();
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
template <class Master_matrix>
|
|
1261
|
+
inline void Chain_matrix<Master_matrix>::_add_bar(Dimension dim)
|
|
1262
|
+
{
|
|
1263
|
+
if constexpr (Master_matrix::Option_list::has_column_pairings) {
|
|
1264
|
+
_barcode().emplace_back(_nextPosition(), -1, dim);
|
|
1265
|
+
if constexpr (Master_matrix::Option_list::has_removable_columns) {
|
|
1266
|
+
_indexToBar().try_emplace(_nextPosition(), --_barcode().end());
|
|
1267
|
+
} else {
|
|
1268
|
+
_indexToBar().push_back(_barcode().size() - 1);
|
|
1269
|
+
}
|
|
1270
|
+
++_nextPosition();
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
template <class Master_matrix>
|
|
1275
|
+
template <class Container>
|
|
1276
|
+
inline void Chain_matrix<Master_matrix>::_container_insert(const Container& column, Index pos, Dimension dim)
|
|
1277
|
+
{
|
|
1278
|
+
ID_index pivot;
|
|
1279
|
+
if constexpr (Master_matrix::Option_list::is_z2) {
|
|
1280
|
+
pivot = *(column.rbegin());
|
|
1281
|
+
} else {
|
|
1282
|
+
pivot = column.rbegin()->first;
|
|
1283
|
+
}
|
|
1284
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
1285
|
+
pivotToColumnIndex_.try_emplace(pivot, pos);
|
|
1286
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
1287
|
+
matrix_.try_emplace(pos, Column(pos, column, dim, RA_opt::rows_, colSettings_));
|
|
1288
|
+
} else {
|
|
1289
|
+
matrix_.try_emplace(pos, Column(column, dim, colSettings_));
|
|
1290
|
+
}
|
|
1291
|
+
} else {
|
|
1292
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
1293
|
+
matrix_.emplace_back(pos, column, dim, RA_opt::rows_, colSettings_);
|
|
1294
|
+
} else {
|
|
1295
|
+
matrix_.emplace_back(column, dim, colSettings_);
|
|
1296
|
+
}
|
|
1297
|
+
pivotToColumnIndex_[pivot] = pos;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
template <class Master_matrix>
|
|
1302
|
+
inline void Chain_matrix<Master_matrix>::_container_insert(const Column& column, [[maybe_unused]] Index pos)
|
|
1303
|
+
{
|
|
1304
|
+
if constexpr (Master_matrix::Option_list::has_map_column_container) {
|
|
1305
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
1306
|
+
matrix_.try_emplace(pos, Column(column, column.get_column_index(), RA_opt::rows_, colSettings_));
|
|
1307
|
+
} else {
|
|
1308
|
+
matrix_.try_emplace(pos, Column(column, colSettings_));
|
|
1309
|
+
}
|
|
1310
|
+
} else {
|
|
1311
|
+
if constexpr (Master_matrix::Option_list::has_row_access) {
|
|
1312
|
+
matrix_.emplace_back(column, column.get_column_index(), RA_opt::rows_, colSettings_);
|
|
1313
|
+
} else {
|
|
1314
|
+
matrix_.emplace_back(column, colSettings_);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
template <class Master_matrix>
|
|
1320
|
+
inline constexpr typename Chain_matrix<Master_matrix>::Barcode& Chain_matrix<Master_matrix>::_barcode()
|
|
1321
|
+
{
|
|
1322
|
+
if constexpr (Master_matrix::Option_list::has_vine_update)
|
|
1323
|
+
return Swap_opt::template Chain_pairing<Master_matrix>::barcode_;
|
|
1324
|
+
else
|
|
1325
|
+
return Pair_opt::barcode_;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
template <class Master_matrix>
|
|
1329
|
+
inline constexpr typename Chain_matrix<Master_matrix>::Bar_dictionary&
|
|
1330
|
+
Chain_matrix<Master_matrix>::_indexToBar()
|
|
1331
|
+
{
|
|
1332
|
+
if constexpr (Master_matrix::Option_list::has_vine_update)
|
|
1333
|
+
return Swap_opt::template Chain_pairing<Master_matrix>::indexToBar_;
|
|
1334
|
+
else
|
|
1335
|
+
return Pair_opt::indexToBar_;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
template <class Master_matrix>
|
|
1339
|
+
inline constexpr typename Chain_matrix<Master_matrix>::Pos_index& Chain_matrix<Master_matrix>::_nextPosition()
|
|
1340
|
+
{
|
|
1341
|
+
if constexpr (Master_matrix::Option_list::has_vine_update)
|
|
1342
|
+
return Swap_opt::template Chain_pairing<Master_matrix>::nextPosition_;
|
|
1343
|
+
else
|
|
1344
|
+
return Pair_opt::nextPosition_;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
} // namespace persistence_matrix
|
|
1348
|
+
} // namespace Gudhi
|
|
1349
|
+
|
|
1350
|
+
#endif // PM_CHAIN_MATRIX_H
|