multipers 2.3.3b6__cp312-cp312-manylinux_2_39_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of multipers might be problematic. Click here for more details.

Files changed (182) hide show
  1. multipers/__init__.py +33 -0
  2. multipers/_signed_measure_meta.py +453 -0
  3. multipers/_slicer_meta.py +211 -0
  4. multipers/array_api/__init__.py +45 -0
  5. multipers/array_api/numpy.py +41 -0
  6. multipers/array_api/torch.py +58 -0
  7. multipers/data/MOL2.py +458 -0
  8. multipers/data/UCR.py +18 -0
  9. multipers/data/__init__.py +1 -0
  10. multipers/data/graphs.py +466 -0
  11. multipers/data/immuno_regions.py +27 -0
  12. multipers/data/minimal_presentation_to_st_bf.py +0 -0
  13. multipers/data/pytorch2simplextree.py +91 -0
  14. multipers/data/shape3d.py +101 -0
  15. multipers/data/synthetic.py +113 -0
  16. multipers/distances.py +202 -0
  17. multipers/filtration_conversions.pxd +229 -0
  18. multipers/filtration_conversions.pxd.tp +84 -0
  19. multipers/filtrations/__init__.py +18 -0
  20. multipers/filtrations/density.py +574 -0
  21. multipers/filtrations/filtrations.py +361 -0
  22. multipers/filtrations.pxd +224 -0
  23. multipers/function_rips.cpython-312-x86_64-linux-gnu.so +0 -0
  24. multipers/function_rips.pyx +105 -0
  25. multipers/grids.cpython-312-x86_64-linux-gnu.so +0 -0
  26. multipers/grids.pyx +433 -0
  27. multipers/gudhi/Persistence_slices_interface.h +132 -0
  28. multipers/gudhi/Simplex_tree_interface.h +239 -0
  29. multipers/gudhi/Simplex_tree_multi_interface.h +551 -0
  30. multipers/gudhi/cubical_to_boundary.h +59 -0
  31. multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
  32. multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
  33. multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
  34. multipers/gudhi/gudhi/Debug_utils.h +45 -0
  35. multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
  36. multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
  37. multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
  38. multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
  39. multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
  40. multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
  41. multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
  42. multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
  43. multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
  44. multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
  45. multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
  46. multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
  47. multipers/gudhi/gudhi/Matrix.h +2107 -0
  48. multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
  49. multipers/gudhi/gudhi/Multi_persistence/Box.h +174 -0
  50. multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
  51. multipers/gudhi/gudhi/Off_reader.h +173 -0
  52. multipers/gudhi/gudhi/One_critical_filtration.h +1441 -0
  53. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
  54. multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
  55. multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
  56. multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
  57. multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
  58. multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
  59. multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
  60. multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
  61. multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
  62. multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
  63. multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
  64. multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
  65. multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
  66. multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
  67. multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
  68. multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
  69. multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
  70. multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
  71. multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
  72. multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
  73. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
  74. multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
  75. multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
  76. multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
  77. multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
  78. multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
  79. multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
  80. multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
  81. multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
  82. multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
  83. multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
  84. multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
  85. multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
  86. multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
  87. multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
  88. multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
  89. multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
  90. multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
  91. multipers/gudhi/gudhi/Points_off_io.h +171 -0
  92. multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
  93. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
  94. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
  95. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
  96. multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
  97. multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
  98. multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
  99. multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
  100. multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
  101. multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
  102. multipers/gudhi/gudhi/Simplex_tree_multi.h +152 -0
  103. multipers/gudhi/gudhi/distance_functions.h +62 -0
  104. multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
  105. multipers/gudhi/gudhi/persistence_interval.h +253 -0
  106. multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
  107. multipers/gudhi/gudhi/reader_utils.h +367 -0
  108. multipers/gudhi/mma_interface_coh.h +256 -0
  109. multipers/gudhi/mma_interface_h0.h +223 -0
  110. multipers/gudhi/mma_interface_matrix.h +293 -0
  111. multipers/gudhi/naive_merge_tree.h +536 -0
  112. multipers/gudhi/scc_io.h +310 -0
  113. multipers/gudhi/truc.h +1403 -0
  114. multipers/io.cpython-312-x86_64-linux-gnu.so +0 -0
  115. multipers/io.pyx +644 -0
  116. multipers/ml/__init__.py +0 -0
  117. multipers/ml/accuracies.py +90 -0
  118. multipers/ml/invariants_with_persistable.py +79 -0
  119. multipers/ml/kernels.py +176 -0
  120. multipers/ml/mma.py +713 -0
  121. multipers/ml/one.py +472 -0
  122. multipers/ml/point_clouds.py +352 -0
  123. multipers/ml/signed_measures.py +1589 -0
  124. multipers/ml/sliced_wasserstein.py +461 -0
  125. multipers/ml/tools.py +113 -0
  126. multipers/mma_structures.cpython-312-x86_64-linux-gnu.so +0 -0
  127. multipers/mma_structures.pxd +128 -0
  128. multipers/mma_structures.pyx +2786 -0
  129. multipers/mma_structures.pyx.tp +1094 -0
  130. multipers/multi_parameter_rank_invariant/diff_helpers.h +84 -0
  131. multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
  132. multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
  133. multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
  134. multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
  135. multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
  136. multipers/multiparameter_edge_collapse.py +41 -0
  137. multipers/multiparameter_module_approximation/approximation.h +2330 -0
  138. multipers/multiparameter_module_approximation/combinatory.h +129 -0
  139. multipers/multiparameter_module_approximation/debug.h +107 -0
  140. multipers/multiparameter_module_approximation/euler_curves.h +0 -0
  141. multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
  142. multipers/multiparameter_module_approximation/heap_column.h +238 -0
  143. multipers/multiparameter_module_approximation/images.h +79 -0
  144. multipers/multiparameter_module_approximation/list_column.h +174 -0
  145. multipers/multiparameter_module_approximation/list_column_2.h +232 -0
  146. multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
  147. multipers/multiparameter_module_approximation/set_column.h +135 -0
  148. multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
  149. multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
  150. multipers/multiparameter_module_approximation/utilities.h +403 -0
  151. multipers/multiparameter_module_approximation/vector_column.h +223 -0
  152. multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
  153. multipers/multiparameter_module_approximation/vineyards.h +464 -0
  154. multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
  155. multipers/multiparameter_module_approximation.cpython-312-x86_64-linux-gnu.so +0 -0
  156. multipers/multiparameter_module_approximation.pyx +235 -0
  157. multipers/pickle.py +90 -0
  158. multipers/plots.py +456 -0
  159. multipers/point_measure.cpython-312-x86_64-linux-gnu.so +0 -0
  160. multipers/point_measure.pyx +395 -0
  161. multipers/simplex_tree_multi.cpython-312-x86_64-linux-gnu.so +0 -0
  162. multipers/simplex_tree_multi.pxd +134 -0
  163. multipers/simplex_tree_multi.pyx +10840 -0
  164. multipers/simplex_tree_multi.pyx.tp +2009 -0
  165. multipers/slicer.cpython-312-x86_64-linux-gnu.so +0 -0
  166. multipers/slicer.pxd +3034 -0
  167. multipers/slicer.pxd.tp +234 -0
  168. multipers/slicer.pyx +20481 -0
  169. multipers/slicer.pyx.tp +1088 -0
  170. multipers/tensor/tensor.h +672 -0
  171. multipers/tensor.pxd +13 -0
  172. multipers/test.pyx +44 -0
  173. multipers/tests/__init__.py +62 -0
  174. multipers/torch/__init__.py +1 -0
  175. multipers/torch/diff_grids.py +240 -0
  176. multipers/torch/rips_density.py +310 -0
  177. multipers-2.3.3b6.dist-info/METADATA +128 -0
  178. multipers-2.3.3b6.dist-info/RECORD +182 -0
  179. multipers-2.3.3b6.dist-info/WHEEL +5 -0
  180. multipers-2.3.3b6.dist-info/licenses/LICENSE +21 -0
  181. multipers-2.3.3b6.dist-info/top_level.txt +1 -0
  182. multipers.libs/libtbb-ca48af5c.so.12.16 +0 -0
