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,905 @@
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 RU_matrix.h
13
+ * @author Hannah Schreiber
14
+ * @brief Contains the @ref Gudhi::persistence_matrix::RU_matrix class.
15
+ */
16
+
17
+ #ifndef PM_RU_MATRIX_H
18
+ #define PM_RU_MATRIX_H
19
+
20
+ #include <utility> //std::swap, std::move & std::exchange
21
+ #include <iostream> //print() only
22
+ #include <vector>
23
+ #include <unordered_map>
24
+
25
+ namespace Gudhi {
26
+ namespace persistence_matrix {
27
+
28
+ template <class Master_matrix>
29
+ class RU_pairing;
30
+
31
+ /**
32
+ * @class RU_matrix RU_matrix.h gudhi/Persistence_matrix/RU_matrix.h
33
+ * @ingroup persistence_matrix
34
+ *
35
+ * @brief %Matrix structure to store the ordered @ref boundarymatrix "boundary matrix" \f$ R \cdot U \f$ of a filtered
36
+ * complex in order to compute its persistent homology, as well as representative cycles.
37
+ * Supports vineyards (see @cite vineyards) and the removal of maximal cells while maintaining
38
+ * a valid barcode. Provides an access to its columns and rows.
39
+ *
40
+ * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced.
41
+ */
42
+ template <class Master_matrix>
43
+ class RU_matrix : public Master_matrix::RU_pairing_option,
44
+ public Master_matrix::RU_vine_swap_option,
45
+ public Master_matrix::RU_representative_cycles_option
46
+ {
47
+ private:
48
+ using Pair_opt = typename Master_matrix::RU_pairing_option;
49
+ using Swap_opt = typename Master_matrix::RU_vine_swap_option;
50
+ using Rep_opt = typename Master_matrix::RU_representative_cycles_option;
51
+
52
+ public:
53
+ /**
54
+ * @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false.
55
+ */
56
+ using Field_operators = typename Master_matrix::Field_operators;
57
+ using Field_element = typename Master_matrix::Element; /**< Type of an field element. */
58
+ using Column = typename Master_matrix::Column; /**< Column type. */
59
+ using Row = typename Master_matrix::Row; /**< Row type,
60
+ only necessary with row access option. */
61
+ using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */
62
+ using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to
63
+ necessary external classes. */
64
+ using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */
65
+ using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */
66
+ using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */
67
+ using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */
68
+ using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */
69
+
70
+ /**
71
+ * @brief Constructs an empty matrix.
72
+ *
73
+ * @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
74
+ * the necessary external classes specifically necessary for the chosen column type, such as custom allocators.
75
+ */
76
+ RU_matrix(Column_settings* colSettings);
77
+ /**
78
+ * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds
79
+ * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by
80
+ * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting
81
+ * with 0.
82
+ *
83
+ * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges.
84
+ * Assumed to have a begin(), end() and size() method.
85
+ * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a
86
+ * filtered **simplicial** complex, whose boundaries are ordered by filtration order.
87
+ * Therefore, `orderedBoundaries[i]` should store the boundary of the \f$ i^{th} \f$ simplex in the filtration,
88
+ * as an ordered list of indices of its facets (again those indices correspond to their respective position
89
+ * in the matrix). That is why the indices of the simplices are assumed to be consecutive and starting with 0
90
+ * (an empty boundary is interpreted as a vertex boundary and not as a non existing simplex).
91
+ * All dimensions up to the maximal dimension of interest have to be present. If only a higher dimension is of
92
+ * interest and not everything should be stored, then use the @ref insert_boundary method instead (after creating the
93
+ * matrix with the @ref RU_matrix(unsigned int, Column_settings*) constructor preferably).
94
+ * @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
95
+ * the necessary external classes specifically necessary for the chosen column type, such as custom allocators.
96
+ */
97
+ template <class Boundary_range = Boundary>
98
+ RU_matrix(const std::vector<Boundary_range>& orderedBoundaries, Column_settings* colSettings);
99
+ /**
100
+ * @brief Constructs a new empty matrix and reserves space for the given number of columns.
101
+ *
102
+ * @param numberOfColumns Number of columns to reserve space for.
103
+ * @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
104
+ * the necessary external classes specifically necessary for the chosen column type, such as custom allocators.
105
+ */
106
+ RU_matrix(unsigned int numberOfColumns, Column_settings* colSettings);
107
+ /**
108
+ * @brief Copy constructor. If @p colSettings is not a null pointer, its value is kept
109
+ * instead of the one in the copied matrix.
110
+ *
111
+ * @param matrixToCopy Matrix to copy.
112
+ * @param colSettings Either a pointer to an existing setting structure for the columns or a null pointer.
113
+ * The structure should contain all the necessary external classes specifically necessary for the chosen column type,
114
+ * such as custom allocators. If null pointer, the pointer stored in @p matrixToCopy is used instead.
115
+ */
116
+ RU_matrix(const RU_matrix& matrixToCopy, Column_settings* colSettings = nullptr);
117
+ /**
118
+ * @brief Move constructor.
119
+ *
120
+ * @param other Matrix to move.
121
+ */
122
+ RU_matrix(RU_matrix&& other) noexcept;
123
+
124
+ ~RU_matrix() = default;
125
+
126
+ /**
127
+ * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary.
128
+ * This means that it is assumed that this method is called on boundaries in the order of the filtration.
129
+ * It also assumes that the cells in the given boundary are identified by their relative position in the filtration,
130
+ * starting at 0. If it is not the case, use the other
131
+ * @ref insert_boundary(ID_index, const Boundary_range&, Dimension) "insert_boundary" instead by indicating the
132
+ * cell ID used in the boundaries when the cell is inserted.
133
+ *
134
+ * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from
135
+ * a more general entry complex. This includes cubical complexes or Morse complexes for example.
136
+ *
137
+ * At the insertion, the boundary is stored in its reduced form and the barcode, if enabled, is updated.
138
+ *
139
+ * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size()
140
+ * method.
141
+ * @param boundary Boundary generating the new column. The content should be ordered by ID.
142
+ * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
143
+ * this parameter can be omitted as it can be deduced from the size of the boundary.
144
+ */
145
+ template <class Boundary_range = Boundary>
146
+ void insert_boundary(const Boundary_range& boundary,
147
+ Dimension dim = Master_matrix::template get_null_value<Dimension>());
148
+ /**
149
+ * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions
150
+ * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then
151
+ * to use the other insertion method to avoid overwriting IDs.
152
+ *
153
+ * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that
154
+ * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted.
155
+ *
156
+ * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size()
157
+ * method.
158
+ * @param cellIndex @ref IDIdx index to use to identify the new cell.
159
+ * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the
160
+ * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in
161
+ * increasing order.
162
+ * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial,
163
+ * this parameter can be omitted as it can be deduced from the size of the boundary.
164
+ */
165
+ template <class Boundary_range = Boundary>
166
+ void insert_boundary(ID_index cellIndex,
167
+ const Boundary_range& boundary,
168
+ Dimension dim = Master_matrix::template get_null_value<Dimension>());
169
+ /**
170
+ * @brief Returns the column at the given @ref MatIdx index in \f$ R \f$ if @p inR is true and
171
+ * in \f$ U \f$ if @p inR is false.
172
+ * The type of the column depends on the chosen options, see @ref PersistenceMatrixOptions::column_type.
173
+ *
174
+ * Note that before returning the column, all column entries can eventually be reordered, if lazy swaps occurred.
175
+ * It is therefore recommended to avoid calling @ref get_column between vine swaps, otherwise the benefits
176
+ * of the the laziness is lost.
177
+ *
178
+ * @param columnIndex @ref MatIdx index of the column to return.
179
+ * @param inR If true, returns the column in \f$ R \f$, if false, returns the column in \f$ U \f$.
180
+ * Default value: true.
181
+ * @return Reference to the column.
182
+ */
183
+ Column& get_column(Index columnIndex, bool inR = true);
184
+ /**
185
+ * @brief Returns the row at the given @ref rowindex "row index" in \f$ R \f$ if @p inR is true and
186
+ * in \f$ U \f$ if @p inR is false.
187
+ * The type of the row depends on the chosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows.
188
+ *
189
+ * Note that before returning the row, all column entries can eventually be reordered, if lazy swaps occurred.
190
+ * It is therefore recommended to avoid calling @ref get_row between vine swaps, otherwise the benefits
191
+ * of the the laziness is lost.
192
+ *
193
+ * @param rowIndex @ref rowindex "Row index" of the row to return.
194
+ * @param inR If true, returns the row in \f$ R \f$, if false, returns the row in \f$ U \f$.
195
+ * Default value: true.
196
+ * @return Reference to the row.
197
+ */
198
+ Row& get_row(Index rowIndex, bool inR = true);
199
+ /**
200
+ * @brief If @ref PersistenceMatrixOptions::has_row_access and @ref PersistenceMatrixOptions::has_removable_rows
201
+ * are true: assumes that the row is empty in \f$ R \f$ and removes it from \f$ R \f$. If the matrix is valid,
202
+ * a row will never be empty in \f$ U \f$, so \f$ U \f$ won't be affected.
203
+ * If @ref PersistenceMatrixOptions::has_map_column_container
204
+ * and @ref PersistenceMatrixOptions::has_column_and_row_swaps are true: cleans up maps used for the lazy row swaps.
205
+ * Otherwise, does nothing.
206
+ *
207
+ * @warning The removed rows are always assumed to be empty in \f$ R \f$. If it is not the case, the deleted row
208
+ * entries are not removed from their columns. And in the case of intrusive rows, this will generate a segmentation
209
+ * fault when the column entries are destroyed later. The row access is just meant as a "read only" access to the
210
+ * rows and the @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed
211
+ * from dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can
212
+ * be quite frequent.
213
+ *
214
+ * @param rowIndex @ref rowindex "Row index" of the empty row.
215
+ */
216
+ void erase_empty_row(Index rowIndex);
217
+ /**
218
+ * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns and
219
+ * @ref PersistenceMatrixOptions::has_vine_update are true.
220
+ * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent
221
+ * (i.e., RU is still an upper triangular decomposition of the @ref boundarymatrix "boundary matrix").
222
+ * The maximality of the cell is not verified.
223
+ * Also updates the barcode if it is stored.
224
+ *
225
+ * See also @ref remove_last.
226
+ *
227
+ * @param columnIndex @ref MatIdx index of the cell to remove.
228
+ */
229
+ void remove_maximal_cell(Index columnIndex);
230
+ /**
231
+ * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true.
232
+ * Removes the last cell in the filtration from the matrix and updates the barcode if it is stored.
233
+ *
234
+ * See also @ref remove_maximal_cell.
235
+ */
236
+ void remove_last();
237
+
238
+ /**
239
+ * @brief Returns the maximal dimension of a cell stored in the matrix.
240
+ * Only available if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access is true.
241
+ *
242
+ * @return The maximal dimension.
243
+ */
244
+ Dimension get_max_dimension() const;
245
+ /**
246
+ * @brief Returns the current number of columns in the matrix.
247
+ *
248
+ * @return The number of columns.
249
+ */
250
+ Index get_number_of_columns() const;
251
+ /**
252
+ * @brief Returns the dimension of the given column.
253
+ *
254
+ * @param columnIndex @ref MatIdx index of the column representing the cell.
255
+ * @return Dimension of the cell.
256
+ */
257
+ Dimension get_column_dimension(Index columnIndex) const;
258
+
259
+ /**
260
+ * @brief Adds column at @p sourceColumnIndex onto the column at @p targetColumnIndex in the matrix.
261
+ *
262
+ * @warning They will be no verification to ensure that the addition makes sense for the validity of a
263
+ * boundary matrix of a filtered complex. For example, a right-to-left addition could corrupt the computation
264
+ * of the barcode if done blindly. So should be used with care.
265
+ *
266
+ * @param sourceColumnIndex @ref MatIdx index of the source column.
267
+ * @param targetColumnIndex @ref MatIdx index of the target column.
268
+ */
269
+ void add_to(Index sourceColumnIndex, Index targetColumnIndex);
270
+ /**
271
+ * @brief Multiplies the target column with the coefficient and then adds the source column to it.
272
+ * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`.
273
+ *
274
+ * @warning They will be no verification to ensure that the addition makes sense for the validity of a
275
+ * boundary matrix of a filtered complex. For example, a right-to-left addition could corrupt the computation
276
+ * of the barcode if done blindly. So should be used with care.
277
+ *
278
+ * @param sourceColumnIndex @ref MatIdx index of the source column.
279
+ * @param coefficient Value to multiply.
280
+ * @param targetColumnIndex @ref MatIdx index of the target column.
281
+ */
282
+ void multiply_target_and_add_to(Index sourceColumnIndex, const Field_element& coefficient, Index targetColumnIndex);
283
+ /**
284
+ * @brief Multiplies the source column with the coefficient before adding it to the target column.
285
+ * That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified.
286
+ *
287
+ * @warning They will be no verification to ensure that the addition makes sense for the validity of a
288
+ * boundary matrix of a filtered complex. For example, a right-to-left addition could corrupt the computation
289
+ * of the barcode if done blindly. So should be used with care.
290
+ *
291
+ * @param coefficient Value to multiply.
292
+ * @param sourceColumnIndex @ref MatIdx index of the source column.
293
+ * @param targetColumnIndex @ref MatIdx index of the target column.
294
+ */
295
+ void multiply_source_and_add_to(const Field_element& coefficient, Index sourceColumnIndex, Index targetColumnIndex);
296
+
297
+ /**
298
+ * @brief Zeroes the entry at the given coordinates in \f$ R \f$ if @p inR is true or in
299
+ * \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the persistence
300
+ * related properties of the matrix.
301
+ *
302
+ * @param columnIndex @ref MatIdx index of the column of the entry.
303
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
304
+ * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$.
305
+ * Default value: true.
306
+ */
307
+ void zero_entry(Index columnIndex, Index rowIndex, bool inR = true);
308
+ /**
309
+ * @brief Zeroes the column at the given index in \f$ R \f$ if @p inR is true or in
310
+ * \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the persistence
311
+ * related properties of the matrix.
312
+ *
313
+ * @param columnIndex @ref MatIdx index of the column to zero.
314
+ * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$.
315
+ * Default value: true.
316
+ */
317
+ void zero_column(Index columnIndex, bool inR = true);
318
+ /**
319
+ * @brief Indicates if the entry at given coordinates has value zero in \f$ R \f$
320
+ * if @p inR is true or in \f$ U \f$ if @p inR is false.
321
+ *
322
+ * @param columnIndex @ref MatIdx index of the column of the entry.
323
+ * @param rowIndex @ref rowindex "Row index" of the row of the entry.
324
+ * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$.
325
+ * Default value: true.
326
+ * @return true If the entry has value zero.
327
+ * @return false Otherwise.
328
+ */
329
+ bool is_zero_entry(Index columnIndex, Index rowIndex, bool inR = true) const;
330
+ /**
331
+ * @brief Indicates if the column at given index has value zero in \f$ R \f$
332
+ * if @p inR is true or in \f$ U \f$ if @p inR is false.
333
+ *
334
+ * Note that if @p inR is false, this method should usually return false.
335
+ *
336
+ * @param columnIndex @ref MatIdx index of the column.
337
+ * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$.
338
+ * Default value: true.
339
+ * @return true If the column has value zero.
340
+ * @return false Otherwise.
341
+ */
342
+ bool is_zero_column(Index columnIndex, bool inR = true);
343
+
344
+ /**
345
+ * @brief Returns the @ref MatIdx index of the column which has the given @ref rowindex "row index" as pivot in
346
+ * \f$ R \f$. Assumes that the pivot exists.
347
+ *
348
+ * @param cellIndex @ref rowindex "Row index" of the pivot.
349
+ * @return @ref MatIdx index of the column in \f$ R \f$ with the given pivot.
350
+ */
351
+ Index get_column_with_pivot(Index cellIndex) const;
352
+ /**
353
+ * @brief Returns the @ref rowindex "row index" of the pivot of the given column in \f$ R \f$.
354
+ *
355
+ * @param columnIndex @ref MatIdx index of the column in \f$ R \f$.
356
+ * @return The @ref rowindex "row index" of the pivot.
357
+ */
358
+ Index get_pivot(Index columnIndex);
359
+
360
+ /**
361
+ * @brief Resets the matrix to an empty matrix.
362
+ *
363
+ * @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all
364
+ * the necessary external classes specifically necessary for the chosen column type, such as custom allocators.
365
+ */
366
+ void reset(Column_settings* colSettings)
367
+ {
368
+ if constexpr (Master_matrix::Option_list::has_column_pairings) Pair_opt::_reset();
369
+ if constexpr (Master_matrix::Option_list::can_retrieve_representative_cycles) Rep_opt::_reset();
370
+ reducedMatrixR_.reset(colSettings);
371
+ mirrorMatrixU_.reset(colSettings);
372
+ pivotToColumnIndex_.clear();
373
+ nextEventIndex_ = 0;
374
+ positionToID_.clear();
375
+ operators_ = Master_matrix::get_operator_ptr(colSettings);
376
+ }
377
+
378
+ /**
379
+ * @brief Assign operator.
380
+ */
381
+ RU_matrix& operator=(const RU_matrix& other);
382
+ /**
383
+ * @brief Move assign operator.
384
+ */
385
+ RU_matrix& operator=(RU_matrix&& other) noexcept;
386
+
387
+ /**
388
+ * @brief Swap operator.
389
+ */
390
+ friend void swap(RU_matrix& matrix1, RU_matrix& matrix2) noexcept
391
+ {
392
+ swap(static_cast<Pair_opt&>(matrix1), static_cast<Pair_opt&>(matrix2));
393
+ swap(static_cast<Swap_opt&>(matrix1), static_cast<Swap_opt&>(matrix2));
394
+ swap(static_cast<Rep_opt&>(matrix1), static_cast<Rep_opt&>(matrix2));
395
+ swap(matrix1.reducedMatrixR_, matrix2.reducedMatrixR_);
396
+ swap(matrix1.mirrorMatrixU_, matrix2.mirrorMatrixU_);
397
+ matrix1.pivotToColumnIndex_.swap(matrix2.pivotToColumnIndex_);
398
+ std::swap(matrix1.nextEventIndex_, matrix2.nextEventIndex_);
399
+ matrix1.positionToID_.swap(matrix2.positionToID_);
400
+ std::swap(matrix1.operators_, matrix2.operators_);
401
+ }
402
+
403
+ void print(); // for debug
404
+
405
+ private:
406
+ using Pivot_dictionary = typename Master_matrix::template Dictionary<Index>;
407
+ using Position_dictionary = std::unordered_map<Pos_index, ID_index>; // TODO: try other type of maps?
408
+ using Barcode = typename Master_matrix::Barcode;
409
+ using Bar_dictionary = typename Master_matrix::Bar_dictionary;
410
+ using R_matrix = typename Master_matrix::Master_boundary_matrix;
411
+ using U_matrix = typename Master_matrix::Master_base_matrix;
412
+
413
+ friend Rep_opt; // direct access to the two matrices
414
+ friend Swap_opt; // direct access to the two matrices, pivotToColumnIndex_
415
+ friend RU_pairing<Master_matrix>; // direct access to positionToID_
416
+
417
+ R_matrix reducedMatrixR_; /**< R. */
418
+ // TODO: make U not accessible by default and add option to enable access? Inaccessible, it
419
+ // needs less options and we could avoid some ifs.
420
+ U_matrix mirrorMatrixU_; /**< U. */
421
+ Pivot_dictionary pivotToColumnIndex_; /**< Map from pivot row index to column @ref MatIdx index. */
422
+ Pos_index nextEventIndex_; /**< Next birth or death index. */
423
+ Position_dictionary positionToID_; /**< Map from @ref MatIdx to @ref IDIdx. */
424
+ Field_operators const* operators_; /**< Field operators, can be nullptr if
425
+ @ref PersistenceMatrixOptions::is_z2 is true. */
426
+
427
+ void _insert_boundary(Index currentIndex);
428
+ void _initialize_U();
429
+ void _reduce();
430
+ void _reduce_last_column(Index lastIndex);
431
+ void _reduce_column(Index target, Index eventIndex);
432
+ void _reduce_column_by(Index target, Index source);
433
+ Index _get_column_with_pivot(ID_index pivot) const;
434
+ void _update_barcode(ID_index birthPivot, Pos_index death);
435
+ void _add_bar(Dimension dim, Pos_index birth);
436
+ void _remove_last_in_barcode(Pos_index eventIndex);
437
+ };
438
+
439
+ template <class Master_matrix>
440
+ inline RU_matrix<Master_matrix>::RU_matrix(Column_settings* colSettings)
441
+ : Pair_opt(),
442
+ Swap_opt(),
443
+ Rep_opt(),
444
+ reducedMatrixR_(colSettings),
445
+ mirrorMatrixU_(colSettings),
446
+ nextEventIndex_(0),
447
+ operators_(Master_matrix::get_operator_ptr(colSettings))
448
+ {}
449
+
450
+ template <class Master_matrix>
451
+ template <class Boundary_range>
452
+ inline RU_matrix<Master_matrix>::RU_matrix(const std::vector<Boundary_range>& orderedBoundaries,
453
+ Column_settings* colSettings)
454
+ : Pair_opt(),
455
+ Swap_opt(),
456
+ Rep_opt(),
457
+ reducedMatrixR_(orderedBoundaries, colSettings),
458
+ mirrorMatrixU_(orderedBoundaries.size(), colSettings),
459
+ nextEventIndex_(orderedBoundaries.size()),
460
+ operators_(Master_matrix::get_operator_ptr(colSettings))
461
+ {
462
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
463
+ pivotToColumnIndex_.reserve(orderedBoundaries.size());
464
+ } else {
465
+ pivotToColumnIndex_.resize(orderedBoundaries.size(), Master_matrix::template get_null_value<Index>());
466
+ }
467
+
468
+ _initialize_U();
469
+ _reduce();
470
+ }
471
+
472
+ template <class Master_matrix>
473
+ inline RU_matrix<Master_matrix>::RU_matrix(unsigned int numberOfColumns, Column_settings* colSettings)
474
+ : Pair_opt(),
475
+ Swap_opt(),
476
+ Rep_opt(),
477
+ reducedMatrixR_(numberOfColumns, colSettings),
478
+ mirrorMatrixU_(numberOfColumns, colSettings),
479
+ nextEventIndex_(0),
480
+ positionToID_(numberOfColumns),
481
+ operators_(Master_matrix::get_operator_ptr(colSettings))
482
+ {
483
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
484
+ pivotToColumnIndex_.reserve(numberOfColumns);
485
+ } else {
486
+ pivotToColumnIndex_.resize(numberOfColumns, Master_matrix::template get_null_value<Index>());
487
+ }
488
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
489
+ Pair_opt::_reserve(numberOfColumns);
490
+ }
491
+ }
492
+
493
+ template <class Master_matrix>
494
+ inline RU_matrix<Master_matrix>::RU_matrix(const RU_matrix& matrixToCopy, Column_settings* colSettings)
495
+ : Pair_opt(static_cast<const Pair_opt&>(matrixToCopy)),
496
+ Swap_opt(static_cast<const Swap_opt&>(matrixToCopy)),
497
+ Rep_opt(static_cast<const Rep_opt&>(matrixToCopy)),
498
+ reducedMatrixR_(matrixToCopy.reducedMatrixR_, colSettings),
499
+ mirrorMatrixU_(matrixToCopy.mirrorMatrixU_, colSettings),
500
+ pivotToColumnIndex_(matrixToCopy.pivotToColumnIndex_),
501
+ nextEventIndex_(matrixToCopy.nextEventIndex_),
502
+ positionToID_(matrixToCopy.positionToID_),
503
+ operators_(colSettings == nullptr ? matrixToCopy.operators_ : Master_matrix::get_operator_ptr(colSettings))
504
+ {}
505
+
506
+ template <class Master_matrix>
507
+ inline RU_matrix<Master_matrix>::RU_matrix(RU_matrix&& other) noexcept
508
+ : Pair_opt(std::move(static_cast<Pair_opt&>(other))),
509
+ Swap_opt(std::move(static_cast<Swap_opt&>(other))),
510
+ Rep_opt(std::move(static_cast<Rep_opt&>(other))),
511
+ reducedMatrixR_(std::move(other.reducedMatrixR_)),
512
+ mirrorMatrixU_(std::move(other.mirrorMatrixU_)),
513
+ pivotToColumnIndex_(std::move(other.pivotToColumnIndex_)),
514
+ nextEventIndex_(std::exchange(other.nextEventIndex_, 0)),
515
+ positionToID_(std::move(other.positionToID_)),
516
+ operators_(std::exchange(other.operators_, nullptr))
517
+ {}
518
+
519
+ template <class Master_matrix>
520
+ template <class Boundary_range>
521
+ inline void RU_matrix<Master_matrix>::insert_boundary(const Boundary_range& boundary, Dimension dim)
522
+ {
523
+ _insert_boundary(reducedMatrixR_.insert_boundary(boundary, dim));
524
+ }
525
+
526
+ template <class Master_matrix>
527
+ template <class Boundary_range>
528
+ inline void RU_matrix<Master_matrix>::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim)
529
+ {
530
+ // maps for possible shifting between column content and position indices used for birth events
531
+ if (cellIndex != nextEventIndex_) {
532
+ positionToID_.emplace(nextEventIndex_, cellIndex);
533
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
534
+ Pair_opt::_insert_id_position(cellIndex, nextEventIndex_);
535
+ }
536
+ }
537
+
538
+ _insert_boundary(reducedMatrixR_.insert_boundary(cellIndex, boundary, dim));
539
+ }
540
+
541
+ template <class Master_matrix>
542
+ inline typename RU_matrix<Master_matrix>::Column& RU_matrix<Master_matrix>::get_column(Index columnIndex, bool inR)
543
+ {
544
+ if (inR) {
545
+ return reducedMatrixR_.get_column(columnIndex);
546
+ }
547
+ return mirrorMatrixU_.get_column(columnIndex);
548
+ }
549
+
550
+ template <class Master_matrix>
551
+ inline typename RU_matrix<Master_matrix>::Row& RU_matrix<Master_matrix>::get_row(Index rowIndex, bool inR)
552
+ {
553
+ static_assert(Master_matrix::Option_list::has_row_access, "'get_row' is not implemented for the chosen options.");
554
+
555
+ if (inR) {
556
+ return reducedMatrixR_.get_row(rowIndex);
557
+ }
558
+ return mirrorMatrixU_.get_row(rowIndex);
559
+ }
560
+
561
+ template <class Master_matrix>
562
+ inline void RU_matrix<Master_matrix>::erase_empty_row(Index rowIndex)
563
+ {
564
+ reducedMatrixR_.erase_empty_row(rowIndex);
565
+ }
566
+
567
+ template <class Master_matrix>
568
+ inline void RU_matrix<Master_matrix>::remove_maximal_cell(Index columnIndex)
569
+ {
570
+ static_assert(Master_matrix::Option_list::has_removable_columns && Master_matrix::Option_list::has_vine_update,
571
+ "'remove_maximal_cell' is not implemented for the chosen options.");
572
+
573
+ // TODO: is there an easy test to verify maximality even without row access?
574
+
575
+ for (Index curr = columnIndex; curr < nextEventIndex_ - 1; ++curr) {
576
+ Swap_opt::vine_swap(curr);
577
+ }
578
+
579
+ remove_last();
580
+ }
581
+
582
+ template <class Master_matrix>
583
+ inline void RU_matrix<Master_matrix>::remove_last()
584
+ {
585
+ static_assert(Master_matrix::Option_list::has_removable_columns,
586
+ "'remove_last' is not implemented for the chosen options.");
587
+
588
+ if (nextEventIndex_ == 0) return; // empty matrix
589
+ --nextEventIndex_;
590
+
591
+ // assumes PosIdx == MatIdx for boundary matrices.
592
+ _remove_last_in_barcode(nextEventIndex_);
593
+
594
+ mirrorMatrixU_.remove_last();
595
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
596
+ pivotToColumnIndex_.erase(reducedMatrixR_.remove_last());
597
+ } else {
598
+ ID_index lastPivot = reducedMatrixR_.remove_last();
599
+ if (lastPivot != Master_matrix::template get_null_value<ID_index>())
600
+ pivotToColumnIndex_[lastPivot] = Master_matrix::template get_null_value<Index>();
601
+ }
602
+
603
+ // if has_column_pairings is true, then the element is already removed in _remove_last_in_barcode
604
+ // to avoid a second "find"
605
+ if constexpr (!Master_matrix::Option_list::has_column_pairings) {
606
+ positionToID_.erase(nextEventIndex_);
607
+ }
608
+ }
609
+
610
+ template <class Master_matrix>
611
+ inline typename RU_matrix<Master_matrix>::Dimension RU_matrix<Master_matrix>::get_max_dimension() const
612
+ {
613
+ return reducedMatrixR_.get_max_dimension();
614
+ }
615
+
616
+ template <class Master_matrix>
617
+ inline typename RU_matrix<Master_matrix>::Index RU_matrix<Master_matrix>::get_number_of_columns() const
618
+ {
619
+ return reducedMatrixR_.get_number_of_columns();
620
+ }
621
+
622
+ template <class Master_matrix>
623
+ inline typename RU_matrix<Master_matrix>::Dimension RU_matrix<Master_matrix>::get_column_dimension(
624
+ Index columnIndex) const
625
+ {
626
+ return reducedMatrixR_.get_column_dimension(columnIndex);
627
+ }
628
+
629
+ template <class Master_matrix>
630
+ inline void RU_matrix<Master_matrix>::add_to(Index sourceColumnIndex, Index targetColumnIndex)
631
+ {
632
+ reducedMatrixR_.add_to(sourceColumnIndex, targetColumnIndex);
633
+ // U transposed to avoid row operations
634
+ if constexpr (Master_matrix::Option_list::is_z2)
635
+ mirrorMatrixU_.add_to(targetColumnIndex, sourceColumnIndex);
636
+ else
637
+ mirrorMatrixU_.multiply_source_and_add_to(
638
+ operators_->get_characteristic() - 1, targetColumnIndex, sourceColumnIndex);
639
+ }
640
+
641
+ template <class Master_matrix>
642
+ inline void RU_matrix<Master_matrix>::multiply_target_and_add_to(Index sourceColumnIndex,
643
+ const Field_element& coefficient,
644
+ Index targetColumnIndex)
645
+ {
646
+ reducedMatrixR_.multiply_target_and_add_to(sourceColumnIndex, coefficient, targetColumnIndex);
647
+ // U transposed to avoid row operations
648
+ mirrorMatrixU_.get_column(targetColumnIndex) *= coefficient;
649
+ mirrorMatrixU_.multiply_source_and_add_to(operators_->get_characteristic() - 1, targetColumnIndex, sourceColumnIndex);
650
+ }
651
+
652
+ template <class Master_matrix>
653
+ inline void RU_matrix<Master_matrix>::multiply_source_and_add_to(const Field_element& coefficient,
654
+ Index sourceColumnIndex,
655
+ Index targetColumnIndex)
656
+ {
657
+ reducedMatrixR_.multiply_source_and_add_to(coefficient, sourceColumnIndex, targetColumnIndex);
658
+ // U transposed to avoid row operations
659
+ if constexpr (Master_matrix::Option_list::is_z2) {
660
+ if (coefficient) mirrorMatrixU_.add_to(targetColumnIndex, sourceColumnIndex);
661
+ } else {
662
+ mirrorMatrixU_.multiply_source_and_add_to(
663
+ operators_->get_characteristic() - coefficient, targetColumnIndex, sourceColumnIndex);
664
+ }
665
+ }
666
+
667
+ template <class Master_matrix>
668
+ inline void RU_matrix<Master_matrix>::zero_entry(Index columnIndex, Index rowIndex, bool inR)
669
+ {
670
+ if (inR) {
671
+ return reducedMatrixR_.zero_entry(columnIndex, rowIndex);
672
+ }
673
+ return mirrorMatrixU_.zero_entry(columnIndex, rowIndex);
674
+ }
675
+
676
+ template <class Master_matrix>
677
+ inline void RU_matrix<Master_matrix>::zero_column(Index columnIndex, bool inR)
678
+ {
679
+ if (inR) {
680
+ return reducedMatrixR_.zero_column(columnIndex);
681
+ }
682
+ return mirrorMatrixU_.zero_column(columnIndex);
683
+ }
684
+
685
+ template <class Master_matrix>
686
+ inline bool RU_matrix<Master_matrix>::is_zero_entry(Index columnIndex, Index rowIndex, bool inR) const
687
+ {
688
+ if (inR) {
689
+ return reducedMatrixR_.is_zero_entry(columnIndex, rowIndex);
690
+ }
691
+ return mirrorMatrixU_.is_zero_entry(columnIndex, rowIndex);
692
+ }
693
+
694
+ template <class Master_matrix>
695
+ inline bool RU_matrix<Master_matrix>::is_zero_column(Index columnIndex, bool inR)
696
+ {
697
+ if (inR) {
698
+ return reducedMatrixR_.is_zero_column(columnIndex);
699
+ }
700
+ return mirrorMatrixU_.is_zero_column(columnIndex);
701
+ }
702
+
703
+ template <class Master_matrix>
704
+ inline typename RU_matrix<Master_matrix>::Index RU_matrix<Master_matrix>::get_column_with_pivot(Index cellIndex) const
705
+ {
706
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
707
+ return pivotToColumnIndex_.at(cellIndex);
708
+ } else {
709
+ return pivotToColumnIndex_[cellIndex];
710
+ }
711
+ }
712
+
713
+ template <class Master_matrix>
714
+ inline typename RU_matrix<Master_matrix>::Index RU_matrix<Master_matrix>::get_pivot(Index columnIndex)
715
+ {
716
+ return reducedMatrixR_.get_column(columnIndex).get_pivot();
717
+ }
718
+
719
+ template <class Master_matrix>
720
+ inline RU_matrix<Master_matrix>& RU_matrix<Master_matrix>::operator=(const RU_matrix& other)
721
+ {
722
+ if (this == &other) return *this;
723
+
724
+ Swap_opt::operator=(other);
725
+ Pair_opt::operator=(other);
726
+ Rep_opt::operator=(other);
727
+ reducedMatrixR_ = other.reducedMatrixR_;
728
+ mirrorMatrixU_ = other.mirrorMatrixU_;
729
+ pivotToColumnIndex_ = other.pivotToColumnIndex_;
730
+ nextEventIndex_ = other.nextEventIndex_;
731
+ positionToID_ = other.positionToID_;
732
+ operators_ = other.operators_;
733
+
734
+ return *this;
735
+ }
736
+
737
+ template <class Master_matrix>
738
+ inline RU_matrix<Master_matrix>& RU_matrix<Master_matrix>::operator=(RU_matrix&& other) noexcept
739
+ {
740
+ if (this == &other) return *this;
741
+
742
+ Pair_opt::operator=(std::move(other));
743
+ Swap_opt::operator=(std::move(other));
744
+ Rep_opt::operator=(std::move(other));
745
+
746
+ reducedMatrixR_ = std::move(other.reducedMatrixR_);
747
+ mirrorMatrixU_ = std::move(other.mirrorMatrixU_);
748
+ pivotToColumnIndex_ = std::move(other.pivotToColumnIndex_);
749
+ nextEventIndex_ = std::exchange(other.nextEventIndex_, 0);
750
+ positionToID_ = std::move(other.positionToID_);
751
+ operators_ = std::exchange(other.operators_, nullptr);
752
+ }
753
+
754
+ template <class Master_matrix>
755
+ inline void RU_matrix<Master_matrix>::print()
756
+ {
757
+ std::cout << "R_matrix:\n";
758
+ reducedMatrixR_.print();
759
+ std::cout << "U_matrix:\n";
760
+ mirrorMatrixU_.print();
761
+ }
762
+
763
+ template <class Master_matrix>
764
+ inline void RU_matrix<Master_matrix>::_insert_boundary(Index currentIndex)
765
+ {
766
+ mirrorMatrixU_.insert_column(currentIndex, 1);
767
+
768
+ if constexpr (!Master_matrix::Option_list::has_map_column_container) {
769
+ ID_index pivot = reducedMatrixR_.get_column(currentIndex).get_pivot();
770
+ if (pivot != Master_matrix::template get_null_value<ID_index>() && pivotToColumnIndex_.size() <= pivot)
771
+ pivotToColumnIndex_.resize((pivot + 1) * 2, Master_matrix::template get_null_value<Index>());
772
+ }
773
+
774
+ _reduce_last_column(currentIndex);
775
+ ++nextEventIndex_;
776
+ }
777
+
778
+ template <class Master_matrix>
779
+ inline void RU_matrix<Master_matrix>::_initialize_U()
780
+ {
781
+ for (ID_index i = 0; i < reducedMatrixR_.get_number_of_columns(); i++) {
782
+ mirrorMatrixU_.insert_column(i, 1);
783
+ }
784
+ }
785
+
786
+ template <class Master_matrix>
787
+ inline void RU_matrix<Master_matrix>::_reduce()
788
+ {
789
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
790
+ Pair_opt::_reserve(reducedMatrixR_.get_number_of_columns());
791
+ }
792
+
793
+ for (Index i = 0; i < reducedMatrixR_.get_number_of_columns(); i++) {
794
+ if (!(reducedMatrixR_.is_zero_column(i))) {
795
+ _reduce_column(i, i);
796
+ } else {
797
+ _add_bar(get_column_dimension(i), i);
798
+ }
799
+ }
800
+ }
801
+
802
+ template <class Master_matrix>
803
+ inline void RU_matrix<Master_matrix>::_reduce_last_column(Index lastIndex)
804
+ {
805
+ if (reducedMatrixR_.get_column(lastIndex).is_empty()) {
806
+ _add_bar(get_column_dimension(lastIndex), nextEventIndex_);
807
+ return;
808
+ }
809
+
810
+ _reduce_column(lastIndex, nextEventIndex_);
811
+ }
812
+
813
+ template <class Master_matrix>
814
+ inline void RU_matrix<Master_matrix>::_reduce_column(Index target, Index eventIndex)
815
+ {
816
+ Column& curr = reducedMatrixR_.get_column(target);
817
+ ID_index pivot = curr.get_pivot();
818
+ Index currIndex = _get_column_with_pivot(pivot);
819
+
820
+ while (pivot != Master_matrix::template get_null_value<ID_index>() &&
821
+ currIndex != Master_matrix::template get_null_value<Index>()) {
822
+ _reduce_column_by(target, currIndex);
823
+ pivot = curr.get_pivot();
824
+ currIndex = _get_column_with_pivot(pivot);
825
+ }
826
+
827
+ if (pivot != Master_matrix::template get_null_value<ID_index>()) {
828
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
829
+ pivotToColumnIndex_.try_emplace(pivot, target);
830
+ } else {
831
+ pivotToColumnIndex_[pivot] = target;
832
+ }
833
+ _update_barcode(pivot, eventIndex);
834
+ } else {
835
+ _add_bar(get_column_dimension(target), eventIndex);
836
+ }
837
+ }
838
+
839
+ template <class Master_matrix>
840
+ inline void RU_matrix<Master_matrix>::_reduce_column_by(Index target, Index source)
841
+ {
842
+ Column& curr = reducedMatrixR_.get_column(target);
843
+ if constexpr (Master_matrix::Option_list::is_z2) {
844
+ curr += reducedMatrixR_.get_column(source);
845
+ // to avoid having to do line operations, U is transposed
846
+ // TODO: explain this somewhere in the documentation...
847
+ mirrorMatrixU_.get_column(source).push_back(*mirrorMatrixU_.get_column(target).begin());
848
+ } else {
849
+ Column& toadd = reducedMatrixR_.get_column(source);
850
+ Field_element coef = toadd.get_pivot_value();
851
+ coef = operators_->get_inverse(coef);
852
+ operators_->multiply_inplace(coef, operators_->get_characteristic() - curr.get_pivot_value());
853
+
854
+ curr.multiply_source_and_add(toadd, coef);
855
+ auto entry = *mirrorMatrixU_.get_column(target).begin();
856
+ operators_->multiply_inplace(entry.get_element(), operators_->get_characteristic() - coef);
857
+ // to avoid having to do line operations, U is transposed
858
+ // TODO: explain this somewhere in the documentation...
859
+ mirrorMatrixU_.get_column(source).push_back(entry);
860
+ }
861
+ }
862
+
863
+ template <class Master_matrix>
864
+ inline typename RU_matrix<Master_matrix>::Index RU_matrix<Master_matrix>::_get_column_with_pivot(ID_index pivot) const
865
+ {
866
+ if (pivot == Master_matrix::template get_null_value<ID_index>())
867
+ return Master_matrix::template get_null_value<Index>();
868
+ if constexpr (Master_matrix::Option_list::has_map_column_container) {
869
+ auto it = pivotToColumnIndex_.find(pivot);
870
+ if (it == pivotToColumnIndex_.end()) return Master_matrix::template get_null_value<Index>();
871
+ return it->second;
872
+ } else {
873
+ if (pivot >= pivotToColumnIndex_.size()) return Master_matrix::template get_null_value<Index>();
874
+ return pivotToColumnIndex_[pivot];
875
+ }
876
+ }
877
+
878
+ template <class Master_matrix>
879
+ inline void RU_matrix<Master_matrix>::_update_barcode(ID_index birthPivot, Pos_index death)
880
+ {
881
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
882
+ Pair_opt::_update_barcode(birthPivot, death);
883
+ }
884
+ }
885
+
886
+ template <class Master_matrix>
887
+ inline void RU_matrix<Master_matrix>::_add_bar(Dimension dim, Pos_index birth)
888
+ {
889
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
890
+ Pair_opt::_add_bar(dim, birth);
891
+ }
892
+ }
893
+
894
+ template <class Master_matrix>
895
+ inline void RU_matrix<Master_matrix>::_remove_last_in_barcode(Pos_index eventIndex)
896
+ {
897
+ if constexpr (Master_matrix::Option_list::has_column_pairings) {
898
+ Pair_opt::_remove_last(eventIndex);
899
+ }
900
+ }
901
+
902
+ } // namespace persistence_matrix
903
+ } // namespace Gudhi
904
+
905
+ #endif // PM_RU_MATRIX_H