multipers 2.3.3b6__cp313-cp313-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- multipers/.dylibs/libc++.1.0.dylib +0 -0
- multipers/.dylibs/libtbb.12.16.dylib +0 -0
- multipers/__init__.py +33 -0
- multipers/_signed_measure_meta.py +453 -0
- multipers/_slicer_meta.py +211 -0
- multipers/array_api/__init__.py +45 -0
- multipers/array_api/numpy.py +41 -0
- multipers/array_api/torch.py +58 -0
- multipers/data/MOL2.py +458 -0
- multipers/data/UCR.py +18 -0
- multipers/data/__init__.py +1 -0
- multipers/data/graphs.py +466 -0
- multipers/data/immuno_regions.py +27 -0
- multipers/data/minimal_presentation_to_st_bf.py +0 -0
- multipers/data/pytorch2simplextree.py +91 -0
- multipers/data/shape3d.py +101 -0
- multipers/data/synthetic.py +113 -0
- multipers/distances.py +202 -0
- multipers/filtration_conversions.pxd +229 -0
- multipers/filtration_conversions.pxd.tp +84 -0
- multipers/filtrations/__init__.py +18 -0
- multipers/filtrations/density.py +574 -0
- multipers/filtrations/filtrations.py +361 -0
- multipers/filtrations.pxd +224 -0
- multipers/function_rips.cpython-313-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-313-darwin.so +0 -0
- multipers/grids.pyx +433 -0
- multipers/gudhi/Persistence_slices_interface.h +132 -0
- multipers/gudhi/Simplex_tree_interface.h +239 -0
- multipers/gudhi/Simplex_tree_multi_interface.h +551 -0
- multipers/gudhi/cubical_to_boundary.h +59 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
- multipers/gudhi/gudhi/Debug_utils.h +45 -0
- multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
- multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
- multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
- multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
- multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
- multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
- multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
- multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
- multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
- multipers/gudhi/gudhi/Matrix.h +2107 -0
- multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
- multipers/gudhi/gudhi/Multi_persistence/Box.h +174 -0
- multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
- multipers/gudhi/gudhi/Off_reader.h +173 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +1441 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
- multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
- multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
- multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
- multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
- multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
- multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
- multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
- multipers/gudhi/gudhi/Points_off_io.h +171 -0
- multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
- multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
- multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
- multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
- multipers/gudhi/gudhi/Simplex_tree_multi.h +152 -0
- multipers/gudhi/gudhi/distance_functions.h +62 -0
- multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
- multipers/gudhi/gudhi/persistence_interval.h +253 -0
- multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
- multipers/gudhi/gudhi/reader_utils.h +367 -0
- multipers/gudhi/mma_interface_coh.h +256 -0
- multipers/gudhi/mma_interface_h0.h +223 -0
- multipers/gudhi/mma_interface_matrix.h +293 -0
- multipers/gudhi/naive_merge_tree.h +536 -0
- multipers/gudhi/scc_io.h +310 -0
- multipers/gudhi/truc.h +1403 -0
- multipers/io.cpython-313-darwin.so +0 -0
- multipers/io.pyx +644 -0
- multipers/ml/__init__.py +0 -0
- multipers/ml/accuracies.py +90 -0
- multipers/ml/invariants_with_persistable.py +79 -0
- multipers/ml/kernels.py +176 -0
- multipers/ml/mma.py +713 -0
- multipers/ml/one.py +472 -0
- multipers/ml/point_clouds.py +352 -0
- multipers/ml/signed_measures.py +1589 -0
- multipers/ml/sliced_wasserstein.py +461 -0
- multipers/ml/tools.py +113 -0
- multipers/mma_structures.cpython-313-darwin.so +0 -0
- multipers/mma_structures.pxd +128 -0
- multipers/mma_structures.pyx +2786 -0
- multipers/mma_structures.pyx.tp +1094 -0
- multipers/multi_parameter_rank_invariant/diff_helpers.h +84 -0
- multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
- multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
- multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
- multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
- multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
- multipers/multiparameter_edge_collapse.py +41 -0
- multipers/multiparameter_module_approximation/approximation.h +2330 -0
- multipers/multiparameter_module_approximation/combinatory.h +129 -0
- multipers/multiparameter_module_approximation/debug.h +107 -0
- multipers/multiparameter_module_approximation/euler_curves.h +0 -0
- multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
- multipers/multiparameter_module_approximation/heap_column.h +238 -0
- multipers/multiparameter_module_approximation/images.h +79 -0
- multipers/multiparameter_module_approximation/list_column.h +174 -0
- multipers/multiparameter_module_approximation/list_column_2.h +232 -0
- multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
- multipers/multiparameter_module_approximation/set_column.h +135 -0
- multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
- multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
- multipers/multiparameter_module_approximation/utilities.h +403 -0
- multipers/multiparameter_module_approximation/vector_column.h +223 -0
- multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
- multipers/multiparameter_module_approximation/vineyards.h +464 -0
- multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
- multipers/multiparameter_module_approximation.cpython-313-darwin.so +0 -0
- multipers/multiparameter_module_approximation.pyx +235 -0
- multipers/pickle.py +90 -0
- multipers/plots.py +456 -0
- multipers/point_measure.cpython-313-darwin.so +0 -0
- multipers/point_measure.pyx +395 -0
- multipers/simplex_tree_multi.cpython-313-darwin.so +0 -0
- multipers/simplex_tree_multi.pxd +134 -0
- multipers/simplex_tree_multi.pyx +10840 -0
- multipers/simplex_tree_multi.pyx.tp +2009 -0
- multipers/slicer.cpython-313-darwin.so +0 -0
- multipers/slicer.pxd +3034 -0
- multipers/slicer.pxd.tp +234 -0
- multipers/slicer.pyx +20481 -0
- multipers/slicer.pyx.tp +1088 -0
- multipers/tensor/tensor.h +672 -0
- multipers/tensor.pxd +13 -0
- multipers/test.pyx +44 -0
- multipers/tests/__init__.py +62 -0
- multipers/torch/__init__.py +1 -0
- multipers/torch/diff_grids.py +240 -0
- multipers/torch/rips_density.py +310 -0
- multipers-2.3.3b6.dist-info/METADATA +128 -0
- multipers-2.3.3b6.dist-info/RECORD +183 -0
- multipers-2.3.3b6.dist-info/WHEEL +6 -0
- multipers-2.3.3b6.dist-info/licenses/LICENSE +21 -0
- multipers-2.3.3b6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,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_
|