@@ -0,0 +1,1070 @@
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): Pawel Dlotko
4
+ *
5
+ * Copyright (C) 2015 Inria
6
+ *
7
+ * Modification(s):
8
+ * - YYYY/MM Author: Description of the modification
9
+ */
10
+
11
+ #ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_
12
+ #define BITMAP_CUBICAL_COMPLEX_BASE_H_
13
+
14
+ #include <gudhi/Debug_utils.h>
15
+
16
+ #include <boost/config.hpp>
17
+ #include <boost/iterator/counting_iterator.hpp>
18
+ #include <boost/range/iterator_range.hpp>
19
+
20
+ #include <iostream>
21
+ #include <vector>
22
+ #include <string>
23
+ #include <fstream>
24
+ #include <algorithm>
25
+ #include <iterator>
26
+ #include <limits>
27
+ #include <utility>
28
+ #include <stdexcept>
29
+ #include <cstddef>
30
+ #include <numeric>
31
+ #include <functional>
32
+
33
+ namespace Gudhi {
34
+
35
+ namespace cubical_complex {
36
+
37
+ /**
38
+ * @brief Cubical complex represented as a bitmap, class with basic implementation.
39
+ * @ingroup cubical_complex
40
+ * @details This is a class implementing a basic bitmap data structure to store cubical complexes.
41
+ * It implements only the most basic subroutines.
42
+ * The idea of the bitmap is the following. Our aim is to have a memory efficient
43
+ * data structure to store d-dimensional cubical complex
44
+ * C being a cubical decomposition
45
+ * of a rectangular region of a space. This is achieved by storing C as a
46
+ * vector of bits (this is where the name 'bitmap' came from).
47
+ * Each cell is represented by a single
48
+ * bit (in case of black and white bitmaps, or by a single element of a type T
49
+ * (here T is a filtration type of a bitmap, typically a double).
50
+ * All the information needed for homology and
51
+ * persistent homology computations (like dimension of a cell, boundary and
52
+ * coboundary elements of a cell, are then obtained from the
53
+ * position of the element in C.
54
+ * The default filtration used in this implementation is the lower star filtration.
55
+ */
56
+ template <typename T>
57
+ class Bitmap_cubical_complex_base {
58
+ public:
59
+ typedef T filtration_type;
60
+
61
+ /**
62
+ *Default constructor
63
+ **/
64
+ Bitmap_cubical_complex_base() {}
65
+ /**
66
+ * There are a few constructors of a Bitmap_cubical_complex_base class.
67
+ * First one, that takes vector<unsigned>, creates an empty bitmap of a dimension equal
68
+ * the number of elements in the
69
+ * input vector and size in the i-th dimension equal the number in the position i-of the input vector.
70
+ */
71
+ explicit Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes);
72
+ /**
73
+ * The second constructor takes as a input a Perseus style file. For more details,
74
+ * please consult the documentations of
75
+ * Perseus software as well as examples attached to this
76
+ * implementation.
77
+ **/
78
+ explicit Bitmap_cubical_complex_base(const char* perseus_style_file);
79
+ /**
80
+ * The last constructor of a Bitmap_cubical_complex_base class accepts vector of dimensions (as the first one)
81
+ * with vector of filtration values of vertices or top dimensional cells depending on the input_top_cells flag.
82
+ **/
83
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& cells, bool input_top_cells = true);
84
+
85
+ /**
86
+ * Destructor of the Bitmap_cubical_complex_base class.
87
+ **/
88
+ virtual ~Bitmap_cubical_complex_base() {}
89
+
90
+ /**
91
+ * The functions get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell
92
+ * and get_cell_data are the basic
93
+ * functions that compute boundary / coboundary / dimension and the filtration
94
+ * value form a position of a cell in the structure of a bitmap. The input parameter of all of those function is a
95
+ * non-negative integer, indicating a position of a cube in the data structure.
96
+ * In the case of functions that compute (co)boundary, the output is a vector if non-negative integers pointing to
97
+ * the positions of (co)boundary element of the input cell.
98
+ * The boundary elements are guaranteed to be returned so that the
99
+ * incidence coefficients of boundary elements are alternating.
100
+ */
101
+ virtual inline std::vector<std::size_t> get_boundary_of_a_cell(std::size_t cell) const;
102
+ /**
103
+ * The functions get_coboundary_of_a_cell, get_coboundary_of_a_cell,
104
+ * get_dimension_of_a_cell and get_cell_data are the basic
105
+ * functions that compute boundary / coboundary / dimension and the filtration
106
+ * value form a position of a cell in the structure of a bitmap.
107
+ * The input parameter of all of those function is a non-negative integer,
108
+ * indicating a position of a cube in the data structure.
109
+ * In the case of functions that compute (co)boundary, the output is a vector if
110
+ * non-negative integers pointing to the
111
+ * positions of (co)boundary element of the input cell.
112
+ * Note that unlike in the case of boundary, over here the elements are
113
+ * not guaranteed to be returned with alternating incidence numbers.
114
+ *
115
+ **/
116
+ virtual inline std::vector<std::size_t> get_coboundary_of_a_cell(std::size_t cell) const;
117
+
118
+ /**
119
+ * This function finds a top-dimensional cell that is incident to the input cell and has
120
+ * the same filtration value. In case several cells are suitable, an arbitrary one is
121
+ * returned. Note that the input parameter can be a cell of any dimension (vertex, edge, etc).
122
+ * On the other hand, the output is always indicating the position of
123
+ * a top-dimensional cube in the data structure.
124
+ * \pre The filtration values are assigned as per `impose_lower_star_filtration()`.
125
+ **/
126
+ inline size_t get_top_dimensional_coface_of_a_cell(size_t splx);
127
+
128
+ /**
129
+ * This function finds a vertex that is incident to the input cell and has
130
+ * the same filtration value. In case several cells are suitable, an arbitrary one is
131
+ * returned. Note that the input parameter can be a cell of any dimension (vertex, edge, etc).
132
+ * On the other hand, the output is always indicating the position of
133
+ * a vertex in the data structure.
134
+ * \pre The filtration values are assigned as per `impose_lower_star_filtration_from_vertices()`.
135
+ **/
136
+ inline size_t get_vertex_of_a_cell(size_t splx);
137
+
138
+ /**
139
+ * This procedure compute incidence numbers between cubes. For a cube \f$A\f$ of
140
+ * dimension n and a cube \f$B \subset A\f$ of dimension n-1, an incidence
141
+ * between \f$A\f$ and \f$B\f$ is the integer with which \f$B\f$ appears in the boundary of \f$A\f$.
142
+ * Note that first parameter is a cube of dimension n,
143
+ * and the second parameter is an adjusted cube in dimension n-1.
144
+ * Given \f$A = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [b_{j},e_{j}] \times [b_{j+1},e_{j+1}] \times \ldots
145
+ *\times [b_{n},e_{n}] \f$
146
+ * such that \f$ b_{j} \neq e_{j} \f$
147
+ * and \f$B = [b_1,e_1] \times \ldots \ [b_{j-1},e_{j-1}] \times [a,a] \times [b_{j+1},e_{j+1}] \times \ldots \times
148
+ *[b_{n},e_{n}] \f$
149
+ * where \f$ a = b_{j}\f$ or \f$ a = e_{j}\f$, the incidence between \f$A\f$ and \f$B\f$
150
+ * computed by this procedure is given by formula:
151
+ * \f$ c\ (-1)^{\sum_{i=1}^{j-1} dim [b_{i},e_{i}]} \f$
152
+ * Where \f$ dim [b_{i},e_{i}] = 0 \f$ if \f$ b_{i}=e_{i} \f$ and 1 in other case.
153
+ * c is -1 if \f$ a = b_{j}\f$ and 1 if \f$ a = e_{j}\f$.
154
+ * @exception std::logic_error In case when the cube \f$B\f$ is not n-1
155
+ * dimensional face of a cube \f$A\f$.
156
+ **/
157
+ virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const {
158
+ // first get the counters for coface and face:
159
+ std::vector<unsigned> coface_counter = this->compute_counter_for_given_cell(coface);
160
+ std::vector<unsigned> face_counter = this->compute_counter_for_given_cell(face);
161
+
162
+ // coface_counter and face_counter should agree at all positions except from one:
163
+ int number_of_position_in_which_counters_do_not_agree = -1;
164
+ std::size_t number_of_full_faces_that_comes_before = 0;
165
+ for (std::size_t i = 0; i != coface_counter.size(); ++i) {
166
+ if ((coface_counter[i] % 2 == 1) && (number_of_position_in_which_counters_do_not_agree == -1)) {
167
+ ++number_of_full_faces_that_comes_before;
168
+ }
169
+ if (coface_counter[i] != face_counter[i]) {
170
+ if (number_of_position_in_which_counters_do_not_agree != -1) {
171
+ std::cerr << "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.\n";
172
+ throw std::logic_error(
173
+ "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.");
174
+ }
175
+ number_of_position_in_which_counters_do_not_agree = i;
176
+ }
177
+ }
178
+
179
+ int incidence = 1;
180
+ if (number_of_full_faces_that_comes_before % 2) incidence = -1;
181
+ // if the face cell is on the right from coface cell:
182
+ if (coface_counter[number_of_position_in_which_counters_do_not_agree] + 1 ==
183
+ face_counter[number_of_position_in_which_counters_do_not_agree]) {
184
+ incidence *= -1;
185
+ }
186
+
187
+ return incidence;
188
+ }
189
+
190
+ /**
191
+ * In the case of get_dimension_of_a_cell function, the output is a non-negative integer
192
+ * indicating the dimension of a cell.
193
+ * Note that unlike in the case of boundary, over here the elements are
194
+ * not guaranteed to be returned with alternating incidence numbers.
195
+ * To compute incidence between cells use compute_incidence_between_cells
196
+ * procedure
197
+ **/
198
+ inline unsigned get_dimension_of_a_cell(std::size_t cell) const;
199
+
200
+ /**
201
+ * In the case of get_cell_data, the output parameter is a reference to the value of a cube in a given position.
202
+ * This allows reading and changing the value of filtration. Note that if the value of a filtration is changed, the
203
+ * code do not check if we have a filtration or not. i.e. it do not check if the value of a filtration of a cell is
204
+ * not smaller than the value of a filtration of its boundary and not greater than the value of its coboundary.
205
+ **/
206
+ inline T& get_cell_data(std::size_t cell);
207
+
208
+ /**
209
+ * Typical input used to construct a baseBitmap class is a filtration given at the top dimensional cells.
210
+ * Then, there are a few ways one can pick the filtration of lower dimensional
211
+ * cells. The most typical one is by so called lower star filtration. This function is always called by any
212
+ * constructor which takes the top dimensional cells. If you use such a constructor,
213
+ * then there is no need to call this function. Call it only if you are putting the filtration
214
+ * of the cells by your own (for instance by using Top_dimensional_cells_iterator).
215
+ **/
216
+ void impose_lower_star_filtration(); // assume that top dimensional cells are already set.
217
+
218
+ /**
219
+ * Set cells filtrations given those of the vertices, and based on lower star filtration.
220
+ * This is already called by the relevant constructors.
221
+ **/
222
+ void impose_lower_star_filtration_from_vertices(); // assume that vertices are already set.
223
+
224
+ /**
225
+ * Returns dimension of a complex.
226
+ **/
227
+ inline unsigned dimension() const { return sizes.size(); }
228
+
229
+ /**
230
+ * Returns number of all cubes in the data structure.
231
+ **/
232
+ inline std::size_t size() const { return this->data.size(); }
233
+
234
+ /**
235
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
236
+ * equally distributed in the range of data.
237
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
238
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
239
+ * some number of bins. The function put_data_to_bins( std::size_t number_of_bins ) is designed for that purpose.
240
+ * The parameter of the function is the number of bins (distinct values) we want to have in the cubical complex.
241
+ **/
242
+ void put_data_to_bins(std::size_t number_of_bins);
243
+
244
+ /**
245
+ * Function that put the input data to bins. By putting data to bins we mean rounding them to a sequence of values
246
+ * equally distributed in the range of data.
247
+ * Sometimes if most of the cells have different birth-death times, the performance of the algorithms to compute
248
+ * persistence gets worst. When dealing with this type of data, one may want to put different values on cells to
249
+ * some number of bins. The function put_data_to_bins( T diameter_of_bin ) is designed for that purpose.
250
+ * The parameter of it is the diameter of each bin. Note that the bottleneck distance between the persistence
251
+ * diagram of the cubical complex before and after using such a function will be bounded by the parameter
252
+ * diameter_of_bin.
253
+ **/
254
+ void put_data_to_bins(T diameter_of_bin);
255
+
256
+ /**
257
+ * Functions to find min and max values of filtration.
258
+ **/
259
+ std::pair<T, T> min_max_filtration();
260
+
261
+ // ITERATORS
262
+
263
+ /**
264
+ * @brief Iterator through all cells in the complex (in order they appear in the structure -- i.e.
265
+ * in lexicographical order).
266
+ **/
267
+ typedef boost::counting_iterator<std::size_t> All_cells_iterator;
268
+
269
+ /**
270
+ * Function returning a All_cells_iterator to the first cell of the bitmap.
271
+ **/
272
+ All_cells_iterator all_cells_iterator_begin() const { return All_cells_iterator(0); }
273
+
274
+ /**
275
+ * Function returning a All_cells_iterator beyond the last cell of the bitmap.
276
+ **/
277
+ All_cells_iterator all_cells_iterator_end() const { return All_cells_iterator(data.size()); }
278
+
279
+ /**
280
+ * @brief Range corresponding to All_cells_iterator
281
+ **/
282
+ typedef boost::iterator_range<All_cells_iterator> All_cells_range;
283
+
284
+ /** Returns a range over all cells. */
285
+ All_cells_range all_cells_range() const { return All_cells_range(all_cells_iterator_begin(), all_cells_iterator_end()); }
286
+
287
+ /**
288
+ * Boundary_range class provides ranges for boundary iterators.
289
+ **/
290
+ typedef typename std::vector<std::size_t>::const_iterator Boundary_iterator;
291
+ typedef typename std::vector<std::size_t> Boundary_range;
292
+
293
+ /**
294
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
295
+ * that provides ranges for the Boundary_simplex_iterator.
296
+ **/
297
+ Boundary_range boundary_range(std::size_t sh) { return this->get_boundary_of_a_cell(sh); }
298
+
299
+ /**
300
+ * Coboundary_range class provides ranges for boundary iterators.
301
+ **/
302
+ typedef typename std::vector<std::size_t>::const_iterator Coboundary_iterator;
303
+ typedef typename std::vector<std::size_t> Coboundary_range;
304
+
305
+ /**
306
+ * boundary_simplex_range creates an object of a Boundary_simplex_range class
307
+ * that provides ranges for the Boundary_simplex_iterator.
308
+ **/
309
+ Coboundary_range coboundary_range(std::size_t sh) { return this->get_coboundary_of_a_cell(sh); }
310
+
311
+ /**
312
+ * @brief Iterator through top dimensional cells of the complex. The cells appear in order they are stored
313
+ * in the structure (i.e. in lexicographical order)
314
+ **/
315
+ class Top_dimensional_cells_iterator {
316
+ public:
317
+ typedef std::input_iterator_tag iterator_category;
318
+ typedef std::size_t value_type;
319
+ typedef std::ptrdiff_t difference_type;
320
+ typedef value_type* pointer;
321
+ typedef value_type reference;
322
+
323
+ Top_dimensional_cells_iterator(Bitmap_cubical_complex_base* b) : counter(b->dimension()), b(b) {}
324
+
325
+ Top_dimensional_cells_iterator operator++() {
326
+ // first find first element of the counter that can be increased:
327
+ std::size_t dim = 0;
328
+ while ((dim != this->b->dimension()) && (this->counter[dim] == this->b->sizes[dim] - 1)) ++dim;
329
+
330
+ if (dim != this->b->dimension()) {
331
+ ++this->counter[dim];
332
+ for (std::size_t i = 0; i != dim; ++i) {
333
+ this->counter[i] = 0;
334
+ }
335
+ } else {
336
+ ++this->counter[0];
337
+ }
338
+ return *this;
339
+ }
340
+
341
+ Top_dimensional_cells_iterator operator++(int) {
342
+ Top_dimensional_cells_iterator result = *this;
343
+ ++(*this);
344
+ return result;
345
+ }
346
+
347
+ bool operator==(const Top_dimensional_cells_iterator& rhs) const {
348
+ if (this->b != rhs.b) return false;
349
+ if (this->counter.size() != rhs.counter.size()) return false;
350
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
351
+ if (this->counter[i] != rhs.counter[i]) return false;
352
+ }
353
+ return true;
354
+ }
355
+
356
+ bool operator!=(const Top_dimensional_cells_iterator& rhs) const { return !(*this == rhs); }
357
+
358
+ /*
359
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
360
+ * an argument of the following functions:
361
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
362
+ * boundary and coboundary and dimension
363
+ * and in function get_cell_data to get a filtration of a cell.
364
+ */
365
+ std::size_t operator*() { return this->compute_index_in_bitmap(); }
366
+
367
+ std::size_t compute_index_in_bitmap() const {
368
+ std::size_t index = 0;
369
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
370
+ index += (2 * this->counter[i] + 1) * this->b->multipliers[i];
371
+ }
372
+ return index;
373
+ }
374
+
375
+ void print_counter() const {
376
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
377
+ std::clog << this->counter[i] << " ";
378
+ }
379
+ }
380
+ friend class Bitmap_cubical_complex_base;
381
+
382
+ protected:
383
+ std::vector<std::size_t> counter;
384
+ Bitmap_cubical_complex_base* b;
385
+ };
386
+
387
+ /**
388
+ * Function returning a Top_dimensional_cells_iterator to the first top dimensional cell of the bitmap.
389
+ **/
390
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin() {
391
+ Top_dimensional_cells_iterator a(this);
392
+ return a;
393
+ }
394
+
395
+ /**
396
+ * Function returning a Top_dimensional_cells_iterator beyond the last top dimensional cell of the bitmap.
397
+ **/
398
+ Top_dimensional_cells_iterator top_dimensional_cells_iterator_end() {
399
+ Top_dimensional_cells_iterator a(this);
400
+ for (std::size_t i = 0; i != this->dimension(); ++i) {
401
+ a.counter[i] = this->sizes[i] - 1;
402
+ }
403
+ a.counter[0]++;
404
+ return a;
405
+ }
406
+
407
+ /**
408
+ * @brief Range corresponding to Top_dimensional_cells_iterator
409
+ **/
410
+ class Top_dimensional_cells_range {
411
+ public:
412
+ Top_dimensional_cells_range(Bitmap_cubical_complex_base* b) : b(b) {}
413
+
414
+ Top_dimensional_cells_iterator begin() { return b->top_dimensional_cells_iterator_begin(); }
415
+
416
+ Top_dimensional_cells_iterator end() { return b->top_dimensional_cells_iterator_end(); }
417
+
418
+ private:
419
+ Bitmap_cubical_complex_base<T>* b;
420
+ };
421
+
422
+ /** Returns a range over all top-dimensional cells. */
423
+ Top_dimensional_cells_range top_dimensional_cells_range() { return Top_dimensional_cells_range(this); }
424
+
425
+ //****************************************************************************************************************//
426
+ //****************************************************************************************************************//
427
+ //****************************************************************************************************************//
428
+ //****************************************************************************************************************//
429
+ class Vertices_iterator {
430
+ public:
431
+ typedef std::input_iterator_tag iterator_category;
432
+ typedef std::size_t value_type;
433
+ typedef std::ptrdiff_t difference_type;
434
+ typedef value_type* pointer;
435
+ typedef value_type reference;
436
+
437
+ Vertices_iterator(Bitmap_cubical_complex_base* b) : counter(b->dimension()), b(b) {}
438
+
439
+ Vertices_iterator operator++() {
440
+ // first find first element of the counter that can be increased:
441
+ std::size_t dim = 0;
442
+ while ((dim != this->b->dimension()) && (this->counter[dim] == this->b->sizes[dim])) ++dim;
443
+
444
+ if (dim != this->b->dimension()) {
445
+ ++this->counter[dim];
446
+ for (std::size_t i = 0; i != dim; ++i) {
447
+ this->counter[i] = 0;
448
+ }
449
+ } else {
450
+ ++this->counter[0];
451
+ }
452
+ return *this;
453
+ }
454
+
455
+ Vertices_iterator operator++(int) {
456
+ Vertices_iterator result = *this;
457
+ ++(*this);
458
+ return result;
459
+ }
460
+
461
+ bool operator==(const Vertices_iterator& rhs) const {
462
+ if (this->b != rhs.b) return false;
463
+ GUDHI_CHECK(this->counter.size() == rhs.counter.size(), "impossible");
464
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
465
+ if (this->counter[i] != rhs.counter[i]) return false;
466
+ }
467
+ return true;
468
+ }
469
+
470
+ bool operator!=(const Vertices_iterator& rhs) const { return !(*this == rhs); }
471
+
472
+ /*
473
+ * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
474
+ * an argument of the following functions:
475
+ * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
476
+ * boundary and coboundary and dimension
477
+ * and in function get_cell_data to get a filtration of a cell.
478
+ */
479
+ std::size_t operator*() const { return this->compute_index_in_bitmap(); }
480
+
481
+ std::size_t compute_index_in_bitmap() const {
482
+ std::size_t index = 0;
483
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
484
+ index += 2 * this->counter[i] * this->b->multipliers[i];
485
+ }
486
+ return index;
487
+ }
488
+
489
+ void print_counter() const {
490
+ for (std::size_t i = 0; i != this->counter.size(); ++i) {
491
+ std::clog << this->counter[i] << " ";
492
+ }
493
+ }
494
+ friend class Bitmap_cubical_complex_base;
495
+
496
+ protected:
497
+ std::vector<std::size_t> counter;
498
+ Bitmap_cubical_complex_base* b;
499
+ };
500
+
501
+ /*
502
+ * Function returning a Vertices_iterator to the first vertex of the bitmap.
503
+ */
504
+ Vertices_iterator vertices_iterator_begin() {
505
+ Vertices_iterator a(this);
506
+ return a;
507
+ }
508
+
509
+ /*
510
+ * Function returning a Vertices_iterator to the last vertex of the bitmap.
511
+ */
512
+ Vertices_iterator vertices_iterator_end() {
513
+ Vertices_iterator a(this);
514
+ for (std::size_t i = 0; i != this->dimension(); ++i) {
515
+ a.counter[i] = this->sizes[i];
516
+ }
517
+ a.counter[0]++;
518
+ return a;
519
+ }
520
+
521
+ /*
522
+ * @brief Vertices_iterator_range class provides ranges for Vertices_iterator_range
523
+ */
524
+ class Vertices_range {
525
+ public:
526
+ Vertices_range(Bitmap_cubical_complex_base* b) : b(b) {}
527
+
528
+ Vertices_iterator begin() { return b->vertices_iterator_begin(); }
529
+
530
+ Vertices_iterator end() { return b->vertices_iterator_end(); }
531
+
532
+ private:
533
+ Bitmap_cubical_complex_base* b;
534
+ };
535
+
536
+ /* Returns a range over all vertices. */
537
+ Vertices_range vertices_range() { return Vertices_range(this); }
538
+
539
+ //****************************************************************************************************************//
540
+ //****************************************************************************************************************//
541
+ //****************************************************************************************************************//
542
+ //****************************************************************************************************************//
543
+
544
+ inline std::size_t number_cells() const { return this->data.size(); }
545
+
546
+ //****************************************************************************************************************//
547
+ //****************************************************************************************************************//
548
+ //****************************************************************************************************************//
549
+ //****************************************************************************************************************//
550
+
551
+ /// @private @brief execute the function on each cell id corresponding to a vertex, in increasing order.
552
+ template <class F> void for_each_vertex(F&&f) {
553
+ for_each_vertex_rec(f, 0, multipliers.size()-1);
554
+ }
555
+
556
+ protected:
557
+ std::vector<unsigned> sizes;
558
+ std::vector<unsigned> multipliers;
559
+ std::vector<T> data;
560
+
561
+ template <class F> void for_each_vertex_rec(F&&f, std::size_t base, int dim);
562
+ void propagate_from_vertices_rec(int special_dim, int current_dim, std::size_t base);
563
+
564
+ void set_up_containers(const std::vector<unsigned>& sizes, bool is_pos_inf) {
565
+ // The fact that multipliers[0]=1 is relied on by optimizations in other functions
566
+ unsigned multiplier = 1;
567
+ for (std::size_t i = 0; i != sizes.size(); ++i) {
568
+ this->sizes.push_back(sizes[i]);
569
+ this->multipliers.push_back(multiplier);
570
+ multiplier *= 2 * sizes[i] + 1;
571
+ }
572
+ if(is_pos_inf)
573
+ this->data = std::vector<T>(multiplier, std::numeric_limits<T>::infinity());
574
+ else
575
+ this->data = std::vector<T>(multiplier, -std::numeric_limits<T>::infinity());
576
+ }
577
+
578
+ std::size_t compute_position_in_bitmap(const std::vector<unsigned>& counter) {
579
+ std::size_t position = 0;
580
+ for (std::size_t i = 0; i != this->multipliers.size(); ++i) {
581
+ position += this->multipliers[i] * counter[i];
582
+ }
583
+ return position;
584
+ }
585
+
586
+ std::vector<unsigned> compute_counter_for_given_cell(std::size_t cell) const {
587
+ std::vector<unsigned> counter;
588
+ counter.reserve(this->sizes.size());
589
+ for (std::size_t dim = this->sizes.size(); dim > 1; --dim) {
590
+ std::size_t quot = cell / this->multipliers[dim - 1];
591
+ cell = cell % this->multipliers[dim - 1];
592
+ counter.push_back(quot);
593
+ }
594
+ // Split out the last iteration to save a costly division by multipliers[0]=1
595
+ counter.push_back(cell);
596
+ std::reverse(counter.begin(), counter.end());
597
+ return counter;
598
+ }
599
+ void read_perseus_style_file(const char* perseus_style_file);
600
+ void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector<unsigned>& sizes_in_following_directions,
601
+ const std::vector<T>& top_dimensional_cells);
602
+ void setup_bitmap_based_on_vertices(const std::vector<unsigned>& sizes_in_following_directions,
603
+ const std::vector<T>& vertices);
604
+ Bitmap_cubical_complex_base(const char* perseus_style_file, const std::vector<bool>& directions);
605
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes, const std::vector<bool>& directions);
606
+ Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& cells,
607
+ const std::vector<bool>& directions, bool input_top_cells);
608
+ };
609
+
610
+ template <typename T>
611
+ void Bitmap_cubical_complex_base<T>::put_data_to_bins(std::size_t number_of_bins) {
612
+
613
+ std::pair<T, T> min_max = this->min_max_filtration();
614
+ T dx = (min_max.second - min_max.first) / (T)number_of_bins;
615
+
616
+ // now put the data into the appropriate bins:
617
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
618
+ #ifdef DEBUG_TRACES
619
+ std::clog << "Before binning : " << this->data[i] << std::endl;
620
+ #endif
621
+ this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins;
622
+ #ifdef DEBUG_TRACES
623
+ std::clog << "After binning : " << this->data[i] << std::endl;
624
+ #endif
625
+ }
626
+ }
627
+
628
+ template <typename T>
629
+ void Bitmap_cubical_complex_base<T>::put_data_to_bins(T diameter_of_bin) {
630
+ std::pair<T, T> min_max = this->min_max_filtration();
631
+
632
+ std::size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin;
633
+ // now put the data into the appropriate bins:
634
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
635
+ #ifdef DEBUG_TRACES
636
+ std::clog << "Before binning : " << this->data[i] << std::endl;
637
+ #endif
638
+ this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins;
639
+ #ifdef DEBUG_TRACES
640
+ std::clog << "After binning : " << this->data[i] << std::endl;
641
+ #endif
642
+ }
643
+ }
644
+
645
+ template <typename T>
646
+ std::pair<T, T> Bitmap_cubical_complex_base<T>::min_max_filtration() {
647
+ std::pair<T, T> min_max(std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity());
648
+ for (std::size_t i = 0; i != this->data.size(); ++i) {
649
+ if (this->data[i] < min_max.first) min_max.first = this->data[i];
650
+ if (this->data[i] > min_max.second) min_max.second = this->data[i];
651
+ }
652
+ return min_max;
653
+ }
654
+
655
+ template <typename T>
656
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes) {
657
+ this->set_up_containers(sizes, true);
658
+ }
659
+
660
+ template <typename T>
661
+ void Bitmap_cubical_complex_base<T>::setup_bitmap_based_on_top_dimensional_cells_list(
662
+ const std::vector<unsigned>& sizes_in_following_directions, const std::vector<T>& top_dimensional_cells) {
663
+ this->set_up_containers(sizes_in_following_directions, true);
664
+ std::size_t number_of_top_dimensional_elements = std::accumulate(std::begin(sizes_in_following_directions),
665
+ std::end(sizes_in_following_directions), std::size_t(1),
666
+ std::multiplies<std::size_t>());
667
+ if (number_of_top_dimensional_elements != top_dimensional_cells.size()) {
668
+ std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<unsigned> "
669
+ << "sizes_in_following_directions, std::vector<T> top_dimensional_cells ). Number of top dimensional "
670
+ << "elements that follow from sizes_in_following_directions vector is different from the size of "
671
+ << "top_dimensional_cells vector."
672
+ << std::endl;
673
+ throw std::invalid_argument(
674
+ "Error in constructor Bitmap_cubical_complex_base( std::vector<unsigned> sizes_in_following_directions,"
675
+ "std::vector<T> top_dimensional_cells ). Number of top dimensional elements that follow from "
676
+ "sizes_in_following_directions vector is different from the size of top_dimensional_cells vector.");
677
+ }
678
+
679
+ std::size_t index = 0;
680
+ for (auto it = this->top_dimensional_cells_iterator_begin();
681
+ it != this->top_dimensional_cells_iterator_end(); ++it) {
682
+ this->get_cell_data(*it) = top_dimensional_cells[index];
683
+ ++index;
684
+ }
685
+ this->impose_lower_star_filtration();
686
+ }
687
+
688
+ template <typename T>
689
+ void Bitmap_cubical_complex_base<T>::setup_bitmap_based_on_vertices(const std::vector<unsigned>& sizes_in_following_directions,
690
+ const std::vector<T>& vertices) {
691
+ std::vector<unsigned> top_cells_sizes;
692
+ std::transform (sizes_in_following_directions.begin(), sizes_in_following_directions.end(), std::back_inserter(top_cells_sizes),
693
+ [](int i){ return i-1;});
694
+ this->set_up_containers(top_cells_sizes, false);
695
+ std::size_t number_of_vertices = std::accumulate(std::begin(sizes_in_following_directions),
696
+ std::end(sizes_in_following_directions), (std::size_t)1,
697
+ std::multiplies<std::size_t>());
698
+ if (number_of_vertices != vertices.size()) {
699
+ std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<unsigned> "
700
+ << "sizes_in_following_directions, std::vector<T> vertices ). Number of vertices "
701
+ << "elements that follow from sizes_in_following_directions vector is different from the size of "
702
+ << "vertices vector."
703
+ << std::endl;
704
+ throw std::invalid_argument(
705
+ "Error in constructor Bitmap_cubical_complex_base( std::vector<unsigned> sizes_in_following_directions,"
706
+ "std::vector<T> vertices ). Number of vertices elements that follow from "
707
+ "sizes_in_following_directions vector is different from the size of vertices vector.");
708
+ }
709
+
710
+ for_each_vertex([this, &vertices, index=(std::size_t)0] (auto cell) mutable { get_cell_data(cell) = vertices[index++]; });
711
+ this->impose_lower_star_filtration_from_vertices();
712
+ }
713
+
714
+ template <typename T>
715
+ size_t Bitmap_cubical_complex_base<T>::get_top_dimensional_coface_of_a_cell(size_t splx) {
716
+ if (this->get_dimension_of_a_cell(splx) == this->dimension()){return splx;}
717
+ else {
718
+ for (auto v : this->get_coboundary_of_a_cell(splx)){
719
+ if(this->get_cell_data(v) == this->get_cell_data(splx)){
720
+ return this->get_top_dimensional_coface_of_a_cell(v);
721
+ }
722
+ }
723
+ }
724
+ BOOST_UNREACHABLE_RETURN(-2);
725
+ }
726
+
727
+ template <typename T>
728
+ size_t Bitmap_cubical_complex_base<T>::get_vertex_of_a_cell(size_t splx) {
729
+ if (this->get_dimension_of_a_cell(splx) == 0){return splx;}
730
+ else {
731
+ for (auto v : this->get_boundary_of_a_cell(splx)){
732
+ if(this->get_cell_data(v) == this->get_cell_data(splx)){
733
+ return this->get_vertex_of_a_cell(v);
734
+ }
735
+ }
736
+ }
737
+ BOOST_UNREACHABLE_RETURN(-2);
738
+ }
739
+
740
+ template <typename T>
741
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes_in_following_directions,
742
+ const std::vector<T>& cells, bool input_top_cells) {
743
+ if (input_top_cells) {
744
+ this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, cells);
745
+ } else {
746
+ this->setup_bitmap_based_on_vertices(sizes_in_following_directions, cells);
747
+ }
748
+ }
749
+
750
+ template <typename T>
751
+ void Bitmap_cubical_complex_base<T>::read_perseus_style_file(const char* perseus_style_file) {
752
+ std::ifstream inFiltration(perseus_style_file);
753
+ if(!inFiltration) throw std::ios_base::failure(std::string("Could not open the file ") + perseus_style_file);
754
+ unsigned dimensionOfData;
755
+ inFiltration >> dimensionOfData;
756
+
757
+ #ifdef DEBUG_TRACES
758
+ std::clog << "dimensionOfData : " << dimensionOfData << std::endl;
759
+ #endif
760
+
761
+ std::vector<unsigned> sizes;
762
+ sizes.reserve(dimensionOfData);
763
+ // all dimensions multiplied
764
+ std::size_t dimensions = 1;
765
+ for (std::size_t i = 0; i != dimensionOfData; ++i) {
766
+ unsigned size_in_this_dimension;
767
+ inFiltration >> size_in_this_dimension;
768
+ sizes.push_back(size_in_this_dimension);
769
+ dimensions *= size_in_this_dimension;
770
+ #ifdef DEBUG_TRACES
771
+ std::clog << "size_in_this_dimension : " << size_in_this_dimension << std::endl;
772
+ #endif
773
+ }
774
+ this->set_up_containers(sizes, true);
775
+
776
+ Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin();
777
+
778
+ T filtrationLevel = 0.;
779
+ std::size_t filtration_counter = 0;
780
+ while (!inFiltration.eof()) {
781
+ std::string line;
782
+ getline(inFiltration, line);
783
+ if (line.length() != 0) {
784
+ int n = sscanf(line.c_str(), "%lf", &filtrationLevel);
785
+ if (n != 1) {
786
+ std::string perseus_error("Bad Perseus file format. This line is incorrect : " + line);
787
+ throw std::ios_base::failure(perseus_error.c_str());
788
+ }
789
+
790
+ #ifdef DEBUG_TRACES
791
+ std::clog << "Cell of an index : " << it.compute_index_in_bitmap()
792
+ << " and dimension: " << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
793
+ << " get the value : " << filtrationLevel << std::endl;
794
+ #endif
795
+ this->get_cell_data(*it) = filtrationLevel;
796
+ ++it;
797
+ ++filtration_counter;
798
+ }
799
+ }
800
+
801
+ if (filtration_counter != dimensions) {
802
+ std::string perseus_error("Bad Perseus file format. Read " + std::to_string(filtration_counter) + " expected " + \
803
+ std::to_string(dimensions) + " values");
804
+ throw std::ios_base::failure(perseus_error);
805
+ }
806
+
807
+ inFiltration.close();
808
+ this->impose_lower_star_filtration();
809
+ }
810
+
811
+ template <typename T>
812
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file,
813
+ const std::vector<bool>& directions) {
814
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
815
+ // conditions.
816
+ // It ignores the last parameter of the function.
817
+ this->read_perseus_style_file(perseus_style_file);
818
+ }
819
+
820
+ template <typename T>
821
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes,
822
+ const std::vector<bool>& directions) {
823
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
824
+ // conditions.
825
+ // It ignores the last parameter of the function.
826
+ this->set_up_containers(sizes, true);
827
+ }
828
+
829
+ template <typename T>
830
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions,
831
+ const std::vector<T>& cells,
832
+ const std::vector<bool>& directions,
833
+ bool input_top_cells) {
834
+ // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
835
+ // conditions.
836
+ // It ignores the last parameter of the function.
837
+ if (input_top_cells) {
838
+ this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, cells);
839
+ } else {
840
+ this->setup_bitmap_based_on_vertices(dimensions, cells);
841
+ }
842
+ }
843
+
844
+ template <typename T>
845
+ Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const char* perseus_style_file) {
846
+ this->read_perseus_style_file(perseus_style_file);
847
+ }
848
+
849
+ template <typename T>
850
+ std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_boundary_of_a_cell(std::size_t cell) const {
851
+ std::vector<std::size_t> boundary_elements;
852
+
853
+ // Speed traded of for memory. Check if it is better in practice.
854
+ boundary_elements.reserve(this->dimension() * 2);
855
+
856
+ std::size_t sum_of_dimensions = 0;
857
+ std::size_t cell1 = cell;
858
+ for (std::size_t i = this->multipliers.size(); i > 1; --i) {
859
+ unsigned position = cell1 / this->multipliers[i - 1];
860
+ cell1 = cell1 % this->multipliers[i - 1];
861
+ if (position % 2 == 1) {
862
+ if (sum_of_dimensions % 2) {
863
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
864
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
865
+ } else {
866
+ boundary_elements.push_back(cell - this->multipliers[i - 1]);
867
+ boundary_elements.push_back(cell + this->multipliers[i - 1]);
868
+ }
869
+ ++sum_of_dimensions;
870
+ }
871
+ }
872
+ // Split out the last iteration to save a costly division by multipliers[0]=1
873
+ if (cell1 % 2 == 1) {
874
+ if (sum_of_dimensions % 2) {
875
+ boundary_elements.push_back(cell + 1);
876
+ boundary_elements.push_back(cell - 1);
877
+ } else {
878
+ boundary_elements.push_back(cell - 1);
879
+ boundary_elements.push_back(cell + 1);
880
+ }
881
+ ++sum_of_dimensions;
882
+ }
883
+
884
+ return boundary_elements;
885
+ }
886
+
887
+ template <typename T>
888
+ std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_coboundary_of_a_cell(std::size_t cell) const {
889
+ std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
890
+ std::vector<std::size_t> coboundary_elements;
891
+ std::size_t cell1 = cell;
892
+ for (std::size_t i = this->multipliers.size(); i > 1; --i) {
893
+ // It is a bit sad to recompute those divisions when we just did them in compute_counter_for_given_cell.
894
+ unsigned position = cell1 / this->multipliers[i - 1];
895
+ cell1 = cell1 % this->multipliers[i - 1];
896
+ if (position % 2 == 0) {
897
+ if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) {
898
+ coboundary_elements.push_back(cell - this->multipliers[i - 1]);
899
+ }
900
+ if ((cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) {
901
+ coboundary_elements.push_back(cell + this->multipliers[i - 1]);
902
+ }
903
+ }
904
+ }
905
+ if (cell1 % 2 == 0) {
906
+ if ((cell > 1) && (counter[0] != 0)) {
907
+ coboundary_elements.push_back(cell - 1);
908
+ }
909
+ if ((cell + 1 < this->data.size()) && (counter[0] != 2 * this->sizes[0])) {
910
+ coboundary_elements.push_back(cell + 1);
911
+ }
912
+ }
913
+ return coboundary_elements;
914
+ }
915
+
916
+ template <typename T>
917
+ unsigned Bitmap_cubical_complex_base<T>::get_dimension_of_a_cell(std::size_t cell) const {
918
+ #ifdef DEBUG_TRACES
919
+ std::clog << "\n\n\n Computing position o a cell of an index : " << cell << std::endl;
920
+ #endif
921
+ unsigned dimension = 0;
922
+ for (std::size_t i = this->multipliers.size(); i > 1; --i) {
923
+ unsigned position = cell / this->multipliers[i - 1];
924
+ std::size_t newcell = cell % this->multipliers[i - 1];
925
+
926
+ #ifdef DEBUG_TRACES
927
+ std::clog << "i-1 :" << i - 1 << std::endl;
928
+ std::clog << "cell : " << cell << std::endl;
929
+ std::clog << "position : " << position << std::endl;
930
+ std::clog << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl;
931
+ #endif
932
+
933
+ if (position % 2 == 1) {
934
+ #ifdef DEBUG_TRACES
935
+ std::clog << "Nonzero length in this direction \n";
936
+ #endif
937
+ dimension++;
938
+ }
939
+ cell = newcell;
940
+ }
941
+ // Split out the last iteration to save a costly division by multipliers[0]=1
942
+ #ifdef DEBUG_TRACES
943
+ std::clog << "i-1 :" << 0 << std::endl;
944
+ std::clog << "cell : " << cell << std::endl;
945
+ std::clog << "position : " << cell << std::endl;
946
+ std::clog << "multipliers[" << 0 << "] = " << 1 << std::endl;
947
+ #endif
948
+
949
+ if (cell % 2 == 1) {
950
+ #ifdef DEBUG_TRACES
951
+ std::clog << "Nonzero length in this direction \n";
952
+ #endif
953
+ dimension++;
954
+ }
955
+
956
+ return dimension;
957
+ }
958
+
959
+ template <typename T>
960
+ inline T& Bitmap_cubical_complex_base<T>::get_cell_data(std::size_t cell) {
961
+ return this->data[cell];
962
+ }
963
+
964
+ template <typename T>
965
+ void Bitmap_cubical_complex_base<T>::impose_lower_star_filtration() {
966
+ // this vector will be used to check which elements have already been taken care of in imposing lower star filtration
967
+ std::vector<bool> is_this_cell_considered(this->data.size(), false);
968
+
969
+ std::vector<std::size_t> indices_to_consider;
970
+ // we assume here that we already have a filtration on the top dimensional cells and
971
+ // we have to extend it to lower ones.
972
+ for (auto it = this->top_dimensional_cells_iterator_begin();
973
+ it != this->top_dimensional_cells_iterator_end(); ++it) {
974
+ indices_to_consider.push_back(it.compute_index_in_bitmap());
975
+ }
976
+
977
+ while (indices_to_consider.size()) {
978
+ #ifdef DEBUG_TRACES
979
+ std::clog << "indices_to_consider in this iteration \n";
980
+ for (auto index : indices_to_consider) {
981
+ std::clog << index << " ";
982
+ }
983
+ #endif
984
+ std::vector<std::size_t> new_indices_to_consider;
985
+ for (auto index : indices_to_consider) {
986
+ std::vector<std::size_t> bd = this->get_boundary_of_a_cell(index);
987
+ for (auto boundary : bd) {
988
+ #ifdef DEBUG_TRACES
989
+ std::clog << "filtration of a cell : " << boundary << " is : " << this->data[boundary]
990
+ << " while of a cell: " << index << " is: " << this->data[index]
991
+ << std::endl;
992
+ #endif
993
+ if (this->data[boundary] > this->data[index]) {
994
+ this->data[boundary] = this->data[index];
995
+ #ifdef DEBUG_TRACES
996
+ std::clog << "Setting the value of a cell : " << boundary
997
+ << " to : " << this->data[index] << std::endl;
998
+ #endif
999
+ }
1000
+ if (is_this_cell_considered[boundary] == false) {
1001
+ new_indices_to_consider.push_back(boundary);
1002
+ is_this_cell_considered[boundary] = true;
1003
+ }
1004
+ }
1005
+ }
1006
+ indices_to_consider.swap(new_indices_to_consider);
1007
+ }
1008
+ }
1009
+
1010
+ template <typename T>
1011
+ template <class F>
1012
+ void Bitmap_cubical_complex_base<T>::for_each_vertex_rec(F&&f, std::size_t base, int dim) {
1013
+ if (dim > 0)
1014
+ for(std::size_t i = 0; i < sizes[dim] + 1; ++i)
1015
+ for_each_vertex_rec(f, base + multipliers[dim] * 2 * i, dim - 1);
1016
+ else
1017
+ for(std::size_t i = 0; i < sizes[0] + 1; ++i)
1018
+ f(base + 2 * i);
1019
+ }
1020
+
1021
+ template <typename T>
1022
+ void Bitmap_cubical_complex_base<T>::impose_lower_star_filtration_from_vertices() {
1023
+ int max_dim = multipliers.size()-1;
1024
+ for (int dim = max_dim; dim >= 0; --dim)
1025
+ propagate_from_vertices_rec(dim, max_dim, 0);
1026
+ }
1027
+
1028
+ template <typename T>
1029
+ void Bitmap_cubical_complex_base<T>::propagate_from_vertices_rec (int special_dim, int current_dim, std::size_t base) {
1030
+ if (special_dim == current_dim) {
1031
+ propagate_from_vertices_rec(special_dim, current_dim - 1, base);
1032
+ return;
1033
+ }
1034
+ if (current_dim < 0) {
1035
+ std::size_t step = multipliers[special_dim];
1036
+ for(std::size_t i = 0; i < sizes[special_dim]; ++i) {
1037
+ std::size_t ref = base + step * 2 * i;
1038
+ data[ref + step] = std::max(data[ref], data[ref + 2 * step]);
1039
+ }
1040
+ return;
1041
+ }
1042
+ if (current_dim < special_dim)
1043
+ for(std::size_t i = 0; i < sizes[current_dim] + 1; ++i)
1044
+ propagate_from_vertices_rec(special_dim, current_dim - 1, base + multipliers[current_dim] * 2 * i);
1045
+ else
1046
+ for(std::size_t i = 0; i < 2 * sizes[current_dim] + 1; ++i)
1047
+ propagate_from_vertices_rec(special_dim, current_dim - 1, base + multipliers[current_dim] * i);
1048
+ }
1049
+
1050
+ template <typename T>
1051
+ bool compareFirstElementsOfTuples(const std::pair<std::pair<T, std::size_t>, char>& first,
1052
+ const std::pair<std::pair<T, std::size_t>, char>& second) {
1053
+ if (first.first.first < second.first.first) {
1054
+ return true;
1055
+ } else {
1056
+ if (first.first.first > second.first.first) {
1057
+ return false;
1058
+ }
1059
+ // in this case first.first.first == second.first.first, so we need to compare dimensions
1060
+ return first.second < second.second;
1061
+ }
1062
+ }
1063
+
1064
+ } // namespace cubical_complex
1065
+
1066
+ namespace Cubical_complex = cubical_complex;
1067
+
1068
+ } // namespace Gudhi
1069
+
1070
+ #endif // BITMAP_CUBICAL_COMPLEX_BASE_H_