multipers 2.4.0b1__cp312-cp312-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.
Files changed (184) hide show
  1. multipers/.dylibs/libboost_timer.dylib +0 -0
  2. multipers/.dylibs/libc++.1.0.dylib +0 -0
  3. multipers/.dylibs/libtbb.12.17.dylib +0 -0
  4. multipers/__init__.py +33 -0
  5. multipers/_signed_measure_meta.py +426 -0
  6. multipers/_slicer_meta.py +231 -0
  7. multipers/array_api/__init__.py +62 -0
  8. multipers/array_api/numpy.py +124 -0
  9. multipers/array_api/torch.py +133 -0
  10. multipers/data/MOL2.py +458 -0
  11. multipers/data/UCR.py +18 -0
  12. multipers/data/__init__.py +1 -0
  13. multipers/data/graphs.py +466 -0
  14. multipers/data/immuno_regions.py +27 -0
  15. multipers/data/minimal_presentation_to_st_bf.py +0 -0
  16. multipers/data/pytorch2simplextree.py +91 -0
  17. multipers/data/shape3d.py +101 -0
  18. multipers/data/synthetic.py +113 -0
  19. multipers/distances.py +202 -0
  20. multipers/filtration_conversions.pxd +736 -0
  21. multipers/filtration_conversions.pxd.tp +226 -0
  22. multipers/filtrations/__init__.py +21 -0
  23. multipers/filtrations/density.py +529 -0
  24. multipers/filtrations/filtrations.py +480 -0
  25. multipers/filtrations.pxd +534 -0
  26. multipers/filtrations.pxd.tp +332 -0
  27. multipers/function_rips.cpython-312-darwin.so +0 -0
  28. multipers/function_rips.pyx +104 -0
  29. multipers/grids.cpython-312-darwin.so +0 -0
  30. multipers/grids.pyx +538 -0
  31. multipers/gudhi/Persistence_slices_interface.h +213 -0
  32. multipers/gudhi/Simplex_tree_interface.h +274 -0
  33. multipers/gudhi/Simplex_tree_multi_interface.h +648 -0
  34. multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
  35. multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
  36. multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
  37. multipers/gudhi/gudhi/Debug_utils.h +52 -0
  38. multipers/gudhi/gudhi/Degree_rips_bifiltration.h +2307 -0
  39. multipers/gudhi/gudhi/Dynamic_multi_parameter_filtration.h +2524 -0
  40. multipers/gudhi/gudhi/Fields/Multi_field.h +453 -0
  41. multipers/gudhi/gudhi/Fields/Multi_field_operators.h +460 -0
  42. multipers/gudhi/gudhi/Fields/Multi_field_shared.h +444 -0
  43. multipers/gudhi/gudhi/Fields/Multi_field_small.h +584 -0
  44. multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +490 -0
  45. multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +580 -0
  46. multipers/gudhi/gudhi/Fields/Z2_field.h +391 -0
  47. multipers/gudhi/gudhi/Fields/Z2_field_operators.h +389 -0
  48. multipers/gudhi/gudhi/Fields/Zp_field.h +493 -0
  49. multipers/gudhi/gudhi/Fields/Zp_field_operators.h +384 -0
  50. multipers/gudhi/gudhi/Fields/Zp_field_shared.h +492 -0
  51. multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
  52. multipers/gudhi/gudhi/Matrix.h +2200 -0
  53. multipers/gudhi/gudhi/Multi_filtration/Multi_parameter_generator.h +1712 -0
  54. multipers/gudhi/gudhi/Multi_filtration/multi_filtration_conversions.h +237 -0
  55. multipers/gudhi/gudhi/Multi_filtration/multi_filtration_utils.h +225 -0
  56. multipers/gudhi/gudhi/Multi_parameter_filtered_complex.h +485 -0
  57. multipers/gudhi/gudhi/Multi_parameter_filtration.h +2643 -0
  58. multipers/gudhi/gudhi/Multi_persistence/Box.h +233 -0
  59. multipers/gudhi/gudhi/Multi_persistence/Line.h +309 -0
  60. multipers/gudhi/gudhi/Multi_persistence/Multi_parameter_filtered_complex_pcoh_interface.h +268 -0
  61. multipers/gudhi/gudhi/Multi_persistence/Persistence_interface_cohomology.h +159 -0
  62. multipers/gudhi/gudhi/Multi_persistence/Persistence_interface_matrix.h +463 -0
  63. multipers/gudhi/gudhi/Multi_persistence/Point.h +853 -0
  64. multipers/gudhi/gudhi/Off_reader.h +173 -0
  65. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +834 -0
  66. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +838 -0
  67. multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +833 -0
  68. multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1367 -0
  69. multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1157 -0
  70. multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +869 -0
  71. multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +905 -0
  72. multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +122 -0
  73. multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +260 -0
  74. multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +288 -0
  75. multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +170 -0
  76. multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +247 -0
  77. multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +571 -0
  78. multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +182 -0
  79. multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +130 -0
  80. multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +235 -0
  81. multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +312 -0
  82. multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1092 -0
  83. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +923 -0
  84. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +914 -0
  85. multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +930 -0
  86. multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1071 -0
  87. multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +203 -0
  88. multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +886 -0
  89. multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +984 -0
  90. multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1213 -0
  91. multipers/gudhi/gudhi/Persistence_matrix/index_mapper.h +58 -0
  92. multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +227 -0
  93. multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +200 -0
  94. multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +166 -0
  95. multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +319 -0
  96. multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +562 -0
  97. multipers/gudhi/gudhi/Persistence_on_a_line.h +152 -0
  98. multipers/gudhi/gudhi/Persistence_on_rectangle.h +617 -0
  99. multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
  100. multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
  101. multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
  102. multipers/gudhi/gudhi/Persistent_cohomology.h +769 -0
  103. multipers/gudhi/gudhi/Points_off_io.h +171 -0
  104. multipers/gudhi/gudhi/Projective_cover_kernel.h +379 -0
  105. multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
  106. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +559 -0
  107. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
  108. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +121 -0
  109. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
  110. multipers/gudhi/gudhi/Simplex_tree/filtration_value_utils.h +155 -0
  111. multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
  112. multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
  113. multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +60 -0
  114. multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +105 -0
  115. multipers/gudhi/gudhi/Simplex_tree.h +3170 -0
  116. multipers/gudhi/gudhi/Slicer.h +848 -0
  117. multipers/gudhi/gudhi/Thread_safe_slicer.h +393 -0
  118. multipers/gudhi/gudhi/distance_functions.h +62 -0
  119. multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
  120. multipers/gudhi/gudhi/multi_simplex_tree_helpers.h +147 -0
  121. multipers/gudhi/gudhi/persistence_interval.h +263 -0
  122. multipers/gudhi/gudhi/persistence_matrix_options.h +188 -0
  123. multipers/gudhi/gudhi/reader_utils.h +367 -0
  124. multipers/gudhi/gudhi/simple_mdspan.h +484 -0
  125. multipers/gudhi/gudhi/slicer_helpers.h +779 -0
  126. multipers/gudhi/tmp_h0_pers/mma_interface_h0.h +223 -0
  127. multipers/gudhi/tmp_h0_pers/naive_merge_tree.h +536 -0
  128. multipers/io.cpython-312-darwin.so +0 -0
  129. multipers/io.pyx +472 -0
  130. multipers/ml/__init__.py +0 -0
  131. multipers/ml/accuracies.py +90 -0
  132. multipers/ml/invariants_with_persistable.py +79 -0
  133. multipers/ml/kernels.py +176 -0
  134. multipers/ml/mma.py +713 -0
  135. multipers/ml/one.py +472 -0
  136. multipers/ml/point_clouds.py +352 -0
  137. multipers/ml/signed_measures.py +1667 -0
  138. multipers/ml/sliced_wasserstein.py +461 -0
  139. multipers/ml/tools.py +113 -0
  140. multipers/mma_structures.cpython-312-darwin.so +0 -0
  141. multipers/mma_structures.pxd +134 -0
  142. multipers/mma_structures.pyx +1483 -0
  143. multipers/mma_structures.pyx.tp +1126 -0
  144. multipers/multi_parameter_rank_invariant/diff_helpers.h +85 -0
  145. multipers/multi_parameter_rank_invariant/euler_characteristic.h +95 -0
  146. multipers/multi_parameter_rank_invariant/function_rips.h +317 -0
  147. multipers/multi_parameter_rank_invariant/hilbert_function.h +761 -0
  148. multipers/multi_parameter_rank_invariant/persistence_slices.h +149 -0
  149. multipers/multi_parameter_rank_invariant/rank_invariant.h +350 -0
  150. multipers/multiparameter_edge_collapse.py +41 -0
  151. multipers/multiparameter_module_approximation/approximation.h +2541 -0
  152. multipers/multiparameter_module_approximation/debug.h +107 -0
  153. multipers/multiparameter_module_approximation/format_python-cpp.h +292 -0
  154. multipers/multiparameter_module_approximation/utilities.h +428 -0
  155. multipers/multiparameter_module_approximation.cpython-312-darwin.so +0 -0
  156. multipers/multiparameter_module_approximation.pyx +286 -0
  157. multipers/ops.cpython-312-darwin.so +0 -0
  158. multipers/ops.pyx +231 -0
  159. multipers/pickle.py +89 -0
  160. multipers/plots.py +550 -0
  161. multipers/point_measure.cpython-312-darwin.so +0 -0
  162. multipers/point_measure.pyx +409 -0
  163. multipers/simplex_tree_multi.cpython-312-darwin.so +0 -0
  164. multipers/simplex_tree_multi.pxd +136 -0
  165. multipers/simplex_tree_multi.pyx +11719 -0
  166. multipers/simplex_tree_multi.pyx.tp +2102 -0
  167. multipers/slicer.cpython-312-darwin.so +0 -0
  168. multipers/slicer.pxd +2097 -0
  169. multipers/slicer.pxd.tp +263 -0
  170. multipers/slicer.pyx +13042 -0
  171. multipers/slicer.pyx.tp +1259 -0
  172. multipers/tensor/tensor.h +672 -0
  173. multipers/tensor.pxd +13 -0
  174. multipers/test.pyx +44 -0
  175. multipers/tests/__init__.py +70 -0
  176. multipers/torch/__init__.py +1 -0
  177. multipers/torch/diff_grids.py +240 -0
  178. multipers/torch/rips_density.py +310 -0
  179. multipers/vector_interface.pxd +46 -0
  180. multipers-2.4.0b1.dist-info/METADATA +131 -0
  181. multipers-2.4.0b1.dist-info/RECORD +184 -0
  182. multipers-2.4.0b1.dist-info/WHEEL +6 -0
  183. multipers-2.4.0b1.dist-info/licenses/LICENSE +21 -0
  184. multipers-2.4.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2200 @@
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 Matrix.h
13
+ * @author Hannah Schreiber
14
+ * @brief Contains @ref Gudhi::persistence_matrix::Matrix class.
15
+ */
16
+
17
+ #ifndef MASTER_MATRIX_H
18
+ #define MASTER_MATRIX_H
19
+
20
+ #include <type_traits>
21
+ #include <vector>
22
+ #include <unordered_map>
23
+ #include <map>
24
+ #include <initializer_list>
25
+
26
+ #include <boost/intrusive/list.hpp>
27
+
28
+ #include <gudhi/Debug_utils.h>
29
+
30
+ #include <gudhi/persistence_matrix_options.h>
31
+ #include <gudhi/persistence_interval.h>
32
+
33
+ #include <gudhi/Fields/Z2_field_operators.h>
34
+
35
+ #include <gudhi/Persistence_matrix/Id_to_index_overlay.h>
36
+ #include <gudhi/Persistence_matrix/Position_to_index_overlay.h>
37
+
38
+ #include <gudhi/Persistence_matrix/matrix_dimension_holders.h>
39
+ #include <gudhi/Persistence_matrix/matrix_row_access.h>
40
+ #include <gudhi/Persistence_matrix/base_swap.h>
41
+ #include <gudhi/Persistence_matrix/base_pairing.h>
42
+ #include <gudhi/Persistence_matrix/ru_pairing.h>
43
+ #include <gudhi/Persistence_matrix/ru_vine_swap.h>
44
+ #include <gudhi/Persistence_matrix/ru_rep_cycles.h>
45
+ #include <gudhi/Persistence_matrix/chain_pairing.h>
46
+ #include <gudhi/Persistence_matrix/chain_vine_swap.h>
47
+ #include <gudhi/Persistence_matrix/chain_rep_cycles.h>
48
+
49
+ #include <gudhi/Persistence_matrix/Base_matrix.h>
50
+ #include <gudhi/Persistence_matrix/Base_matrix_with_column_compression.h>
51
+ #include <gudhi/Persistence_matrix/Boundary_matrix.h>
52
+ #include <gudhi/Persistence_matrix/RU_matrix.h>
53
+ #include <gudhi/Persistence_matrix/Chain_matrix.h>
54
+
55
+ #include <gudhi/Persistence_matrix/allocators/entry_constructors.h>
56
+ #include <gudhi/Persistence_matrix/columns/entry_types.h>
57
+ #include <gudhi/Persistence_matrix/columns/row_access.h>
58
+
59
+ #include <gudhi/Persistence_matrix/columns/column_dimension_holder.h>
60
+ #include <gudhi/Persistence_matrix/columns/chain_column_extra_properties.h>
61
+ #include <gudhi/Persistence_matrix/columns/intrusive_list_column.h>
62
+ #include <gudhi/Persistence_matrix/columns/intrusive_set_column.h>
63
+ #include <gudhi/Persistence_matrix/columns/list_column.h>
64
+ #include <gudhi/Persistence_matrix/columns/set_column.h>
65
+ #include <gudhi/Persistence_matrix/columns/unordered_set_column.h>
66
+ #include <gudhi/Persistence_matrix/columns/vector_column.h>
67
+ #include <gudhi/Persistence_matrix/columns/naive_vector_column.h>
68
+ #include <gudhi/Persistence_matrix/columns/heap_column.h>
69
+
70
+ /// Gudhi namespace.
71
+ namespace Gudhi {
72
+ /// Persistence matrix namespace.
73
+ namespace persistence_matrix {
74
+
75
+ /**
76
+ * @class Matrix matrix.h gudhi/matrix.h
77
+ * @ingroup persistence_matrix
78
+ *
79
+ * @brief Data structure for matrices, and in particular thought for matrices representing filtered complexes
80
+ * in order to compute persistence and/or representative cycles.
81
+ *
82
+ * @anchor mp_matrices __%Matrix types:__
83
+ *
84
+ * The are roughly three types of matrices available and one is selected automatically depending on the options chosen:
85
+ * - @anchor basematrix a @ref basematrix "basic matrix" which can represent any matrix and therefore will not make any
86
+ * assumption on its content. It is the only matrix type with the option of column compression (as it is the only one
87
+ * where it makes sense). This type is chosen by default when none of the homology related options are set to true:
88
+ * @ref PersistenceMatrixOptions::has_column_pairings, @ref PersistenceMatrixOptions::has_vine_update and
89
+ * @ref PersistenceMatrixOptions::can_retrieve_representative_cycles.
90
+ * - @anchor boundarymatrix a @ref boundarymatrix "boundary matrix" @f$ B = R \cdot U @f$ which either stores only
91
+ * @f$ R @f$ or the whole decomposition @f$ R @f$ and @f$ U @f$ depending on the options. This type is selected if
92
+ * @ref PersistenceMatrixOptions::is_of_boundary_type is set to true and at least one of the following options:
93
+ * @ref PersistenceMatrixOptions::has_column_pairings, @ref PersistenceMatrixOptions::has_vine_update and
94
+ * @ref PersistenceMatrixOptions::can_retrieve_representative_cycles. If only
95
+ * @ref PersistenceMatrixOptions::has_column_pairings is true, then only @f$ R @f$ is stored, but if either
96
+ * @ref PersistenceMatrixOptions::has_vine_update or @ref PersistenceMatrixOptions::can_retrieve_representative_cycles
97
+ * is true, then @f$ U @f$ also needs to be stored. Note that the option
98
+ * @ref PersistenceMatrixOptions::column_indexation_type will produce a small overhead when set to
99
+ * @ref Column_indexation_types::IDENTIFIER.
100
+ * - @anchor chainmatrix a @ref chainmatrix "chain complex matrix" representing a "compatible base" of a filtered chain
101
+ * complex (see @cite zigzag). This matrix is deduced from the boundary matrix and therefore encodes more or less the
102
+ * same information but differently and can therefore be better suited for certain applications. This type can be used
103
+ * the same way than the precedent type, only the option @ref PersistenceMatrixOptions::is_of_boundary_type has to be
104
+ * set to false. Note that the option @ref PersistenceMatrixOptions::column_indexation_type will produce a small
105
+ * overhead when set to @ref Column_indexation_types::POSITION or @ref Column_indexation_types::IDENTIFIER.
106
+ *
107
+ * @anchor mp_indexation __Indexation scheme:__
108
+ *
109
+ * The indexation system for columns of the different matrix types can be a bit tricky and different methods will not
110
+ * always take the same type of index as input (for optimization purposes). So, to avoid confusion, we will name and
111
+ * define here the different possibilities, such that we can directly refer to it in the descriptions of the methods.
112
+ * Note that every column and row in a @ref boundarymatrix "boundary" or @ref chainmatrix "chain matrix" is always
113
+ * associated to a single simplex/cell, so in order to avoid repeating formulations like "of the simplex associated to
114
+ * the column" all the time, we will amalgamate both notions together.
115
+ *
116
+ * Let @f$ c @f$ be a column.
117
+ * - @anchor MatIdx @ref MatIdx "MatIdx": This will correspond to the position of @f$ c @f$ in the matrix, i.e.,
118
+ * @f$ underlying\_container[MatIdx] = c @f$. This will be the only public indexing scheme for
119
+ * @ref basematrix "basic matrices".
120
+ * - @anchor PosIdx @ref PosIdx "PosIdx": This will correspond to the relative position of @f$ c @f$ in the current
121
+ * filtration compared to the other columns, starting the count at 0. For @ref boundarymatrix "boundary matrices",
122
+ * @ref PosIdx will always be equal to @ref MatIdx, but this is not true for @ref chainmatrix "chain matrices" when
123
+ * swaps or removals were performed.
124
+ * - @anchor IDIdx @ref IDIdx "IDIdx": This will correspond to the ID of @f$ c @f$ in the complex used to identify it in
125
+ * the boundaries. If at the insertion of @f$ c @f$, its ID was not specified and it was the @f$ n^{th} @f$ insertion,
126
+ * it is assumed that the ID is @f$ n @f$ (which means that @ref IDIdx and @ref PosIdx will only start to differ when
127
+ * swaps or removals are performed). If an ID is specified at the insertion of @f$ c @f$, the ID is stored as the
128
+ * @ref IDIdx of @f$ c @f$. IDs can be freely chosen with the only restriction that they have to be strictly
129
+ * increasing in the order of the filtration at initialisation.
130
+ *
131
+ * In conclusion, with default values, if no vine swaps or removals occurs, all three indexing schemes are the same.
132
+ *
133
+ * @anchor rowindex Let @f$ r @f$ be a row. Rows are indexed in two ways depending only if the matrix is a
134
+ * @ref chainmatrix "chain matrix" or not. If the matrix is a @ref chainmatrix "chain matrix", @f$ r @f$ is always
135
+ * indexed by its ID, so it correspond to the @ref IDIdx indexing scheme. If the matrix is not a
136
+ * @ref chainmatrix "chain matrix", @f$ r @f$ will originally also be indexed by the ID, but when a swap occurs,
137
+ * the rows also swap IDs and the new ID has to be used to access @f$ r @f$. This means that when the default
138
+ * @ref IDIdx scheme is used (the cells are numerated in order of appearance in the filtration starting at 0),
139
+ * the indexation of the rows correspond to @ref PosIdx.
140
+ *
141
+ * @tparam PersistenceMatrixOptions Structure encoding all the options of the matrix.
142
+ * See description of @ref PersistenceMatrixOptions for more details.
143
+ */
144
+ template <class PersistenceMatrixOptions = Default_options<> >
145
+ class Matrix
146
+ {
147
+ public:
148
+ using Option_list = PersistenceMatrixOptions; // to make it accessible from the other classes
149
+ using Index = typename PersistenceMatrixOptions::Index; /**< Type of @ref MatIdx index. */
150
+ using ID_index = typename PersistenceMatrixOptions::Index; /**< Type of @ref IDIdx index. */
151
+ using Pos_index = typename PersistenceMatrixOptions::Index; /**< Type of @ref PosIdx index. */
152
+ using Dimension = typename PersistenceMatrixOptions::Dimension; /**< Type for dimension value. */
153
+
154
+ /**
155
+ * @brief coefficients field type.
156
+ */
157
+ using Field_operators = std::conditional_t<PersistenceMatrixOptions::is_z2,
158
+ Gudhi::persistence_fields::Z2_field_operators,
159
+ typename PersistenceMatrixOptions::Field_coeff_operators>;
160
+ /**
161
+ * @brief Type of a field element.
162
+ */
163
+ using Element = typename Field_operators::Element;
164
+ using Characteristic = typename Field_operators::Characteristic;
165
+
166
+ /**
167
+ * @brief Returns value from a type when not set.
168
+ */
169
+ template <typename T>
170
+ static constexpr T get_null_value()
171
+ {
172
+ return -1;
173
+ }
174
+
175
+ /**
176
+ * @brief Type for a bar in the computed barcode. Stores the birth, death and dimension of the bar.
177
+ */
178
+ using Bar = Persistence_interval<Dimension, Pos_index>;
179
+
180
+ // tags for boost to associate a row and a column to a same entry
181
+ struct Matrix_row_tag;
182
+ struct Matrix_column_tag;
183
+
184
+ using Base_hook_matrix_row =
185
+ boost::intrusive::list_base_hook<boost::intrusive::tag<Matrix_row_tag>,
186
+ boost::intrusive::link_mode<boost::intrusive::auto_unlink> >;
187
+ using Base_hook_matrix_list_column =
188
+ boost::intrusive::list_base_hook<boost::intrusive::tag<Matrix_column_tag>,
189
+ boost::intrusive::link_mode<boost::intrusive::safe_link> >;
190
+ using Base_hook_matrix_set_column =
191
+ boost::intrusive::set_base_hook<boost::intrusive::tag<Matrix_column_tag>,
192
+ boost::intrusive::link_mode<boost::intrusive::safe_link> >;
193
+
194
+ // Two dummies are necessary to avoid double inheritance as an entry can inherit both a row and a column hook.
195
+ struct Dummy_row_hook {};
196
+
197
+ struct Dummy_column_hook {};
198
+
199
+ using Row_hook =
200
+ std::conditional_t<PersistenceMatrixOptions::has_row_access && PersistenceMatrixOptions::has_intrusive_rows,
201
+ Base_hook_matrix_row,
202
+ Dummy_row_hook>;
203
+ using Column_hook =
204
+ std::conditional_t<PersistenceMatrixOptions::column_type == Column_types::INTRUSIVE_LIST,
205
+ Base_hook_matrix_list_column,
206
+ std::conditional_t<PersistenceMatrixOptions::column_type == Column_types::INTRUSIVE_SET,
207
+ Base_hook_matrix_set_column,
208
+ Dummy_column_hook> >;
209
+
210
+ // Option to store the column index within the entry (additionally to the row index). Necessary only with row access.
211
+ using Entry_column_index_option = std::conditional_t<PersistenceMatrixOptions::has_row_access,
212
+ Entry_column_index<Index>,
213
+ Dummy_entry_column_index_mixin>;
214
+ // Option to store the value of the entry.
215
+ // Unnecessary for values in Z_2 as there are always 1 (0-valued entries are never stored).
216
+ using Entry_field_element_option = std::
217
+ conditional_t<PersistenceMatrixOptions::is_z2, Dummy_entry_field_element_mixin, Entry_field_element<Element> >;
218
+ /**
219
+ * @brief Type of a matrix entry. See @ref Entry for a more detailed description.
220
+ */
221
+ using Matrix_entry = Entry<Matrix<PersistenceMatrixOptions> >;
222
+
223
+ /**
224
+ * @brief Default entry constructor/destructor, using classic new and delete.
225
+ * For now, only used as default value for columns constructed independently outside of the matrix by the user.
226
+ * Could be used in the future when parallel options are implemented, as usual pools are not thread safe.
227
+ */
228
+ inline static New_entry_constructor<Matrix_entry> defaultEntryConstructor;
229
+ /**
230
+ * @brief Entry constructor/destructor used by the matrix. Uses a pool of entries to accelerate memory management,
231
+ * as entries are constructed and destroyed a lot during reduction, swaps or additions.
232
+ */
233
+ using Entry_constructor = Pool_entry_constructor<Matrix_entry>;
234
+
235
+ /**
236
+ * @brief Type used to identify an entry, for example when inserting a boundary.
237
+ * If @ref PersistenceMatrixOptions::is_z2 is true, the type is an @ref IDIdx and corresponds to the row index of the
238
+ * entry (the entry value is assumed to be 1). If @ref PersistenceMatrixOptions::is_z2 is false, the type is a pair
239
+ * whose first element is the row index of the entry and the second element is the value of the entry (which again is
240
+ * assumed to be non-zero). The column index of the row is always deduced from the context in which the type is used.
241
+ */
242
+ using Entry_representative =
243
+ std::conditional_t<PersistenceMatrixOptions::is_z2, ID_index, std::pair<ID_index, Element> >;
244
+
245
+ /**
246
+ * @private
247
+ */
248
+ static ID_index get_row_index(const Matrix_entry& e)
249
+ {
250
+ return e.get_row_index();
251
+ }
252
+ /**
253
+ * @private
254
+ */
255
+ static ID_index get_row_index(const Entry_representative& e)
256
+ {
257
+ if constexpr (PersistenceMatrixOptions::is_z2) {
258
+ return e;
259
+ } else {
260
+ return e.first;
261
+ }
262
+ }
263
+ /**
264
+ * @private
265
+ */
266
+ static ID_index& get_row_index(Entry_representative& e)
267
+ {
268
+ if constexpr (PersistenceMatrixOptions::is_z2) {
269
+ return e;
270
+ } else {
271
+ return e.first;
272
+ }
273
+ }
274
+ /**
275
+ * @private
276
+ */
277
+ static Element get_element(const Matrix_entry& e)
278
+ {
279
+ return e.get_element();
280
+ }
281
+ /**
282
+ * @private
283
+ */
284
+ static Element get_element(const Entry_representative& e)
285
+ {
286
+ if constexpr (PersistenceMatrixOptions::is_z2) {
287
+ return Field_operators::get_multiplicative_identity();
288
+ } else {
289
+ return e.second;
290
+ }
291
+ }
292
+
293
+ /**
294
+ * @brief Compares two entries by their position in the row. They are assume to be in the same row.
295
+ */
296
+ struct RowEntryComp {
297
+ bool operator()(const Matrix_entry& c1, const Matrix_entry& c2) const
298
+ {
299
+ return c1.get_column_index() < c2.get_column_index();
300
+ }
301
+ };
302
+
303
+ /**
304
+ * @brief Type of the rows stored in the matrix. Is either an intrusive list of @ref Matrix_entry (not ordered) if
305
+ * @ref PersistenceMatrixOptions::has_intrusive_rows is true, or a set of @ref Matrix_entry (ordered by
306
+ * column index) otherwise.
307
+ */
308
+ using Row = std::conditional_t<PersistenceMatrixOptions::has_intrusive_rows,
309
+ boost::intrusive::list<Matrix_entry,
310
+ boost::intrusive::constant_time_size<false>,
311
+ boost::intrusive::base_hook<Base_hook_matrix_row> >,
312
+ std::set<Matrix_entry, RowEntryComp> >;
313
+
314
+ using Row_container =
315
+ std::conditional_t<PersistenceMatrixOptions::has_removable_rows, std::map<ID_index, Row>, std::vector<Row> >;
316
+
317
+ // Row access at column level
318
+ using Row_access_option = std::conditional_t<PersistenceMatrixOptions::has_row_access,
319
+ Row_access<Matrix<PersistenceMatrixOptions> >,
320
+ Dummy_row_access>;
321
+ // Row access at matrix level
322
+ using Matrix_row_access_option =
323
+ std::conditional_t<PersistenceMatrixOptions::has_row_access,
324
+ Matrix_row_access<Row, Row_container, PersistenceMatrixOptions::has_removable_rows, ID_index>,
325
+ Dummy_matrix_row_access>;
326
+
327
+ template <typename value_type>
328
+ using Dictionary = std::conditional_t<PersistenceMatrixOptions::has_map_column_container,
329
+ std::unordered_map<unsigned int, value_type>,
330
+ std::vector<value_type> >;
331
+
332
+ static const bool isNonBasic = PersistenceMatrixOptions::has_column_pairings ||
333
+ PersistenceMatrixOptions::has_vine_update ||
334
+ PersistenceMatrixOptions::can_retrieve_representative_cycles;
335
+
336
+ using Column_dimension_option = std::
337
+ conditional_t<isNonBasic, Column_dimension_holder<Matrix<PersistenceMatrixOptions> >, Dummy_dimension_holder>;
338
+ // Extra information needed for a column when the matrix is a @ref chainmatrix "chain matrix".
339
+ using Chain_column_option = std::conditional_t<isNonBasic && !PersistenceMatrixOptions::is_of_boundary_type,
340
+ Chain_column_extra_properties<Matrix<PersistenceMatrixOptions> >,
341
+ Dummy_chain_properties>;
342
+
343
+ using Matrix_heap_column = Heap_column<Matrix<PersistenceMatrixOptions> >;
344
+ using Matrix_list_column = List_column<Matrix<PersistenceMatrixOptions> >;
345
+ using Matrix_vector_column = Vector_column<Matrix<PersistenceMatrixOptions> >;
346
+ using Matrix_naive_vector_column = Naive_std_vector_column<Matrix<PersistenceMatrixOptions> >;
347
+ using Matrix_small_vector_column = Naive_small_vector_column<Matrix<PersistenceMatrixOptions> >;
348
+ using Matrix_set_column = Set_column<Matrix<PersistenceMatrixOptions> >;
349
+ using Matrix_unordered_set_column = Unordered_set_column<Matrix<PersistenceMatrixOptions> >;
350
+ using Matrix_intrusive_list_column = Intrusive_list_column<Matrix<PersistenceMatrixOptions> >;
351
+ using Matrix_intrusive_set_column = Intrusive_set_column<Matrix<PersistenceMatrixOptions> >;
352
+
353
+ /**
354
+ * @brief Type of the columns stored in the matrix. The type depends on the value of
355
+ * @ref PersistenceMatrixOptions::column_type defined in the given options. See @ref Column_types for a more detailed
356
+ * description. All columns follow the @ref PersistenceMatrixColumn concept.
357
+ */
358
+ using Column = std::conditional_t<
359
+ PersistenceMatrixOptions::column_type == Column_types::HEAP,
360
+ Matrix_heap_column,
361
+ std::conditional_t<
362
+ PersistenceMatrixOptions::column_type == Column_types::LIST,
363
+ Matrix_list_column,
364
+ std::conditional_t<
365
+ PersistenceMatrixOptions::column_type == Column_types::SET,
366
+ Matrix_set_column,
367
+ std::conditional_t<
368
+ PersistenceMatrixOptions::column_type == Column_types::UNORDERED_SET,
369
+ Matrix_unordered_set_column,
370
+ std::conditional_t<
371
+ PersistenceMatrixOptions::column_type == Column_types::VECTOR,
372
+ Matrix_vector_column,
373
+ std::conditional_t<
374
+ PersistenceMatrixOptions::column_type == Column_types::INTRUSIVE_LIST,
375
+ Matrix_intrusive_list_column,
376
+ std::conditional_t<
377
+ PersistenceMatrixOptions::column_type == Column_types::NAIVE_VECTOR,
378
+ Matrix_naive_vector_column,
379
+ std::conditional_t<PersistenceMatrixOptions::column_type == Column_types::SMALL_VECTOR,
380
+ Matrix_small_vector_column,
381
+ Matrix_intrusive_set_column>
382
+ > > > > > > >;
383
+
384
+ struct Column_z2_settings {
385
+ Column_z2_settings() : entryConstructor() {}
386
+ Column_z2_settings([[maybe_unused]] Characteristic characteristic) : entryConstructor() {}
387
+ Column_z2_settings([[maybe_unused]] const Column_z2_settings& toCopy) : entryConstructor() {}
388
+ Column_z2_settings([[maybe_unused]] Column_z2_settings&& toMove) noexcept : entryConstructor() {}
389
+ ~Column_z2_settings() = default;
390
+ Column_z2_settings& operator=([[maybe_unused]] const Column_z2_settings& other) { return *this; }
391
+ Column_z2_settings& operator=([[maybe_unused]] Column_z2_settings&& other) noexcept { return *this; }
392
+
393
+ Entry_constructor entryConstructor; // will be replaced by more specific allocators depending on the column type.
394
+ };
395
+
396
+ struct Column_zp_settings {
397
+ Column_zp_settings() : operators(), entryConstructor() {}
398
+ Column_zp_settings(Characteristic characteristic) : operators(characteristic), entryConstructor() {}
399
+ Column_zp_settings(const Column_zp_settings& toCopy) : operators(toCopy.operators), entryConstructor() {}
400
+ Column_zp_settings(Column_zp_settings&& toMove) noexcept
401
+ : operators(std::move(toMove.operators)), entryConstructor() {}
402
+ ~Column_zp_settings() = default;
403
+ Column_zp_settings& operator=(const Column_zp_settings& other)
404
+ {
405
+ operators = other.operators;
406
+ return *this;
407
+ }
408
+ Column_zp_settings& operator=(Column_zp_settings&& other) noexcept
409
+ {
410
+ if (this == &other) return *this;
411
+
412
+ operators = std::move(other.operators);
413
+ return *this;
414
+ }
415
+
416
+ Field_operators operators;
417
+ Entry_constructor entryConstructor; // will be replaced by more specific allocators depending on the column type.
418
+ };
419
+
420
+ // struct Column_z2_with_rows_settings {
421
+ // Column_z2_with_rows_settings() : entryConstructor(), rows(nullptr) {}
422
+ // Column_z2_with_rows_settings([[maybe_unused]] Characteristic characteristic)
423
+ // : entryConstructor(), rows(nullptr) {}
424
+
425
+ // Entry_constructor entryConstructor;
426
+ // Row_container* rows;
427
+ // };
428
+
429
+ // struct Column_zp_with_rows_settings {
430
+ // Column_zp_with_rows_settings() : operators(), entryConstructor(), rows(nullptr) {}
431
+ // Column_zp_with_rows_settings(Characteristic characteristic)
432
+ // : operators(characteristic), entryConstructor(), rows(nullptr) {}
433
+
434
+ // Field_operators operators;
435
+ // Entry_constructor entryConstructor;
436
+ // Row_container* rows;
437
+ // };
438
+
439
+ // To prepare a more flexible use of the column types later (custom allocators depending on the column type etc.)
440
+ using Column_settings = std::conditional_t<PersistenceMatrixOptions::is_z2, Column_z2_settings, Column_zp_settings>;
441
+
442
+ /**
443
+ * @private
444
+ */
445
+ static Field_operators const* get_operator_ptr(Column_settings const* colSettings)
446
+ {
447
+ if constexpr (PersistenceMatrixOptions::is_z2) {
448
+ return nullptr;
449
+ } else {
450
+ if (colSettings == nullptr) return nullptr; // used for dummy columns
451
+ return &(colSettings->operators);
452
+ }
453
+ }
454
+ /**
455
+ * @private
456
+ */
457
+ template <typename T>
458
+ static Element get_coefficient_value(T v, [[maybe_unused]] Field_operators const* operators)
459
+ {
460
+ if constexpr (PersistenceMatrixOptions::is_z2) {
461
+ return Field_operators::get_value(v);
462
+ } else {
463
+ return operators->get_value(v);
464
+ }
465
+ }
466
+ /**
467
+ * @private
468
+ */
469
+ static Element get_coefficient_value(bool v, [[maybe_unused]] Field_operators const* operators) { return v; }
470
+
471
+ // using Column_settings = typename std::conditional<
472
+ // PersistenceMatrixOptions::is_z2,
473
+ // typename std::conditional<PersistenceMatrixOptions::has_row_access,
474
+ // Column_z2_with_rows_settings,
475
+ // Column_z2_settings
476
+ // >::type,
477
+ // typename std::conditional<PersistenceMatrixOptions::has_row_access,
478
+ // Column_zp_with_rows_settings,
479
+ // Column_zp_settings
480
+ // >::type
481
+ // >::type;
482
+
483
+ using Column_container = std::conditional_t<PersistenceMatrixOptions::has_map_column_container,
484
+ std::unordered_map<Index, Column>,
485
+ std::vector<Column> >;
486
+
487
+ static const bool hasFixedBarcode = Option_list::is_of_boundary_type && !PersistenceMatrixOptions::has_vine_update;
488
+ /**
489
+ * @brief Type of the computed barcode. It is either a list of @ref Matrix::Bar or a vector of @ref Matrix::Bar,
490
+ * depending if bars need to be removed from the container as some point or not.
491
+ */
492
+ using Barcode = std::conditional_t<
493
+ hasFixedBarcode,
494
+ std::vector<Bar>,
495
+ std::conditional_t<PersistenceMatrixOptions::has_removable_columns, std::list<Bar>, std::vector<Bar> > >;
496
+ using Bar_dictionary =
497
+ std::conditional_t<hasFixedBarcode,
498
+ std::conditional_t<PersistenceMatrixOptions::can_retrieve_representative_cycles,
499
+ std::vector<Index>, // RU
500
+ std::unordered_map<Pos_index, Index> // boundary
501
+ >,
502
+ std::conditional_t<PersistenceMatrixOptions::has_removable_columns,
503
+ std::unordered_map<Pos_index, typename Barcode::iterator>,
504
+ std::vector<Index> > >;
505
+
506
+ // default type for boundaries to permit list initialization directly in function parameters
507
+ using Boundary = std::conditional_t<PersistenceMatrixOptions::is_z2,
508
+ std::initializer_list<ID_index>,
509
+ std::initializer_list<std::pair<ID_index, Element> > >;
510
+
511
+ // i.e. is simple @ref boundarymatrix "boundary matrix". Also, only needed because of the reduction algorithm.
512
+ // TODO: remove the necessity and recalculate when needed or keep it like that?
513
+ static const bool maxDimensionIsNeeded =
514
+ PersistenceMatrixOptions::has_column_pairings && PersistenceMatrixOptions::is_of_boundary_type &&
515
+ !PersistenceMatrixOptions::has_vine_update && !PersistenceMatrixOptions::can_retrieve_representative_cycles;
516
+
517
+ using Matrix_dimension_option =
518
+ std::conditional_t<PersistenceMatrixOptions::has_matrix_maximal_dimension_access || maxDimensionIsNeeded,
519
+ std::conditional_t<PersistenceMatrixOptions::has_removable_columns,
520
+ Matrix_all_dimension_holder<Dimension>,
521
+ Matrix_max_dimension_holder<Dimension> >,
522
+ Dummy_matrix_dimension_holder>;
523
+
524
+ using Master_base_matrix = std::conditional_t<PersistenceMatrixOptions::has_column_compression,
525
+ Base_matrix_with_column_compression<Matrix<PersistenceMatrixOptions> >,
526
+ Base_matrix<Matrix<PersistenceMatrixOptions> > >;
527
+ using Master_boundary_matrix = Boundary_matrix<Matrix<PersistenceMatrixOptions> >;
528
+ using Master_RU_matrix = RU_matrix<Matrix<PersistenceMatrixOptions> >;
529
+ using Master_chain_matrix = Chain_matrix<Matrix<PersistenceMatrixOptions> >;
530
+
531
+ template <class Base>
532
+ using Base_swap_option = std::conditional_t<PersistenceMatrixOptions::has_vine_update ||
533
+ PersistenceMatrixOptions::has_column_and_row_swaps,
534
+ Base_swap<Matrix<PersistenceMatrixOptions>, Base>,
535
+ Dummy_base_swap>;
536
+ using Base_pairing_option =
537
+ std::conditional_t<PersistenceMatrixOptions::has_column_pairings && !PersistenceMatrixOptions::has_vine_update &&
538
+ !PersistenceMatrixOptions::can_retrieve_representative_cycles,
539
+ Base_pairing<Matrix<PersistenceMatrixOptions> >,
540
+ Dummy_base_pairing>;
541
+
542
+ using RU_pairing_option = std::conditional_t<PersistenceMatrixOptions::has_column_pairings,
543
+ std::conditional_t<PersistenceMatrixOptions::has_vine_update,
544
+ RU_barcode_swap<Matrix<PersistenceMatrixOptions> >,
545
+ RU_pairing<Matrix<PersistenceMatrixOptions> > >,
546
+ Dummy_ru_pairing>;
547
+ using RU_vine_swap_option = std::conditional_t<PersistenceMatrixOptions::has_vine_update,
548
+ RU_vine_swap<Matrix<PersistenceMatrixOptions> >,
549
+ Dummy_ru_vine_swap>;
550
+ using RU_representative_cycles_option =
551
+ std::conditional_t<PersistenceMatrixOptions::can_retrieve_representative_cycles,
552
+ RU_representative_cycles<Matrix<PersistenceMatrixOptions> >,
553
+ Dummy_ru_representative_cycles>;
554
+
555
+ using Chain_pairing_option =
556
+ std::conditional_t<PersistenceMatrixOptions::has_column_pairings,
557
+ std::conditional_t<PersistenceMatrixOptions::has_vine_update,
558
+ Chain_barcode_swap<Matrix<PersistenceMatrixOptions> >,
559
+ Chain_pairing<Matrix<PersistenceMatrixOptions> > >,
560
+ Dummy_chain_pairing>;
561
+ using Chain_vine_swap_option = std::conditional_t<PersistenceMatrixOptions::has_vine_update,
562
+ Chain_vine_swap<Matrix<PersistenceMatrixOptions> >,
563
+ Dummy_chain_vine_swap>;
564
+ using Chain_representative_cycles_option =
565
+ std::conditional_t<PersistenceMatrixOptions::can_retrieve_representative_cycles,
566
+ Chain_representative_cycles<Matrix<PersistenceMatrixOptions> >,
567
+ Dummy_chain_representative_cycles>;
568
+
569
+ /**
570
+ * @brief Type of a representative cycle. Vector of @ref rowindex "row indices".
571
+ */
572
+ using Cycle = std::vector<Entry_representative>;
573
+
574
+ /**
575
+ * @private
576
+ */
577
+ template <class EntryRange>
578
+ static Cycle build_cycle_from_range(const EntryRange& entries)
579
+ {
580
+ Cycle cycle;
581
+ if constexpr (RangeTraits<EntryRange>::has_size) {
582
+ cycle.reserve(entries.size());
583
+ }
584
+ for (const auto& c : entries) {
585
+ if constexpr (PersistenceMatrixOptions::is_z2) {
586
+ cycle.push_back(c.get_row_index());
587
+ } else {
588
+ cycle.push_back({c.get_row_index(), c.get_element()});
589
+ }
590
+ }
591
+ return cycle;
592
+ }
593
+
594
+ // Return types to factorize the corresponding methods
595
+
596
+ // The returned column is `const` if the matrix uses column compression
597
+ using Returned_column =
598
+ std::conditional_t<!isNonBasic && PersistenceMatrixOptions::has_column_compression, const Column, Column>;
599
+ // The returned row is `const` if the matrix uses column compression
600
+ using Returned_row =
601
+ std::conditional_t<!isNonBasic && PersistenceMatrixOptions::has_column_compression, const Row, Row>;
602
+ // If the matrix is a chain matrix, the insertion method returns the pivots of its unpaired columns used to reduce the
603
+ // inserted boundary. Otherwise, void.
604
+ using Insertion_return =
605
+ std::conditional_t<PersistenceMatrixOptions::is_of_boundary_type || !isNonBasic ||
606
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION,
607
+ void,
608
+ std::vector<Entry_representative> >;
609
+
610
+ /**
611
+ * @brief Default constructor. Initializes an empty matrix.
612
+ */
613
+ Matrix();
614
+ /**
615
+ * @brief Constructs a new matrix from the given ranges of @ref Entry_representative. Each range corresponds to a
616
+ * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing
617
+ * IDs. If the columns are representing a boundary matrix, the IDs of the simplices are also assumed to be
618
+ * consecutive, ordered by filtration value, starting with 0.
619
+ *
620
+ * See @ref mp_matrices "matrix descriptions" for further details on how the given matrix is handled.
621
+ *
622
+ * @tparam Container Range type for @ref Entry_representative ranges. Assumed to have a begin(), end() and size()
623
+ * method.
624
+ * @param columns For a @ref basematrix "base matrix", the columns are copied as is. If options related to homology
625
+ * are activated, @p columns is interpreted as a boundary matrix of a **simplicial** complex. In this case,
626
+ * `columns[i]` should store the boundary of simplex `i` as an ordered list of indices of its facets (again those
627
+ * indices correspond to their respective position in the matrix). Therefore the indices of the simplices are assumed
628
+ * to be consecutive and starting with 0 (an empty boundary is interpreted as a vertex boundary and not as a non
629
+ * existing simplex). All dimensions up to the maximal dimension of interest have to be present. If only a higher
630
+ * dimension is of interest and not everything should be stored, then use the @ref insert_boundary method instead
631
+ * (after creating the matrix with the @ref Matrix(unsigned int numberOfColumns, Characteristic characteristic)
632
+ * constructor preferably). If the persistence barcode has to be computed from this matrix, the simplices are also
633
+ * assumed to be ordered by appearance order in the filtration. Also, depending of the options, the matrix is
634
+ * eventually reduced on the fly or converted into a chain complex base, so the new matrix is not always identical to
635
+ * the old one.
636
+ * @param characteristic Characteristic of the coefficient field. Has to be specified if
637
+ * @ref PersistenceMatrixOptions::is_z2 is false. Default value is 11. Ignored if
638
+ * @ref PersistenceMatrixOptions::is_z2 is true.
639
+ */
640
+ template <class Container = Boundary>
641
+ Matrix(const std::vector<Container>& columns, Characteristic characteristic = 11);
642
+ /**
643
+ * @brief Constructs a new empty matrix and reserves space for the given number of columns.
644
+ *
645
+ * @param numberOfColumns Number of columns to reserve space for.
646
+ * @param characteristic Characteristic of the coefficient field. If not specified and
647
+ * @ref PersistenceMatrixOptions::is_z2 is false, the characteristic has to be set later with the use of
648
+ * @ref set_characteristic before calling for the first time a method needing it. Ignored if
649
+ * @ref PersistenceMatrixOptions::is_z2 is true.
650
+ */
651
+ Matrix(unsigned int numberOfColumns, Characteristic characteristic = Field_operators::nullCharacteristic);
652
+ /**
653
+ * @brief Constructs a new empty matrix with the given comparator functions. Only available when those comparators
654
+ * are necessary.
655
+ *
656
+ * That is, when **all** following options have following values:
657
+ * - @ref PersistenceMatrixOptions::is_of_boundary_type = false
658
+ * - @ref PersistenceMatrixOptions::has_vine_update = true
659
+ * - @ref PersistenceMatrixOptions::has_column_pairings = false
660
+ *
661
+ * Those comparators are necessary to distinguish cases in a vine update. When the matrix is of
662
+ * @ref boundarymatrix "boundary type" or if the column pairing is activated (i.e., the barcode is stored),
663
+ * the comparators can be easily deduced without overhead. If neither are true, we assume that one has additional
664
+ * information outside of the matrix about the barcode to provide a better suited comparator adapted to the situation
665
+ * (as in the implementation of the Zigzag algorithm @cite zigzag for example.)
666
+ *
667
+ * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
668
+ * cell is associated to a bar with strictly smaller birth than the bar associated to the second one.
669
+ * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
670
+ * cell is associated to a bar with strictly smaller death than the bar associated to the second one.
671
+ */
672
+ Matrix(const std::function<bool(Pos_index, Pos_index)>& birthComparator,
673
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator);
674
+ /**
675
+ * @brief Constructs a new matrix from the given ranges with the given comparator functions.
676
+ * Only available when those comparators are necessary.
677
+ *
678
+ * That is, when **all** following options have following values:
679
+ * - @ref PersistenceMatrixOptions::is_of_boundary_type = false
680
+ * - @ref PersistenceMatrixOptions::has_vine_update = true
681
+ * - @ref PersistenceMatrixOptions::has_column_pairings = false
682
+ *
683
+ * See description of @ref Matrix(const std::vector<Container>& columns, Characteristic characteristic)
684
+ * for more information about @p orderedBoundaries and
685
+ * @ref Matrix(const std::function<bool(Pos_index,Pos_index)>&, const std::function<bool(Pos_index,Pos_index)>&)
686
+ * for more information about the comparators.
687
+ *
688
+ * @tparam Boundary_range Range type for @ref Entry_representative ranges. Assumed to have a begin(), end() and size()
689
+ * method.
690
+ * @param orderedBoundaries Vector of ordered boundaries in filtration order. Indexed continuously starting at 0.
691
+ * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
692
+ * cell is associated to a bar with strictly smaller birth than the bar associated to the second one.
693
+ * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
694
+ * cell is associated to a bar with strictly smaller death than the bar associated to the second one.
695
+ * @param characteristic Characteristic of the coefficient field. Has to be specified if
696
+ * @ref PersistenceMatrixOptions::is_z2 is false. Default value is 11.
697
+ * Ignored if @ref PersistenceMatrixOptions::is_z2 is true.
698
+ */
699
+ template <class Boundary_range = Boundary>
700
+ Matrix(const std::vector<Boundary_range>& orderedBoundaries,
701
+ const std::function<bool(Pos_index, Pos_index)>& birthComparator,
702
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator,
703
+ Characteristic characteristic = 11);
704
+ /**
705
+ * @brief Constructs a new empty matrix and reserves space for the given number of columns.
706
+ * Only available when those comparators are necessary.
707
+ *
708
+ * That is, when **all** following options have following values:
709
+ * - @ref PersistenceMatrixOptions::is_of_boundary_type = false
710
+ * - @ref PersistenceMatrixOptions::has_vine_update = true
711
+ * - @ref PersistenceMatrixOptions::has_column_pairings = false
712
+ *
713
+ * See description of
714
+ * @ref Matrix(const std::function<bool(Pos_index,Pos_index)>&, const std::function<bool(Pos_index,Pos_index)>&)
715
+ * for more information about the comparators.
716
+ *
717
+ * @param numberOfColumns Number of columns to reserve space for.
718
+ * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
719
+ * cell is associated to a bar with strictly smaller birth than the bar associated to the second one.
720
+ * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first
721
+ * cell is associated to a bar with strictly smaller death than the bar associated to the second one.
722
+ * @param characteristic Characteristic of the coefficient field. If not specified and
723
+ * @ref PersistenceMatrixOptions::is_z2 is false, the characteristic has to be set later with the use of
724
+ * @ref set_characteristic before calling for the first time a method needing it.
725
+ * Ignored if @ref PersistenceMatrixOptions::is_z2 is true.
726
+ */
727
+ Matrix(unsigned int numberOfColumns,
728
+ const std::function<bool(Pos_index, Pos_index)>& birthComparator,
729
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator,
730
+ Characteristic characteristic = Field_operators::nullCharacteristic);
731
+ /**
732
+ * @brief Copy constructor.
733
+ *
734
+ * @param matrixToCopy %Matrix to copy.
735
+ */
736
+ Matrix(const Matrix& matrixToCopy);
737
+ /**
738
+ * @brief Move constructor.
739
+ * After the move, the given matrix will be empty.
740
+ *
741
+ * @param other %Matrix to move.
742
+ */
743
+ Matrix(Matrix&& other) noexcept;
744
+
745
+ ~Matrix();
746
+
747
+ // TODO: compatibility with multi fields:
748
+ // - set_characteristic(Characteristic min, Characteristic max)
749
+ // - readapt reduction?
750
+ /**
751
+ * @brief Sets the characteristic of the coefficient field if @ref PersistenceMatrixOptions::is_z2 is false,
752
+ * does nothing otherwise.
753
+ * Should be used if no characteristic could be specified at the creation of the empty matrix.
754
+ * Do not change the value of the characteristic once used.
755
+ *
756
+ * @warning The coefficient values stored in the matrix are stored after computing the corresponding modulo.
757
+ * Therefore, changing the characteristic after is very likely to invalidate all entry values.
758
+ *
759
+ * @param characteristic The characteristic to set.
760
+ */
761
+ void set_characteristic(Characteristic characteristic);
762
+
763
+ // (TODO: if there is no row access and the column type corresponds to the internal column type of the matrix,
764
+ // moving the column instead of copying it should be possible. Is it worth implementing it?)
765
+ /**
766
+ * @brief Inserts a new ordered column at the end of the matrix by copying the given range of
767
+ * @ref Entry_representative. The content of the range is assumed to be sorted by increasing ID value.
768
+ *
769
+ * Only available for @ref basematrix "base matrices".
770
+ * Otherwise use @ref insert_boundary which will deduce a new column from the boundary given.
771
+ *
772
+ * @tparam Container Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method.
773
+ * @param column Column to be inserted.
774
+ */
775
+ template <class Container, class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
776
+ void insert_column(const Container& column);
777
+ /**
778
+ * @brief Inserts a new ordered column at the given index by copying the given range of @ref Entry_representative.
779
+ * There should not be any other column inserted at that index which was not explicitly removed before.
780
+ * The content of the range is assumed to be sorted by increasing ID value.
781
+ *
782
+ * Only available for @ref basematrix "base matrices" without column compression and without row access.
783
+ *
784
+ * @tparam Container Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method.
785
+ * @param column Column to be inserted.
786
+ * @param columnIndex @ref MatIdx index to which the column has to be inserted.
787
+ */
788
+ template <class Container, class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
789
+ void insert_column(const Container& column, Index columnIndex);
790
+ /**
791
+ * @brief Inserts a new column at the end of the matrix. The column will consist of the given index only.
792
+ *
793
+ * @param idx Entry ID.
794
+ * @param e Entry coefficient. Ignored if the coefficient field is Z2. Default value: 1.
795
+ */
796
+ void insert_column(ID_index idx, Element e = 1U);
797
+ // TODO: for simple boundary matrices, add an index pointing to the first column inserted after the last call of
798
+ // get_current_barcode to enable several calls to get_current_barcode
799
+ /**
800
+ * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary.
801
+ * This means that it is assumed that this method is called on boundaries in the order of the filtration.
802
+ * It also assumes that the cells in the given boundary are identified by their relative position in the filtration,
803
+ * starting at 0. If it is not the case, use the other
804
+ * @ref insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary"
805
+ * instead by indicating the cell ID used in the boundaries when the cell is inserted.
806
+ *
807
+ * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from
808
+ * a more general entry complex. This includes cubical complexes or Morse complexes for example.
809
+ *
810
+ * The content of the new column will vary depending on the underlying @ref mp_matrices "type of the matrix":
811
+ * - If it is a @ref basematrix "basic matrix" type, the boundary is copied as it is, i.e., the method is equivalent
812
+ * to @ref insert_column.
813
+ * - If it is a @ref boundarymatrix "boundary type matrix" and only \f$ R \f$ is stored, the boundary is also just
814
+ * copied. The column will only be reduced later when the barcode is requested in order to apply some optimizations
815
+ * with the additional knowledge. Hence, the barcode will also not be updated, so call @ref get_current_barcode only
816
+ * when the matrix is complete.
817
+ * - If it is a @ref boundarymatrix "boundary type matrix" and both \f$ R \f$ and \f$ U \f$ are stored, the new
818
+ * boundary is stored in its reduced form and the barcode, if active, is also updated.
819
+ * - If it is a @ref chainmatrix "chain type matrix", the new column is of the form `IDIdx + linear combination of
820
+ * older column IDIdxs`, where the combination is deduced while reducing the given boundary. If the barcode is stored,
821
+ * it will also be updated.
822
+ *
823
+ * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method.
824
+ * @param boundary Boundary generating the new column. The content should be ordered by ID.
825
+ * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
826
+ * this parameter can be omitted as it can be deduced from the size of the boundary.
827
+ * @return If it is a @ref chainmatrix "chain matrix", the method returns the @ref MatIdx indices of the unpaired
828
+ * chains used to reduce the boundary. Otherwise, nothing.
829
+ */
830
+ template <class Boundary_range = Boundary>
831
+ Insertion_return insert_boundary(const Boundary_range& boundary, Dimension dim = Matrix::get_null_value<Dimension>());
832
+ /**
833
+ * @brief Only available for @ref mp_matrices "non-basic matrices".
834
+ * It does the same as the other version, but allows the boundary cells to be identified without restrictions
835
+ * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then
836
+ * to use the other insertion method to avoid overwriting IDs.
837
+ *
838
+ * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that
839
+ * for @ref mp_matrices "non-basic matrices", the cells are inserted by order of filtration), it is sufficient to
840
+ * indicate the ID of the cell being inserted.
841
+ *
842
+ * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method.
843
+ * @param cellIndex @ref IDIdx index to use to identify the new cell.
844
+ * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the
845
+ * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in
846
+ * increasing order.
847
+ * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
848
+ * this parameter can be omitted as it can be deduced from the size of the boundary.
849
+ * @return If it is a @ref chainmatrix "chain matrix", the method returns the @ref MatIdx indices of the unpaired
850
+ * chains used to reduce the boundary. Otherwise, nothing.
851
+ */
852
+ template <class Boundary_range = Boundary>
853
+ Insertion_return insert_boundary(ID_index cellIndex,
854
+ const Boundary_range& boundary,
855
+ Dimension dim = Matrix::get_null_value<Dimension>());
856
+
857
+ /**
858
+ * @brief Returns the column at the given @ref MatIdx index.
859
+ * For @ref boundarymatrix "RU matrices", is equivalent to
860
+ * @ref get_column(Index columnIndex, bool inR) "get_column(columnIndex, true)".
861
+ * The type of the column depends on the chosen options, see @ref PersistenceMatrixOptions::column_type.
862
+ *
863
+ * @param columnIndex @ref MatIdx index of the column to return.
864
+ * @return Reference to the column. Is `const` if the matrix has column compression.
865
+ */
866
+ Returned_column& get_column(Index columnIndex);
867
+ /**
868
+ * @brief Only available for @ref chainmatrix "chain matrices". Returns the column at the given @ref MatIdx index.
869
+ * The type of the column depends on the chosen options, see @ref PersistenceMatrixOptions::column_type.
870
+ *
871
+ * @param columnIndex @ref MatIdx index of the column to return.
872
+ * @return Const reference to the column.
873
+ */
874
+ const Column& get_column(Index columnIndex) const;
875
+ // TODO: there is no particular reason that this method is not available for identifier indexing,
876
+ // just has to be added to the interface...
877
+ /**
878
+ * @brief Only available for @ref boundarymatrix "RU matrices" without @ref Column_indexation_types::IDENTIFIER
879
+ * indexing. Returns the column at the given @ref MatIdx index in \f$ R \f$ if @p inR is true and in \f$ U \f$ if
880
+ * @p inR is false. The type of the column depends on the chosen options,
881
+ * see @ref PersistenceMatrixOptions::column_type.
882
+ *
883
+ * @param columnIndex @ref MatIdx index of the column to return.
884
+ * @param inR If true, returns the column in \f$ R \f$, if false, returns the column in \f$ U \f$.
885
+ * @return Const reference to the column.
886
+ */
887
+ const Column& get_column(Index columnIndex, bool inR);
888
+
889
+ // TODO: update column indices when reordering rows (after lazy swap) such that always MatIdx are returned.
890
+ /**
891
+ * @brief Only available if @ref PersistenceMatrixOptions::has_row_access is true. Returns the row at the given
892
+ * @ref rowindex "row index". For @ref boundarymatrix "RU matrices", is equivalent to
893
+ * @ref get_row(ID_index rowIndex, bool inR) "get_row(columnIndex, true)". The type of the row depends on the
894
+ * chosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows.
895
+ *
896
+ * @param rowIndex @ref rowindex "Row index" of the row to return: @ref IDIdx for @ref chainmatrix "chain matrices" or
897
+ * updated @ref IDIdx for @ref boundarymatrix "boundary matrices" if swaps occurred.
898
+ * @return Reference to the row. Is `const` if the matrix has column compression.
899
+ */
900
+ Returned_row& get_row(ID_index rowIndex);
901
+ /**
902
+ * @brief Only available for @ref chainmatrix "chain matrices" and matrices with column compression.
903
+ * Returns the row at the given @ref rowindex "row index".
904
+ * The type of the row depends on the chosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows.
905
+ *
906
+ * @param rowIndex @ref rowindex "Row index" of the row to return: @ref IDIdx for @ref chainmatrix "chain matrices"
907
+ * or updated @ref IDIdx for @ref boundarymatrix "boundary matrices" if swaps occurred.
908
+ * @return Const reference to the row.
909
+ */
910
+ const Row& get_row(ID_index rowIndex) const;
911
+ // TODO: there is no particular reason that this method is not available for identifier indexing,
912
+ // just has to be added to the interface...
913
+ /**
914
+ * @brief Only available for @ref boundarymatrix "RU matrices" without @ref Column_indexation_types::IDENTIFIER
915
+ * indexing. Returns the row at the given @ref rowindex "row index" in \f$ R \f$ if @p inR is true and in \f$ U \f$ if
916
+ * @p inR is false. The type of the row depends on the chosen options, see
917
+ * @ref PersistenceMatrixOptions::has_intrusive_rows.
918
+ *
919
+ * @param rowIndex @ref rowindex "Row index" of the row to return: updated @ref IDIdx if swaps occurred.
920
+ * @param inR If true, returns the row in \f$ R \f$, if false, returns the row in \f$ U \f$.
921
+ * @return Const reference to the row.
922
+ */
923
+ const Row& get_row(ID_index rowIndex, bool inR);
924
+
925
+ /**
926
+ * @brief Only available for @ref basematrix "base matrices" without column compression and if
927
+ * @ref PersistenceMatrixOptions::has_map_column_container is true. Otherwise, see @ref remove_last. Erases the given
928
+ * column from the matrix. If @ref PersistenceMatrixOptions::has_row_access is also true, the deleted column entries
929
+ * are also automatically removed from their respective rows.
930
+ *
931
+ * @param columnIndex @ref MatIdx index of the column to remove.
932
+ */
933
+ void remove_column(Index columnIndex);
934
+ // TODO: rename method to be less confusing.
935
+ /**
936
+ * @brief The effect varies depending on the matrices and the options:
937
+ * - @ref basematrix "base matrix" and @ref boundarymatrix "boundary matrix":
938
+ * - @ref PersistenceMatrixOptions::has_map_column_container and @ref
939
+ * PersistenceMatrixOptions::has_column_and_row_swaps are true: cleans up maps used for the lazy row swaps.
940
+ * - @ref PersistenceMatrixOptions::has_row_access and @ref PersistenceMatrixOptions::has_removable_rows are true:
941
+ * assumes that the row is empty and removes it.
942
+ * - Otherwise, does nothing.
943
+ * - @ref boundarymatrix "boundary matrix" with \f$ U \f$ stored: only \f$ R \f$ is affected by the above. If properly
944
+ * used, \f$ U \f$ will never have empty rows.
945
+ * - @ref chainmatrix "chain matrix": only available if @ref PersistenceMatrixOptions::has_row_access and
946
+ * @ref PersistenceMatrixOptions::has_removable_rows are true. Assumes that the row is empty and removes it.
947
+ *
948
+ * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not
949
+ * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when
950
+ * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the
951
+ * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from
952
+ * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be quite
953
+ * frequent.
954
+ *
955
+ * @param rowIndex @ref rowindex "Row index" of the empty row to remove.
956
+ */
957
+ void erase_empty_row(ID_index rowIndex);
958
+ // TODO: for chain matrices, replace IDIdx input with MatIdx input to homogenize.
959
+ /**
960
+ * @brief Only available for @ref boundarymatrix "RU" and @ref chainmatrix "chain matrices" and if
961
+ * @ref PersistenceMatrixOptions::has_removable_columns and @ref PersistenceMatrixOptions::has_vine_update are true.
962
+ * For @ref chainmatrix "chain matrices", @ref PersistenceMatrixOptions::has_map_column_container and
963
+ * @ref PersistenceMatrixOptions::has_column_pairings also need to be true. Assumes that the cell is maximal in the
964
+ * current complex and removes it such that the matrix remains consistent (i.e., RU is still an upper triangular
965
+ * decomposition of the boundary matrix and chain is still a compatible bases of the chain complex in the sense
966
+ * of @cite zigzag). The maximality of the cell is not verified. Also updates the barcode if it was computed.
967
+ *
968
+ * For @ref chainmatrix "chain matrices", using the other version of the method could perform better depending on how
969
+ * the data is maintained on the side of the user. Then, @ref PersistenceMatrixOptions::has_column_pairings also do
970
+ * not need to be true.
971
+ *
972
+ * See also @ref remove_last and @ref remove_column.
973
+ *
974
+ * @param columnIndex If @ref boundarymatrix "boundary matrix", @ref MatIdx index of the cell to remove, otherwise the
975
+ * @ref IDIdx index.
976
+ */
977
+ void remove_maximal_cell(Index columnIndex);
978
+ // TODO: See if it would be better to use something more general than a vector for columnsToSwap, such that
979
+ // the user do not have to construct the vector from scratch. Like passing iterators instead. But it would be nice,
980
+ // to still be able to do (cell, {})...
981
+ /**
982
+ * @brief Only available for @ref chainmatrix "chain matrices" and if
983
+ * @ref PersistenceMatrixOptions::has_removable_columns, @ref PersistenceMatrixOptions::has_vine_update and
984
+ * @ref PersistenceMatrixOptions::has_map_column_container are true. Assumes that the cell is maximal in the current
985
+ * complex and removes it such that the matrix remains consistent (i.e., it is still a compatible bases of the chain
986
+ * complex in the sense of @cite zigzag). The maximality of the cell is not verified. Also updates the barcode if it
987
+ * was computed.
988
+ *
989
+ * To maintain the compatibility, vine swaps are done to move the cell up to the end of the filtration. Once at the
990
+ * end, the removal is trivial. But for @ref chainmatrix "chain matrices", swaps do not actually swap the position of
991
+ * the column every time, so the cells appearing after @p cellIndex in the filtration have to be searched first within
992
+ * the matrix. If the user has an easy access to the @ref IDIdx of the cells in the order of filtration, passing them
993
+ * by argument with @p columnsToSwap allows to skip a linear search process. Typically, if the user knows that the
994
+ * cell he wants to remove is already the last cell of the filtration, calling
995
+ * @ref remove_maximal_cell(ID_index cellIndex, const std::vector<ID_index>& columnsToSwap)
996
+ * "remove_maximal_cell(cellID, {})" will be faster than @ref remove_last().
997
+ *
998
+ * See also @ref remove_last.
999
+ *
1000
+ * @param cellIndex @ref IDIdx index of the cell to remove
1001
+ * @param columnsToSwap Vector of @ref IDIdx indices of the cells coming after @p cellIndex in the filtration.
1002
+ */
1003
+ void remove_maximal_cell(ID_index cellIndex, const std::vector<ID_index>& columnsToSwap);
1004
+ /**
1005
+ * @brief Removes the last inserted column/cell from the matrix.
1006
+ * If the matrix is @ref mp_matrices "non basic", @ref PersistenceMatrixOptions::has_removable_columns has to be true
1007
+ * for the method to be available. Additionally, if the matrix is a @ref chainmatrix "chain matrix", either
1008
+ * @ref PersistenceMatrixOptions::has_map_column_container has to be true or
1009
+ * @ref PersistenceMatrixOptions::has_vine_update has to be false. And if the matrix is a
1010
+ * @ref basematrix "base matrix" it should be without column compression.
1011
+ *
1012
+ * See also @ref remove_maximal_cell and @ref remove_column.
1013
+ *
1014
+ * For @ref chainmatrix "chain matrices", if @ref PersistenceMatrixOptions::has_vine_update is true, the last cell
1015
+ * does not have to be at the end of the matrix and therefore has to be searched first. In this case, if the user
1016
+ * already knows the @ref IDIdx of the last cell, calling
1017
+ * @ref remove_maximal_cell(ID_index cellIndex, const std::vector<ID_index>& columnsToSwap)
1018
+ * "remove_maximal_cell(cellID, {})" instead allows to skip the search.
1019
+ */
1020
+ void remove_last();
1021
+
1022
+ /**
1023
+ * @brief Returns the maximal dimension of a cell stored in the matrix. Only available for
1024
+ * @ref mp_matrices "non-basic matrices" and if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access
1025
+ * is true.
1026
+ *
1027
+ * @return The maximal dimension.
1028
+ */
1029
+ Dimension get_max_dimension() const;
1030
+ /**
1031
+ * @brief Returns the current number of columns in the matrix.
1032
+ *
1033
+ * @return The number of columns.
1034
+ */
1035
+ Index get_number_of_columns() const;
1036
+ /**
1037
+ * @brief Returns the dimension of the given cell. Only available for @ref mp_matrices "non-basic matrices".
1038
+ *
1039
+ * @param columnIndex @ref MatIdx index of the column representing the cell.
1040
+ * @return Dimension of the cell.
1041
+ */
1042
+ Dimension get_column_dimension(Index columnIndex) const;
1043
+
1044
+ /**
1045
+ * @brief Adds column at @p sourceColumnIndex onto the column at @p targetColumnIndex in the matrix. Is available
1046
+ * for every matrix type, but should be used with care with @ref mp_matrices "non-basic matrices", as they will be
1047
+ * no verification to ensure that the addition makes sense for the meaning of the underlying object. For example,
1048
+ * a right-to-left addition could corrupt the computation of the barcode or the representative cycles if done blindly.
1049
+ *
1050
+ * For @ref basematrix "basic matrices" with column compression, the representatives are summed together, which means
1051
+ * that all column compressed together with the target column are affected by the change, not only the target.
1052
+ *
1053
+ * @tparam Integer_index Any signed or unsigned integer type.
1054
+ * @param sourceColumnIndex @ref MatIdx index of the column to add.
1055
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1056
+ */
1057
+ template <typename Integer_index>
1058
+ std::enable_if_t<std::is_integral_v<Integer_index> > add_to(Integer_index sourceColumnIndex,
1059
+ Integer_index targetColumnIndex);
1060
+ /**
1061
+ * @brief Adds the given range of @ref Entry onto the column at @p targetColumnIndex in the matrix. Only available
1062
+ * for @ref basematrix "basic matrices".
1063
+ *
1064
+ * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which
1065
+ * means that all column compressed together with the target column are affected by the change, not only the target.
1066
+ *
1067
+ * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be
1068
+ * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true.
1069
+ * @param sourceColumn Source @ref Entry range.
1070
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1071
+ */
1072
+ template <class Entry_range>
1073
+ std::enable_if_t<!std::is_integral_v<Entry_range> > add_to(const Entry_range& sourceColumn, Index targetColumnIndex);
1074
+
1075
+ /**
1076
+ * @brief Multiplies the target column with the coefficient and then adds the source column to it.
1077
+ * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`.
1078
+ * Is available for every matrix type, but should be used with care with @ref mp_matrices "non-basic matrices",
1079
+ * as they will be no verification to ensure that the addition makes sense for the meaning of the underlying object.
1080
+ * For example, a right-to-left addition could corrupt the computation of the barcode or the representative cycles
1081
+ * if done blindly.
1082
+ *
1083
+ * For @ref basematrix "basic matrices" with column compression, the representatives are summed together, which means
1084
+ * that all column compressed together with the target column are affected by the change, not only the target.
1085
+ *
1086
+ * @tparam Integer_index Any signed or unsigned integer type.
1087
+ * @param sourceColumnIndex @ref MatIdx index of the column to add.
1088
+ * @param coefficient Value to multiply.
1089
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1090
+ */
1091
+ template <typename Integer_index>
1092
+ std::enable_if_t<std::is_integral_v<Integer_index> > multiply_target_and_add_to(Integer_index sourceColumnIndex,
1093
+ int coefficient,
1094
+ Integer_index targetColumnIndex);
1095
+ /**
1096
+ * @brief Multiplies the target column with the coefficient and then adds the given range of @ref Entry to it.
1097
+ * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`. Only available for
1098
+ * @ref basematrix "basic matrices".
1099
+ *
1100
+ * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which
1101
+ * means that all column compressed together with the target column are affected by the change, not only the target.
1102
+ *
1103
+ * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be
1104
+ * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true.
1105
+ * @param sourceColumn Source @ref Entry range.
1106
+ * @param coefficient Value to multiply.
1107
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1108
+ */
1109
+ template <class Entry_range>
1110
+ std::enable_if_t<!std::is_integral_v<Entry_range> > multiply_target_and_add_to(const Entry_range& sourceColumn,
1111
+ int coefficient,
1112
+ Index targetColumnIndex);
1113
+
1114
+ /**
1115
+ * @brief Multiplies the source column with the coefficient before adding it to the target column.
1116
+ * That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified.
1117
+ * Is available for every matrix type, but should be used with care with @ref mp_matrices "non-basic matrices", as
1118
+ * they will be no verification to ensure that the addition makes sense for the meaning of the underlying object.
1119
+ * For example, a right-to-left addition could corrupt the computation of the barcode or the representative cycles
1120
+ * if done blindly.
1121
+ *
1122
+ * For @ref basematrix "basic matrices" with column compression, the representatives are summed together, which means
1123
+ * that all column compressed together with the target column are affected by the change, not only the target.
1124
+ *
1125
+ * @tparam Integer_index Any signed or unsigned integer type.
1126
+ * @param coefficient Value to multiply.
1127
+ * @param sourceColumnIndex @ref MatIdx index of the column to add.
1128
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1129
+ */
1130
+ template <typename Integer_index>
1131
+ std::enable_if_t<std::is_integral_v<Integer_index> > multiply_source_and_add_to(int coefficient,
1132
+ Integer_index sourceColumnIndex,
1133
+ Integer_index targetColumnIndex);
1134
+ /**
1135
+ * @brief Multiplies the source column with the coefficient before adding it to the target column.
1136
+ * That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified.
1137
+ * Only available for @ref basematrix "basic matrices".
1138
+ *
1139
+ * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which
1140
+ * means that all column compressed together with the target column are affected by the change, not only the target.
1141
+ *
1142
+ * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be
1143
+ * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true.
1144
+ * @param coefficient Value to multiply.
1145
+ * @param sourceColumn Source @ref Entry range.
1146
+ * @param targetColumnIndex @ref MatIdx index of the target column.
1147
+ */
1148
+ template <class Entry_range>
1149
+ std::enable_if_t<!std::is_integral_v<Entry_range> > multiply_source_and_add_to(int coefficient,
1150
+ const Entry_range& sourceColumn,
1151
+ Index targetColumnIndex);
1152
+
1153
+ /**
1154
+ * @brief Zeroes the entry at the given coordinates. Not available for @ref chainmatrix "chain matrices" and for
1155
+ * @ref basematrix "base matrices" with column compression. In general, should be used with care with
1156
+ * @ref mp_matrices "non-basic matrices" to not destroy the validity of the persistence related properties of the
1157
+ * matrix.
1158
+ *
1159
+ * For @ref boundarymatrix "RU matrices", equivalent to
1160
+ * @ref zero_entry(Index columnIndex, ID_index rowIndex, bool inR) "zero_entry(columnIndex, rowIndex, true)".
1161
+ *
1162
+ * @param columnIndex @ref MatIdx index of the column of the entry.
1163
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
1164
+ */
1165
+ void zero_entry(Index columnIndex, ID_index rowIndex);
1166
+ /**
1167
+ * @brief Only available for @ref boundarymatrix "RU matrices". Zeroes the entry at the given coordinates in \f$ R \f$
1168
+ * if @p inR is true or in \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the
1169
+ * persistence related properties of the matrix.
1170
+ *
1171
+ * @param columnIndex @ref MatIdx index of the column of the entry.
1172
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
1173
+ * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$.
1174
+ */
1175
+ void zero_entry(Index columnIndex, ID_index rowIndex, bool inR);
1176
+ /**
1177
+ * @brief Zeroes the column at the given index. Not available for @ref chainmatrix "chain matrices" and for
1178
+ * @ref basematrix "base matrices" with column compression. In general, should be used with care with
1179
+ * @ref mp_matrices "non-basic matrices" to not destroy the validity of the persistence related properties of the
1180
+ * matrix.
1181
+ *
1182
+ * For @ref boundarymatrix "RU matrices", equivalent to
1183
+ * @ref zero_column(Index columnIndex, bool inR) "zero_column(columnIndex, true)".
1184
+ *
1185
+ * @param columnIndex @ref MatIdx index of the column to zero.
1186
+ */
1187
+ void zero_column(Index columnIndex);
1188
+ /**
1189
+ * @brief Only available for @ref boundarymatrix "RU matrices". Zeroes the column at the given index in \f$ R \f$ if
1190
+ * @p inR is true or in \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the
1191
+ * persistence related properties of the matrix.
1192
+ *
1193
+ * @param columnIndex @ref MatIdx index of the column to zero.
1194
+ * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$.
1195
+ */
1196
+ void zero_column(Index columnIndex, bool inR);
1197
+ /**
1198
+ * @brief Indicates if the entry at given coordinates has value zero.
1199
+ *
1200
+ * For @ref boundarymatrix "RU matrices", equivalent to
1201
+ * @ref is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const
1202
+ * "is_zero_entry(columnIndex, rowIndex, true)".
1203
+ *
1204
+ * @param columnIndex @ref MatIdx index of the column of the entry.
1205
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
1206
+ * @return true If the entry has value zero.
1207
+ * @return false Otherwise.
1208
+ */
1209
+ bool is_zero_entry(Index columnIndex, ID_index rowIndex);
1210
+ /**
1211
+ * @brief Only available for @ref boundarymatrix "RU matrices". Indicates if the entry at given coordinates has value
1212
+ * zero in \f$ R \f$ if @p inR is true or in \f$ U \f$ if @p inR is false.
1213
+ *
1214
+ * @param columnIndex @ref MatIdx index of the column of the entry.
1215
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
1216
+ * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$.
1217
+ * @return true If the entry has value zero.
1218
+ * @return false Otherwise.
1219
+ */
1220
+ bool is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const;
1221
+ /**
1222
+ * @brief Indicates if the column at given index has value zero.
1223
+ *
1224
+ * For @ref boundarymatrix "RU matrices", equivalent to
1225
+ * @ref is_zero_column(Index columnIndex, bool inR) "is_zero_column(columnIndex, true)".
1226
+ *
1227
+ * Note that for @ref chainmatrix "chain matrices", this method should always return false, as a valid
1228
+ * @ref chainmatrix "chain matrix" never has empty columns.
1229
+ *
1230
+ * @param columnIndex @ref MatIdx index of the column.
1231
+ * @return true If the column has value zero.
1232
+ * @return false Otherwise.
1233
+ */
1234
+ bool is_zero_column(Index columnIndex);
1235
+ /**
1236
+ * @brief Only available for @ref boundarymatrix "RU matrices". Indicates if the column at given index has value zero
1237
+ * in \f$ R \f$ if @p inR is true or in \f$ U \f$ if @p inR is false.
1238
+ *
1239
+ * Note that if @p inR is false, this method should usually return false.
1240
+ *
1241
+ * @param columnIndex @ref MatIdx index of the column.
1242
+ * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$.
1243
+ * @return true If the column has value zero.
1244
+ * @return false Otherwise.
1245
+ */
1246
+ bool is_zero_column(Index columnIndex, bool inR);
1247
+
1248
+ /**
1249
+ * @brief Returns the @ref MatIdx index of the column which has the given @ref rowindex "row index" as pivot. Only
1250
+ * available for @ref boundarymatrix "RU" and @ref chainmatrix "chain matrices". Assumes that the pivot exists. For
1251
+ * @ref boundarymatrix "RU matrices", the column is returned from \f$ R \f$.
1252
+ *
1253
+ * Recall that the @ref rowindex "row indices" for @ref chainmatrix "chain matrices" correspond to the @ref IDIdx
1254
+ * indices and that the @ref rowindex "row indices" for a @ref boundarymatrix "RU matrix" correspond to the updated
1255
+ * @ref IDIdx indices which got potentially swapped by a vine swap.
1256
+ *
1257
+ * @param cellIndex @ref rowindex "Row index" of the pivot.
1258
+ * @return @ref MatIdx index of the column with the given pivot.
1259
+ */
1260
+ Index get_column_with_pivot(ID_index cellIndex) const;
1261
+ /**
1262
+ * @brief Returns the @ref rowindex "row index" of the pivot of the given column. Only available for
1263
+ * @ref mp_matrices "non-basic matrices".
1264
+ *
1265
+ * @param columnIndex @ref MatIdx index of the column
1266
+ * @return The @ref rowindex "row index" of the pivot.
1267
+ */
1268
+ ID_index get_pivot(Index columnIndex);
1269
+
1270
+ /**
1271
+ * @brief Assign operator.
1272
+ *
1273
+ * @param other %Matrix to copy
1274
+ * @return Reference to this object.
1275
+ */
1276
+ Matrix& operator=(Matrix other) &;
1277
+ /**
1278
+ * @brief Assign operator.
1279
+ *
1280
+ * @param other %Matrix to move
1281
+ * @return Reference to this object.
1282
+ */
1283
+ Matrix& operator=(Matrix&& other) && noexcept;
1284
+
1285
+ /**
1286
+ * @brief Swap operator for two matrices.
1287
+ *
1288
+ * @param matrix1 First matrix to swap.
1289
+ * @param matrix2 Second matrix to swap.
1290
+ */
1291
+ friend void swap(Matrix& matrix1, Matrix& matrix2) noexcept
1292
+ {
1293
+ swap(matrix1.matrix_, matrix2.matrix_);
1294
+ std::swap(matrix1.colSettings_, matrix2.colSettings_);
1295
+ }
1296
+
1297
+ void print(); // for debug
1298
+
1299
+ // TODO: change the behaviour for boundary matrices.
1300
+ /**
1301
+ * @brief Returns the current barcode of the matrix. Available only if
1302
+ * @ref PersistenceMatrixOptions::has_column_pairings is true.
1303
+ *
1304
+ * Recall that we assume that the boundaries were inserted in the order of filtration for the barcode to be valid.
1305
+ *
1306
+ * @warning For simple @ref boundarymatrix "boundary matrices" (only storing \f$ R \f$), we assume that
1307
+ * @ref get_current_barcode is only called once the matrix is completed and won't be modified again.
1308
+ *
1309
+ * @return A reference to the barcode. The barcode is a vector of @ref Matrix::Bar. A bar stores three information:
1310
+ * the @ref PosIdx birth index, the @ref PosIdx death index and the dimension of the bar.
1311
+ */
1312
+ const Barcode& get_current_barcode();
1313
+ /**
1314
+ * @brief Returns the current barcode of the matrix. Available only if
1315
+ * @ref PersistenceMatrixOptions::has_column_pairings is true.
1316
+ *
1317
+ * Recall that we assume that the boundaries were inserted in the order of filtration for the barcode to be valid.
1318
+ *
1319
+ * @warning For simple @ref boundarymatrix "boundary matrices" (only storing \f$ R \f$), we assume that
1320
+ * @ref get_current_barcode is only called once the matrix is completed and won't be modified again.
1321
+ *
1322
+ * @return A const reference to the barcode. The barcode is a vector of @ref Matrix::Bar. A bar stores three
1323
+ * information: the @ref PosIdx birth index, the @ref PosIdx death index and the dimension of the bar.
1324
+ */
1325
+ const Barcode& get_current_barcode() const;
1326
+
1327
+ /**
1328
+ * @brief Only available for @ref basematrix "base matrices" without column compression and simple
1329
+ * @ref boundarymatrix "boundary matrices" (only storing \f$ R \f$) and if
1330
+ * @ref PersistenceMatrixOptions::has_column_and_row_swaps is true. Swaps the two given columns. Note for
1331
+ * @ref boundarymatrix "boundary matrices", that it really just swaps two columns and does not update anything else,
1332
+ * nor performs additions to maintain some properties on the matrix.
1333
+ *
1334
+ * @param columnIndex1 First column @ref MatIdx index to swap.
1335
+ * @param columnIndex2 Second column @ref MatIdx index to swap.
1336
+ */
1337
+ void swap_columns(Index columnIndex1, Index columnIndex2);
1338
+ /**
1339
+ * @brief Only available for @ref basematrix "base matrices" without column compression and simple
1340
+ * @ref boundarymatrix "boundary matrices" (only storing \f$ R \f$) and if
1341
+ * @ref PersistenceMatrixOptions::has_column_and_row_swaps is true. Swaps the two given rows. Note for
1342
+ * @ref boundarymatrix "boundary matrices", that it really just swaps two rows and does not update anything else,
1343
+ * nor performs additions to maintain some properties on the matrix.
1344
+ *
1345
+ * @param rowIndex1 First @ref rowindex "row index" to swap.
1346
+ * @param rowIndex2 Second @ref rowindex "row index" to swap.
1347
+ */
1348
+ void swap_rows(Index rowIndex1, Index rowIndex2);
1349
+ // TODO: find better name. And benchmark also to verify if it is really worth it to have this extra version in
1350
+ // addition to vine_swap.
1351
+ /**
1352
+ * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a boundary
1353
+ * matrix or @ref PersistenceMatrixOptions::column_indexation_type is set to @ref Column_indexation_types::POSITION.
1354
+ * Does the same than @ref vine_swap, but assumes that the swap is non trivial and therefore skips a part of the case
1355
+ * study.
1356
+ *
1357
+ * @param index @ref PosIdx index of the first cell to swap. The second one has to be at `index + 1`. Recall that for
1358
+ * @ref boundarymatrix "boundary matrices", @ref PosIdx == @ref MatIdx.
1359
+ * @return true If the barcode changed from the swap.
1360
+ * @return false Otherwise.
1361
+ */
1362
+ bool vine_swap_with_z_eq_1_case(Pos_index index);
1363
+ /**
1364
+ * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a
1365
+ * @ref chainmatrix "chain matrix" or @ref PersistenceMatrixOptions::column_indexation_type is set to
1366
+ * @ref Column_indexation_types::IDENTIFIER. Does the same than @ref vine_swap, but assumes that the swap is
1367
+ * non-trivial and therefore skips a part of the case study.
1368
+ *
1369
+ * @param columnIndex1 @ref MatIdx index of the first cell.
1370
+ * @param columnIndex2 @ref MatIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs
1371
+ * by one.
1372
+ * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of
1373
+ * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx
1374
+ * \f$ max(pos1, pos2) \f$.
1375
+ */
1376
+ Index vine_swap_with_z_eq_1_case(Index columnIndex1, Index columnIndex2);
1377
+ /**
1378
+ * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a
1379
+ * @ref boundarymatrix "boundary matrix" or @ref PersistenceMatrixOptions::column_indexation_type is set to
1380
+ * @ref Column_indexation_types::POSITION. Does a vine swap between two cells which are consecutive in the
1381
+ * filtration. Roughly, if \f$ F \f$ is the current filtration represented by the matrix, the method modifies the
1382
+ * matrix such that the new state corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but
1383
+ * with the two cells at position `index` and `index + 1` swapped. Of course, the two cells should not have a
1384
+ * face/coface relation which each other ; \f$ F' \f$ has to be a valid filtration.
1385
+ * See @cite vineyards for more information about vine and vineyards.
1386
+ *
1387
+ * @param index @ref PosIdx index of the first cell to swap. The second one has to be at `index + 1`. Recall that for
1388
+ * @ref boundarymatrix "boundary matrices", @ref PosIdx == @ref MatIdx.
1389
+ * @return true If the barcode changed from the swap.
1390
+ * @return false Otherwise.
1391
+ */
1392
+ bool vine_swap(Pos_index index);
1393
+ /**
1394
+ * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a
1395
+ * @ref chainmatrix "chain matrix" or @ref PersistenceMatrixOptions::column_indexation_type is set to
1396
+ * @ref Column_indexation_types::IDENTIFIER. Does a vine swap between two cells which are consecutive in the
1397
+ * filtration. Roughly, if \f$ F \f$ is the current filtration represented by the matrix, the method modifies the
1398
+ * matrix such that the new state corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but
1399
+ * with the two given cells at swapped positions. Of course, the two cells should not have a face/coface relation
1400
+ * which each other ; \f$ F' \f$ has to be a valid filtration.
1401
+ * See @cite vineyards for more information about vine and vineyards.
1402
+ *
1403
+ * @param columnIndex1 @ref MatIdx index of the first cell.
1404
+ * @param columnIndex2 @ref MatIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs
1405
+ * by one.
1406
+ * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of
1407
+ * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx
1408
+ * \f$ max(pos1, pos2) \f$.
1409
+ */
1410
+ Index vine_swap(Index columnIndex1, Index columnIndex2);
1411
+
1412
+ /**
1413
+ * @brief Only available if @ref PersistenceMatrixOptions::can_retrieve_representative_cycles is true. Pre-computes
1414
+ * the representative cycles of the current state of the filtration represented by the matrix. It needs to be called
1415
+ * before calling @ref get_representative_cycles if the matrix was modified since last call. Otherwise the old cycles
1416
+ * will be returned.
1417
+ *
1418
+ * @param dim If different from default value, only the cycles of the given dimension are updated.
1419
+ * All others are erased.
1420
+ */
1421
+ void update_representative_cycles(Dimension dim = get_null_value<Dimension>());
1422
+ /**
1423
+ * @brief Only available if @ref PersistenceMatrixOptions::can_retrieve_representative_cycles is true. Pre-computes
1424
+ * the representative cycle in the current matrix state of the given bar. It needs to be called
1425
+ * before calling @ref get_representative_cycle if the matrix was modified since last call. Otherwise the old cycle
1426
+ * will be returned.
1427
+ *
1428
+ * @param bar Bar corresponding to the wanted representative cycle.
1429
+ */
1430
+ void update_representative_cycle(const Bar& bar);
1431
+ /**
1432
+ * @brief Only available if @ref PersistenceMatrixOptions::can_retrieve_representative_cycles is true.
1433
+ * Returns all representative cycles of the current filtration. @ref update_representative_cycles has to be called
1434
+ * first if a modification to the matrix has to be token into account since last call.
1435
+ *
1436
+ * @return A const reference to the vector of representative cycles.
1437
+ */
1438
+ const std::vector<Cycle>& get_representative_cycles();
1439
+ /**
1440
+ * @brief Only available if @ref PersistenceMatrixOptions::can_retrieve_representative_cycles is true.
1441
+ * Returns the cycle representing the given bar. @ref update_representative_cycles or
1442
+ * @ref update_representative_cycle have to be called first if a modification to the matrix has to be token into
1443
+ * account since last call.
1444
+ *
1445
+ * @param bar A bar from the current barcode.
1446
+ * @return A const reference to the cycle representing @p bar.
1447
+ */
1448
+ const Cycle& get_representative_cycle(const Bar& bar);
1449
+
1450
+ private:
1451
+ using Underlying_matrix = std::conditional_t<
1452
+ isNonBasic,
1453
+ std::conditional_t<
1454
+ PersistenceMatrixOptions::is_of_boundary_type,
1455
+ std::conditional_t<
1456
+ PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles,
1457
+ std::conditional_t<
1458
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER ||
1459
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION,
1460
+ Master_RU_matrix,
1461
+ Id_to_index_overlay<Master_RU_matrix, Matrix<PersistenceMatrixOptions>
1462
+ > >,
1463
+ std::conditional_t<
1464
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER ||
1465
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION,
1466
+ Master_boundary_matrix,
1467
+ Id_to_index_overlay<Master_boundary_matrix, Matrix<PersistenceMatrixOptions>
1468
+ > > >,
1469
+ std::conditional_t<
1470
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER,
1471
+ Master_chain_matrix,
1472
+ std::conditional_t<PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION,
1473
+ Position_to_index_overlay<Master_chain_matrix, Matrix<PersistenceMatrixOptions> >,
1474
+ Id_to_index_overlay<Master_chain_matrix, Matrix<PersistenceMatrixOptions>
1475
+ > > > >,
1476
+ Master_base_matrix>;
1477
+
1478
+ // Field_operators* operators_;
1479
+ // Entry_constructor* entryPool_;
1480
+ Column_settings* colSettings_; // pointer because the of swap operator on matrix_ which also stores the pointer
1481
+ Underlying_matrix matrix_;
1482
+
1483
+ static constexpr void _assert_options();
1484
+
1485
+ Element _get_value(int coefficient) const;
1486
+ };
1487
+
1488
+ template <class PersistenceMatrixOptions>
1489
+ inline Matrix<PersistenceMatrixOptions>::Matrix() : colSettings_(new Column_settings()), matrix_(colSettings_)
1490
+ {
1491
+ static_assert(
1492
+ PersistenceMatrixOptions::is_of_boundary_type || !PersistenceMatrixOptions::has_vine_update ||
1493
+ PersistenceMatrixOptions::has_column_pairings,
1494
+ "When no barcode is recorded with vine swaps, comparison functions for the columns have to be provided.");
1495
+ _assert_options();
1496
+ }
1497
+
1498
+ template <class PersistenceMatrixOptions>
1499
+ template <class Container>
1500
+ inline Matrix<PersistenceMatrixOptions>::Matrix(const std::vector<Container>& columns, Characteristic characteristic)
1501
+ : colSettings_(new Column_settings(characteristic)), matrix_(columns, colSettings_)
1502
+ {
1503
+ static_assert(PersistenceMatrixOptions::is_of_boundary_type || !PersistenceMatrixOptions::has_vine_update ||
1504
+ PersistenceMatrixOptions::has_column_pairings,
1505
+ "When no barcode is recorded with vine swaps for chain matrices, comparison functions for the columns "
1506
+ "have to be provided.");
1507
+ _assert_options();
1508
+ }
1509
+
1510
+ template <class PersistenceMatrixOptions>
1511
+ inline Matrix<PersistenceMatrixOptions>::Matrix(unsigned int numberOfColumns, Characteristic characteristic)
1512
+ : colSettings_(new Column_settings(characteristic)), matrix_(numberOfColumns, colSettings_)
1513
+ {
1514
+ static_assert(PersistenceMatrixOptions::is_of_boundary_type || !PersistenceMatrixOptions::has_vine_update ||
1515
+ PersistenceMatrixOptions::has_column_pairings,
1516
+ "When no barcode is recorded with vine swaps for chain matrices, comparison functions for the columns "
1517
+ "have to be provided.");
1518
+ _assert_options();
1519
+ }
1520
+
1521
+ template <class PersistenceMatrixOptions>
1522
+ inline Matrix<PersistenceMatrixOptions>::Matrix(const std::function<bool(Pos_index, Pos_index)>& birthComparator,
1523
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator)
1524
+ : colSettings_(new Column_settings()), matrix_(colSettings_, birthComparator, deathComparator)
1525
+ {
1526
+ static_assert(
1527
+ !PersistenceMatrixOptions::is_of_boundary_type && PersistenceMatrixOptions::has_vine_update &&
1528
+ !PersistenceMatrixOptions::has_column_pairings,
1529
+ "Constructor only available for chain matrices when vine swaps are enabled, but the barcode is not recorded.");
1530
+ _assert_options();
1531
+ }
1532
+
1533
+ template <class PersistenceMatrixOptions>
1534
+ template <class Boundary_range>
1535
+ inline Matrix<PersistenceMatrixOptions>::Matrix(const std::vector<Boundary_range>& orderedBoundaries,
1536
+ const std::function<bool(Pos_index, Pos_index)>& birthComparator,
1537
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator,
1538
+ Characteristic characteristic)
1539
+ : colSettings_(new Column_settings(characteristic)),
1540
+ matrix_(orderedBoundaries, colSettings_, birthComparator, deathComparator)
1541
+ {
1542
+ static_assert(
1543
+ !PersistenceMatrixOptions::is_of_boundary_type && PersistenceMatrixOptions::has_vine_update &&
1544
+ !PersistenceMatrixOptions::has_column_pairings,
1545
+ "Constructor only available for chain matrices when vine swaps are enabled, but the barcode is not recorded.");
1546
+ _assert_options();
1547
+ }
1548
+
1549
+ template <class PersistenceMatrixOptions>
1550
+ inline Matrix<PersistenceMatrixOptions>::Matrix(unsigned int numberOfColumns,
1551
+ const std::function<bool(Pos_index, Pos_index)>& birthComparator,
1552
+ const std::function<bool(Pos_index, Pos_index)>& deathComparator,
1553
+ Characteristic characteristic)
1554
+ : colSettings_(new Column_settings(characteristic)),
1555
+ matrix_(numberOfColumns, colSettings_, birthComparator, deathComparator)
1556
+ {
1557
+ static_assert(
1558
+ !PersistenceMatrixOptions::is_of_boundary_type && PersistenceMatrixOptions::has_vine_update &&
1559
+ !PersistenceMatrixOptions::has_column_pairings,
1560
+ "Constructor only available for chain matrices when vine swaps are enabled, but the barcode is not recorded.");
1561
+ _assert_options();
1562
+ }
1563
+
1564
+ template <class PersistenceMatrixOptions>
1565
+ inline Matrix<PersistenceMatrixOptions>::Matrix(const Matrix& matrixToCopy)
1566
+ : colSettings_(new Column_settings(*matrixToCopy.colSettings_)), matrix_(matrixToCopy.matrix_, colSettings_)
1567
+ {
1568
+ _assert_options();
1569
+ }
1570
+
1571
+ template <class PersistenceMatrixOptions>
1572
+ inline Matrix<PersistenceMatrixOptions>::Matrix(Matrix&& other) noexcept
1573
+ : colSettings_(std::exchange(other.colSettings_, nullptr)), matrix_(std::move(other.matrix_))
1574
+ {
1575
+ _assert_options();
1576
+ }
1577
+
1578
+ template <class PersistenceMatrixOptions>
1579
+ inline Matrix<PersistenceMatrixOptions>::~Matrix()
1580
+ {
1581
+ matrix_.reset(colSettings_); // to avoid crashes at destruction, all columns have to be destroyed first
1582
+ delete colSettings_;
1583
+ }
1584
+
1585
+ template <class PersistenceMatrixOptions>
1586
+ inline void Matrix<PersistenceMatrixOptions>::set_characteristic(Characteristic characteristic)
1587
+ {
1588
+ if constexpr (!PersistenceMatrixOptions::is_z2) {
1589
+ if (colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic) {
1590
+ std::cerr << "Warning: Characteristic already initialised. Changing it could lead to incoherences in the matrix "
1591
+ "as the modulo was already applied to values in existing columns.";
1592
+ }
1593
+
1594
+ colSettings_->operators.set_characteristic(characteristic);
1595
+ }
1596
+ }
1597
+
1598
+ template <class PersistenceMatrixOptions>
1599
+ template <class Container, class>
1600
+ inline void Matrix<PersistenceMatrixOptions>::insert_column(const Container& column)
1601
+ {
1602
+ if constexpr (!PersistenceMatrixOptions::is_z2) {
1603
+ GUDHI_CHECK(colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic,
1604
+ std::logic_error("Matrix::insert_column - Columns cannot be initialized if the coefficient field "
1605
+ "characteristic is not specified."));
1606
+ }
1607
+
1608
+ static_assert(
1609
+ !isNonBasic,
1610
+ "'insert_column' not available for the chosen options. The input has to be in the form of a cell boundary.");
1611
+ matrix_.insert_column(column);
1612
+ }
1613
+
1614
+ template <class PersistenceMatrixOptions>
1615
+ template <class Container, class>
1616
+ inline void Matrix<PersistenceMatrixOptions>::insert_column(const Container& column, Index columnIndex)
1617
+ {
1618
+ if constexpr (!PersistenceMatrixOptions::is_z2) {
1619
+ GUDHI_CHECK(colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic,
1620
+ std::logic_error("Matrix::insert_column - Columns cannot be initialized if the coefficient field "
1621
+ "characteristic is not specified."));
1622
+ }
1623
+
1624
+ static_assert(!isNonBasic && !PersistenceMatrixOptions::has_column_compression,
1625
+ "'insert_column' with those parameters is not available for the chosen options.");
1626
+ static_assert(!PersistenceMatrixOptions::has_row_access,
1627
+ "Columns have to be inserted at the end of the matrix when row access is enabled.");
1628
+ matrix_.insert_column(column, columnIndex);
1629
+ }
1630
+
1631
+ template <class PersistenceMatrixOptions>
1632
+ inline void Matrix<PersistenceMatrixOptions>::insert_column(ID_index idx, [[maybe_unused]] Element e)
1633
+ {
1634
+ static_assert(
1635
+ !isNonBasic,
1636
+ "'insert_column' not available for the chosen options. The input has to be in the form of a cell boundary.");
1637
+
1638
+ if constexpr (PersistenceMatrixOptions::is_z2) {
1639
+ matrix_.insert_column(idx);
1640
+ } else {
1641
+ GUDHI_CHECK(colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic,
1642
+ std::logic_error("Matrix::insert_column - Columns cannot be initialized if the coefficient field "
1643
+ "characteristic is not specified."));
1644
+ matrix_.insert_column(idx, e);
1645
+ }
1646
+ }
1647
+
1648
+ template <class PersistenceMatrixOptions>
1649
+ template <class Boundary_range>
1650
+ inline typename Matrix<PersistenceMatrixOptions>::Insertion_return Matrix<PersistenceMatrixOptions>::insert_boundary(
1651
+ const Boundary_range& boundary,
1652
+ Dimension dim)
1653
+ {
1654
+ if constexpr (!PersistenceMatrixOptions::is_z2) {
1655
+ GUDHI_CHECK(colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic,
1656
+ std::logic_error("Matrix::insert_boundary - Columns cannot be initialized if the coefficient field "
1657
+ "characteristic is not specified."));
1658
+ }
1659
+
1660
+ if constexpr (isNonBasic && !PersistenceMatrixOptions::is_of_boundary_type &&
1661
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER)
1662
+ return matrix_.insert_boundary(boundary, dim);
1663
+ else
1664
+ matrix_.insert_boundary(boundary, dim);
1665
+ }
1666
+
1667
+ template <class PersistenceMatrixOptions>
1668
+ template <class Boundary_range>
1669
+ inline typename Matrix<PersistenceMatrixOptions>::Insertion_return
1670
+ Matrix<PersistenceMatrixOptions>::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim)
1671
+ {
1672
+ if constexpr (!PersistenceMatrixOptions::is_z2) {
1673
+ GUDHI_CHECK(colSettings_->operators.get_characteristic() != Field_operators::nullCharacteristic,
1674
+ std::logic_error("Matrix::insert_boundary - Columns cannot be initialized if the coefficient field "
1675
+ "characteristic is not specified."));
1676
+ }
1677
+
1678
+ static_assert(isNonBasic, "Only enabled for non-basic matrices.");
1679
+ if constexpr (!PersistenceMatrixOptions::is_of_boundary_type &&
1680
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER)
1681
+ return matrix_.insert_boundary(cellIndex, boundary, dim);
1682
+ else
1683
+ matrix_.insert_boundary(cellIndex, boundary, dim);
1684
+ }
1685
+
1686
+ template <class PersistenceMatrixOptions>
1687
+ inline typename Matrix<PersistenceMatrixOptions>::Returned_column& Matrix<PersistenceMatrixOptions>::get_column(
1688
+ Index columnIndex)
1689
+ {
1690
+ return matrix_.get_column(columnIndex);
1691
+ }
1692
+
1693
+ template <class PersistenceMatrixOptions>
1694
+ inline const typename Matrix<PersistenceMatrixOptions>::Column& Matrix<PersistenceMatrixOptions>::get_column(
1695
+ Index columnIndex) const
1696
+ {
1697
+ return matrix_.get_column(columnIndex);
1698
+ }
1699
+
1700
+ template <class PersistenceMatrixOptions>
1701
+ inline const typename Matrix<PersistenceMatrixOptions>::Column& Matrix<PersistenceMatrixOptions>::get_column(
1702
+ Index columnIndex,
1703
+ bool inR)
1704
+ {
1705
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1706
+ static_assert(
1707
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1708
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1709
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1710
+ "Only enabled for position indexed RU matrices.");
1711
+
1712
+ return matrix_.get_column(columnIndex, inR);
1713
+ }
1714
+
1715
+ template <class PersistenceMatrixOptions>
1716
+ inline typename Matrix<PersistenceMatrixOptions>::Returned_row& Matrix<PersistenceMatrixOptions>::get_row(
1717
+ ID_index rowIndex)
1718
+ {
1719
+ static_assert(PersistenceMatrixOptions::has_row_access, "'get_row' is not available for the chosen options.");
1720
+
1721
+ return matrix_.get_row(rowIndex);
1722
+ }
1723
+
1724
+ template <class PersistenceMatrixOptions>
1725
+ inline const typename Matrix<PersistenceMatrixOptions>::Row& Matrix<PersistenceMatrixOptions>::get_row(
1726
+ ID_index rowIndex) const
1727
+ {
1728
+ static_assert(PersistenceMatrixOptions::has_row_access, "'get_row' is not available for the chosen options.");
1729
+
1730
+ return matrix_.get_row(rowIndex);
1731
+ }
1732
+
1733
+ template <class PersistenceMatrixOptions>
1734
+ inline const typename Matrix<PersistenceMatrixOptions>::Row& Matrix<PersistenceMatrixOptions>::get_row(
1735
+ ID_index rowIndex,
1736
+ bool inR)
1737
+ {
1738
+ static_assert(PersistenceMatrixOptions::has_row_access, "'get_row' is not available for the chosen options.");
1739
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1740
+ static_assert(
1741
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1742
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1743
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1744
+ "Only enabled for position indexed RU matrices.");
1745
+
1746
+ return matrix_.get_row(rowIndex, inR);
1747
+ }
1748
+
1749
+ template <class PersistenceMatrixOptions>
1750
+ inline void Matrix<PersistenceMatrixOptions>::remove_column(Index columnIndex)
1751
+ {
1752
+ static_assert(PersistenceMatrixOptions::has_map_column_container && !isNonBasic &&
1753
+ !PersistenceMatrixOptions::has_column_compression,
1754
+ "'remove_column' is not available for the chosen options.");
1755
+
1756
+ matrix_.remove_column(columnIndex);
1757
+ }
1758
+
1759
+ template <class PersistenceMatrixOptions>
1760
+ inline void Matrix<PersistenceMatrixOptions>::erase_empty_row(ID_index rowIndex)
1761
+ {
1762
+ static_assert(
1763
+ !isNonBasic || PersistenceMatrixOptions::is_of_boundary_type || PersistenceMatrixOptions::has_removable_rows,
1764
+ "'erase_empty_row' is not available for the chosen options.");
1765
+
1766
+ matrix_.erase_empty_row(rowIndex);
1767
+ }
1768
+
1769
+ template <class PersistenceMatrixOptions>
1770
+ inline void Matrix<PersistenceMatrixOptions>::remove_maximal_cell(Index columnIndex)
1771
+ {
1772
+ static_assert(PersistenceMatrixOptions::has_removable_columns,
1773
+ "'remove_maximal_cell(ID_index)' is not available for the chosen options.");
1774
+ static_assert(isNonBasic && PersistenceMatrixOptions::has_vine_update,
1775
+ "'remove_maximal_cell(ID_index)' is not available for the chosen options.");
1776
+ static_assert(PersistenceMatrixOptions::is_of_boundary_type || (PersistenceMatrixOptions::has_map_column_container &&
1777
+ PersistenceMatrixOptions::has_column_pairings),
1778
+ "'remove_maximal_cell(ID_index)' is not available for the chosen options.");
1779
+
1780
+ matrix_.remove_maximal_cell(columnIndex);
1781
+ }
1782
+
1783
+ template <class PersistenceMatrixOptions>
1784
+ inline void Matrix<PersistenceMatrixOptions>::remove_maximal_cell(ID_index cellIndex,
1785
+ const std::vector<ID_index>& columnsToSwap)
1786
+ {
1787
+ static_assert(PersistenceMatrixOptions::has_removable_columns,
1788
+ "'remove_maximal_cell(ID_index,const std::vector<Index>&)' is not available for the chosen options.");
1789
+ static_assert(isNonBasic && !PersistenceMatrixOptions::is_of_boundary_type,
1790
+ "'remove_maximal_cell(ID_index,const std::vector<Index>&)' is not available for the chosen options.");
1791
+ static_assert(PersistenceMatrixOptions::has_map_column_container && PersistenceMatrixOptions::has_vine_update,
1792
+ "'remove_maximal_cell(ID_index,const std::vector<Index>&)' is not available for the chosen options.");
1793
+
1794
+ matrix_.remove_maximal_cell(cellIndex, columnsToSwap);
1795
+ }
1796
+
1797
+ template <class PersistenceMatrixOptions>
1798
+ inline void Matrix<PersistenceMatrixOptions>::remove_last()
1799
+ {
1800
+ static_assert(PersistenceMatrixOptions::has_removable_columns || !isNonBasic,
1801
+ "'remove_last' is not available for the chosen options.");
1802
+ static_assert(!PersistenceMatrixOptions::has_column_compression || isNonBasic,
1803
+ "'remove_last' is not available for the chosen options.");
1804
+ static_assert(!isNonBasic || PersistenceMatrixOptions::is_of_boundary_type ||
1805
+ PersistenceMatrixOptions::has_map_column_container || !PersistenceMatrixOptions::has_vine_update,
1806
+ "'remove_last' is not available for the chosen options.");
1807
+
1808
+ matrix_.remove_last();
1809
+ }
1810
+
1811
+ template <class PersistenceMatrixOptions>
1812
+ inline typename Matrix<PersistenceMatrixOptions>::Dimension Matrix<PersistenceMatrixOptions>::get_max_dimension() const
1813
+ {
1814
+ static_assert(isNonBasic, "'get_max_dimension' is not available for the chosen options.");
1815
+
1816
+ return matrix_.get_max_dimension();
1817
+ }
1818
+
1819
+ template <class PersistenceMatrixOptions>
1820
+ inline typename Matrix<PersistenceMatrixOptions>::Index Matrix<PersistenceMatrixOptions>::get_number_of_columns() const
1821
+ {
1822
+ return matrix_.get_number_of_columns();
1823
+ }
1824
+
1825
+ template <class PersistenceMatrixOptions>
1826
+ inline typename Matrix<PersistenceMatrixOptions>::Dimension Matrix<PersistenceMatrixOptions>::get_column_dimension(
1827
+ Index columnIndex) const
1828
+ {
1829
+ static_assert(isNonBasic, "'get_column_dimension' is not available for the chosen options.");
1830
+
1831
+ return matrix_.get_column_dimension(columnIndex);
1832
+ }
1833
+
1834
+ template <class PersistenceMatrixOptions>
1835
+ template <typename Integer_index>
1836
+ inline std::enable_if_t<std::is_integral_v<Integer_index> > Matrix<PersistenceMatrixOptions>::add_to(
1837
+ Integer_index sourceColumnIndex,
1838
+ Integer_index targetColumnIndex)
1839
+ {
1840
+ matrix_.add_to(sourceColumnIndex, targetColumnIndex);
1841
+ }
1842
+
1843
+ template <class PersistenceMatrixOptions>
1844
+ template <class Entry_range>
1845
+ inline std::enable_if_t<!std::is_integral_v<Entry_range> > Matrix<PersistenceMatrixOptions>::add_to(
1846
+ const Entry_range& sourceColumn,
1847
+ Index targetColumnIndex)
1848
+ {
1849
+ static_assert(!isNonBasic,
1850
+ "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain "
1851
+ "algebraic consistency.");
1852
+
1853
+ matrix_.add_to(sourceColumn, targetColumnIndex);
1854
+ }
1855
+
1856
+ template <class PersistenceMatrixOptions>
1857
+ template <typename Integer_index>
1858
+ inline std::enable_if_t<std::is_integral_v<Integer_index> >
1859
+ Matrix<PersistenceMatrixOptions>::multiply_target_and_add_to(Integer_index sourceColumnIndex,
1860
+ int coefficient,
1861
+ Integer_index targetColumnIndex)
1862
+ {
1863
+ matrix_.multiply_target_and_add_to(sourceColumnIndex, _get_value(coefficient), targetColumnIndex);
1864
+ }
1865
+
1866
+ template <class PersistenceMatrixOptions>
1867
+ template <class Entry_range>
1868
+ inline std::enable_if_t<!std::is_integral_v<Entry_range> > Matrix<PersistenceMatrixOptions>::multiply_target_and_add_to(
1869
+ const Entry_range& sourceColumn,
1870
+ int coefficient,
1871
+ Index targetColumnIndex)
1872
+ {
1873
+ static_assert(!isNonBasic,
1874
+ "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain "
1875
+ "algebraic consistency.");
1876
+
1877
+ matrix_.multiply_target_and_add_to(sourceColumn, _get_value(coefficient), targetColumnIndex);
1878
+ }
1879
+
1880
+ template <class PersistenceMatrixOptions>
1881
+ template <typename Integer_index>
1882
+ inline std::enable_if_t<std::is_integral_v<Integer_index> >
1883
+ Matrix<PersistenceMatrixOptions>::multiply_source_and_add_to(int coefficient,
1884
+ Integer_index sourceColumnIndex,
1885
+ Integer_index targetColumnIndex)
1886
+ {
1887
+ matrix_.multiply_source_and_add_to(_get_value(coefficient), sourceColumnIndex, targetColumnIndex);
1888
+ }
1889
+
1890
+ template <class PersistenceMatrixOptions>
1891
+ template <class Entry_range>
1892
+ inline std::enable_if_t<!std::is_integral_v<Entry_range> > Matrix<PersistenceMatrixOptions>::multiply_source_and_add_to(
1893
+ int coefficient,
1894
+ const Entry_range& sourceColumn,
1895
+ Index targetColumnIndex)
1896
+ {
1897
+ static_assert(!isNonBasic,
1898
+ "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain "
1899
+ "algebraic consistency.");
1900
+
1901
+ matrix_.multiply_source_and_add_to(_get_value(coefficient), sourceColumn, targetColumnIndex);
1902
+ }
1903
+
1904
+ template <class PersistenceMatrixOptions>
1905
+ inline void Matrix<PersistenceMatrixOptions>::zero_entry(Index columnIndex, ID_index rowIndex)
1906
+ {
1907
+ static_assert(PersistenceMatrixOptions::is_of_boundary_type && !PersistenceMatrixOptions::has_column_compression,
1908
+ "'zero_entry' is not available for the chosen options.");
1909
+
1910
+ return matrix_.zero_entry(columnIndex, rowIndex);
1911
+ }
1912
+
1913
+ template <class PersistenceMatrixOptions>
1914
+ inline void Matrix<PersistenceMatrixOptions>::zero_entry(Index columnIndex, ID_index rowIndex, bool inR)
1915
+ {
1916
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1917
+ static_assert(
1918
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1919
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1920
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1921
+ "Only enabled for RU matrices.");
1922
+
1923
+ return matrix_.zero_entry(columnIndex, rowIndex, inR);
1924
+ }
1925
+
1926
+ template <class PersistenceMatrixOptions>
1927
+ inline void Matrix<PersistenceMatrixOptions>::zero_column(Index columnIndex)
1928
+ {
1929
+ static_assert(PersistenceMatrixOptions::is_of_boundary_type && !PersistenceMatrixOptions::has_column_compression,
1930
+ "'zero_column' is not available for the chosen options.");
1931
+
1932
+ return matrix_.zero_column(columnIndex);
1933
+ }
1934
+
1935
+ template <class PersistenceMatrixOptions>
1936
+ inline void Matrix<PersistenceMatrixOptions>::zero_column(Index columnIndex, bool inR)
1937
+ {
1938
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1939
+ static_assert(
1940
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1941
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1942
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1943
+ "Only enabled for RU matrices.");
1944
+
1945
+ return matrix_.zero_column(columnIndex, inR);
1946
+ }
1947
+
1948
+ template <class PersistenceMatrixOptions>
1949
+ inline bool Matrix<PersistenceMatrixOptions>::is_zero_entry(Index columnIndex, ID_index rowIndex)
1950
+ {
1951
+ return matrix_.is_zero_entry(columnIndex, rowIndex);
1952
+ }
1953
+
1954
+ template <class PersistenceMatrixOptions>
1955
+ inline bool Matrix<PersistenceMatrixOptions>::is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const
1956
+ {
1957
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1958
+ static_assert(
1959
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1960
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1961
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1962
+ "Only enabled for RU matrices.");
1963
+
1964
+ return matrix_.is_zero_entry(columnIndex, rowIndex, inR);
1965
+ }
1966
+
1967
+ template <class PersistenceMatrixOptions>
1968
+ inline bool Matrix<PersistenceMatrixOptions>::is_zero_column(Index columnIndex)
1969
+ {
1970
+ return matrix_.is_zero_column(columnIndex);
1971
+ }
1972
+
1973
+ template <class PersistenceMatrixOptions>
1974
+ inline bool Matrix<PersistenceMatrixOptions>::is_zero_column(Index columnIndex, bool inR)
1975
+ {
1976
+ // TODO: I don't think there is a particular reason why the indexation is forced, should be removed.
1977
+ static_assert(
1978
+ isNonBasic && PersistenceMatrixOptions::is_of_boundary_type &&
1979
+ (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles) &&
1980
+ PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER,
1981
+ "Only enabled for RU matrices.");
1982
+
1983
+ return matrix_.is_zero_column(columnIndex, inR);
1984
+ }
1985
+
1986
+ template <class PersistenceMatrixOptions>
1987
+ inline typename Matrix<PersistenceMatrixOptions>::Index Matrix<PersistenceMatrixOptions>::get_column_with_pivot(
1988
+ ID_index cellIndex) const
1989
+ {
1990
+ static_assert(isNonBasic && (!PersistenceMatrixOptions::is_of_boundary_type ||
1991
+ (PersistenceMatrixOptions::has_vine_update ||
1992
+ PersistenceMatrixOptions::can_retrieve_representative_cycles)),
1993
+ "'get_column_with_pivot' is not available for the chosen options.");
1994
+
1995
+ return matrix_.get_column_with_pivot(cellIndex);
1996
+ }
1997
+
1998
+ template <class PersistenceMatrixOptions>
1999
+ inline typename Matrix<PersistenceMatrixOptions>::ID_index Matrix<PersistenceMatrixOptions>::get_pivot(
2000
+ Index columnIndex)
2001
+ {
2002
+ static_assert(isNonBasic, "'get_pivot' is not available for the chosen options.");
2003
+
2004
+ return matrix_.get_pivot(columnIndex);
2005
+ }
2006
+
2007
+ template <class PersistenceMatrixOptions>
2008
+ inline Matrix<PersistenceMatrixOptions>& Matrix<PersistenceMatrixOptions>::operator=(Matrix other) &
2009
+ {
2010
+ swap(matrix_, other.matrix_);
2011
+ std::swap(colSettings_, other.colSettings_);
2012
+
2013
+ return *this;
2014
+ }
2015
+
2016
+ template <class PersistenceMatrixOptions>
2017
+ inline Matrix<PersistenceMatrixOptions>& Matrix<PersistenceMatrixOptions>::operator=(Matrix&& other) && noexcept
2018
+ {
2019
+ if (this == &other) return *this;
2020
+
2021
+ matrix_ = std::move(other.matrix_);
2022
+ colSettings_ = std::exchange(other.colSettings_, nullptr);
2023
+
2024
+ return *this;
2025
+ }
2026
+
2027
+ template <class PersistenceMatrixOptions>
2028
+ inline void Matrix<PersistenceMatrixOptions>::print()
2029
+ {
2030
+ return matrix_.print();
2031
+ }
2032
+
2033
+ template <class PersistenceMatrixOptions>
2034
+ inline const typename Matrix<PersistenceMatrixOptions>::Barcode& Matrix<PersistenceMatrixOptions>::get_current_barcode()
2035
+ {
2036
+ static_assert(PersistenceMatrixOptions::has_column_pairings, "This method was not enabled.");
2037
+
2038
+ return matrix_.get_current_barcode();
2039
+ }
2040
+
2041
+ template <class PersistenceMatrixOptions>
2042
+ inline const typename Matrix<PersistenceMatrixOptions>::Barcode& Matrix<PersistenceMatrixOptions>::get_current_barcode()
2043
+ const
2044
+ {
2045
+ static_assert(PersistenceMatrixOptions::has_column_pairings, "This method was not enabled.");
2046
+ static_assert(
2047
+ !PersistenceMatrixOptions::is_of_boundary_type || PersistenceMatrixOptions::has_vine_update ||
2048
+ PersistenceMatrixOptions::can_retrieve_representative_cycles,
2049
+ "'get_current_barcode' is not const for boundary matrices as the barcode is only computed when explicitly "
2050
+ "asked.");
2051
+
2052
+ return matrix_.get_current_barcode();
2053
+ }
2054
+
2055
+ template <class PersistenceMatrixOptions>
2056
+ inline void Matrix<PersistenceMatrixOptions>::swap_columns(Index columnIndex1, Index columnIndex2)
2057
+ {
2058
+ static_assert(
2059
+ (!isNonBasic && !PersistenceMatrixOptions::has_column_compression) ||
2060
+ (isNonBasic && PersistenceMatrixOptions::is_of_boundary_type && !PersistenceMatrixOptions::has_vine_update &&
2061
+ !PersistenceMatrixOptions::can_retrieve_representative_cycles),
2062
+ "This method was not enabled.");
2063
+ return matrix_.swap_columns(columnIndex1, columnIndex2);
2064
+ }
2065
+
2066
+ template <class PersistenceMatrixOptions>
2067
+ inline void Matrix<PersistenceMatrixOptions>::swap_rows(Index rowIndex1, Index rowIndex2)
2068
+ {
2069
+ static_assert(
2070
+ (!isNonBasic && !PersistenceMatrixOptions::has_column_compression) ||
2071
+ (isNonBasic && PersistenceMatrixOptions::is_of_boundary_type && !PersistenceMatrixOptions::has_vine_update &&
2072
+ !PersistenceMatrixOptions::can_retrieve_representative_cycles),
2073
+ "This method was not enabled.");
2074
+ return matrix_.swap_rows(rowIndex1, rowIndex2);
2075
+ }
2076
+
2077
+ template <class PersistenceMatrixOptions>
2078
+ inline bool Matrix<PersistenceMatrixOptions>::vine_swap_with_z_eq_1_case(Pos_index index)
2079
+ {
2080
+ static_assert(PersistenceMatrixOptions::has_vine_update, "This method was not enabled.");
2081
+ static_assert(PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION ||
2082
+ (PersistenceMatrixOptions::is_of_boundary_type &&
2083
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER),
2084
+ "This method was not enabled.");
2085
+ return matrix_.vine_swap_with_z_eq_1_case(index);
2086
+ }
2087
+
2088
+ template <class PersistenceMatrixOptions>
2089
+ inline typename Matrix<PersistenceMatrixOptions>::Index Matrix<PersistenceMatrixOptions>::vine_swap_with_z_eq_1_case(
2090
+ Index columnIndex1,
2091
+ Index columnIndex2)
2092
+ {
2093
+ static_assert(PersistenceMatrixOptions::has_vine_update, "This method was not enabled.");
2094
+ static_assert(PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::IDENTIFIER ||
2095
+ (!PersistenceMatrixOptions::is_of_boundary_type &&
2096
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER),
2097
+ "This method was not enabled.");
2098
+
2099
+ return matrix_.vine_swap_with_z_eq_1_case(columnIndex1, columnIndex2);
2100
+ }
2101
+
2102
+ template <class PersistenceMatrixOptions>
2103
+ inline bool Matrix<PersistenceMatrixOptions>::vine_swap(Pos_index index)
2104
+ {
2105
+ static_assert(PersistenceMatrixOptions::has_vine_update, "This method was not enabled.");
2106
+ static_assert(PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION ||
2107
+ (PersistenceMatrixOptions::is_of_boundary_type &&
2108
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER),
2109
+ "This method was not enabled.");
2110
+ return matrix_.vine_swap(index);
2111
+ }
2112
+
2113
+ template <class PersistenceMatrixOptions>
2114
+ inline typename Matrix<PersistenceMatrixOptions>::Index Matrix<PersistenceMatrixOptions>::vine_swap(Index columnIndex1,
2115
+ Index columnIndex2)
2116
+ {
2117
+ static_assert(PersistenceMatrixOptions::has_vine_update, "This method was not enabled.");
2118
+ static_assert(PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::IDENTIFIER ||
2119
+ (!PersistenceMatrixOptions::is_of_boundary_type &&
2120
+ PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER),
2121
+ "This method was not enabled.");
2122
+ return matrix_.vine_swap(columnIndex1, columnIndex2);
2123
+ }
2124
+
2125
+ template <class PersistenceMatrixOptions>
2126
+ inline void Matrix<PersistenceMatrixOptions>::update_representative_cycles(Dimension dim)
2127
+ {
2128
+ static_assert(PersistenceMatrixOptions::can_retrieve_representative_cycles, "This method was not enabled.");
2129
+ matrix_.update_representative_cycles(dim);
2130
+ }
2131
+
2132
+ template <class PersistenceMatrixOptions>
2133
+ inline void Matrix<PersistenceMatrixOptions>::update_representative_cycle(const Bar& bar)
2134
+ {
2135
+ static_assert(PersistenceMatrixOptions::can_retrieve_representative_cycles, "This method was not enabled.");
2136
+ matrix_.update_representative_cycle(bar);
2137
+ }
2138
+
2139
+ template <class PersistenceMatrixOptions>
2140
+ inline const std::vector<typename Matrix<PersistenceMatrixOptions>::Cycle>&
2141
+ Matrix<PersistenceMatrixOptions>::get_representative_cycles()
2142
+ {
2143
+ static_assert(PersistenceMatrixOptions::can_retrieve_representative_cycles, "This method was not enabled.");
2144
+ return matrix_.get_representative_cycles();
2145
+ }
2146
+
2147
+ template <class PersistenceMatrixOptions>
2148
+ inline const typename Matrix<PersistenceMatrixOptions>::Cycle&
2149
+ Matrix<PersistenceMatrixOptions>::get_representative_cycle(const Bar& bar)
2150
+ {
2151
+ static_assert(PersistenceMatrixOptions::can_retrieve_representative_cycles, "This method was not enabled.");
2152
+ return matrix_.get_representative_cycle(bar);
2153
+ }
2154
+
2155
+ template <class PersistenceMatrixOptions>
2156
+ constexpr void Matrix<PersistenceMatrixOptions>::_assert_options()
2157
+ {
2158
+ static_assert(
2159
+ PersistenceMatrixOptions::column_type != Column_types::HEAP || !PersistenceMatrixOptions::has_row_access,
2160
+ "Row access is not possible for heap columns.");
2161
+ static_assert(!PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::is_z2,
2162
+ "Vine update currently works only for Z_2 coefficients.");
2163
+ // static_assert(!PersistenceMatrixOptions::can_retrieve_representative_cycles || PersistenceMatrixOptions::is_z2,
2164
+ // "Representative cycles can currently only be computed with Z_2 coefficients.");
2165
+ static_assert(
2166
+ PersistenceMatrixOptions::column_type != Column_types::HEAP || !PersistenceMatrixOptions::has_column_compression,
2167
+ "Column compression not compatible with heap columns.");
2168
+
2169
+ // // This should be warnings instead, as PersistenceMatrixOptions::has_column_compression is just ignored in those
2170
+ // // cases and don't produces errors as long as the corresponding methods are not called.
2171
+ // static_assert(!PersistenceMatrixOptions::has_column_compression || !PersistenceMatrixOptions::has_column_pairings,
2172
+ // "Column compression not available to compute persistence homology (it would bring no advantages; "
2173
+ // "use it for co-homology instead).");
2174
+ // static_assert(!PersistenceMatrixOptions::has_column_compression || !PersistenceMatrixOptions::has_vine_update,
2175
+ // "Column compression not available for vineyards.");
2176
+ // static_assert(!PersistenceMatrixOptions::has_column_compression ||
2177
+ // !PersistenceMatrixOptions::can_retrieve_representative_cycles,
2178
+ // "Column compression not available to retrieve representative cycles.");
2179
+ // // Would column removal while column compression be useful? If yes, should erase() remove a single column or the
2180
+ // // class of columns identical to the input?
2181
+ // // For a single column, I have an implementation for union-find (not the current one) which allows deleting a
2182
+ // // single element in constant time, but find becomes log n in worst case.
2183
+ // // For a column class, we either just ignore the removed class (constant time), but this results in memory
2184
+ // // residues, or, we have an erase method which is at least linear in the size of the class.
2185
+ // static_assert(
2186
+ // !PersistenceMatrixOptions::has_column_compression || !PersistenceMatrixOptions::has_map_column_container,
2187
+ // "When column compression is used, the removal of columns is not implemented yet.");
2188
+ }
2189
+
2190
+ template <class PersistenceMatrixOptions>
2191
+ inline typename Matrix<PersistenceMatrixOptions>::Element Matrix<PersistenceMatrixOptions>::_get_value(
2192
+ int coefficient) const
2193
+ {
2194
+ return get_coefficient_value(coefficient, get_operator_ptr(colSettings_));
2195
+ }
2196
+
2197
+ } // namespace persistence_matrix
2198
+ } // namespace Gudhi
2199
+
2200
+ #endif // MASTER_MATRIX_H