From 436a7fbe36a9de6a969afd5978c3d496773a8690 Mon Sep 17 00:00:00 2001 From: mathieu Date: Thu, 16 Jan 2020 15:46:41 -0500 Subject: added wrapper functions --- src/python/gudhi/cubical_complex.pyx | 29 ++++++++- src/python/gudhi/simplex_tree.pxd | 1 + src/python/gudhi/simplex_tree.pyx | 28 +++++++- .../include/Persistent_cohomology_interface.h | 76 ++++++++++++++++++++++ 4 files changed, 132 insertions(+), 2 deletions(-) (limited to 'src/python') diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index cbeda014..5562e8a7 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -31,6 +31,7 @@ cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface>": Cubical_complex_persistence_interface(Bitmap_cubical_complex_base_interface * st, bool persistence_dim_max) vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[pair[int, pair[pair[double, int], pair[double, int]]]] get_persistence_cubical_generators(int homology_coeff_field, double min_persistence) vector[int] betti_numbers() vector[int] persistent_betti_numbers(double from_value, double to_value) vector[pair[double,double]] intervals_in_dimension(int dimension) @@ -85,7 +86,7 @@ cdef class CubicalComplex: elif ((dimensions is None) and (top_dimensional_cells is None) and (perseus_file != '')): if os.path.isfile(perseus_file): - self.thisptr = new Bitmap_cubical_complex_base_interface(perseus_file.encode('utf-8')) + self.thisptr = new Bitmap_cubical_complex_base_interface(str.encode(perseus_file)) else: print("file " + perseus_file + " not found.") else: @@ -145,6 +146,32 @@ cdef class CubicalComplex: persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) return persistence_result + def persistence_generators(self, homology_coeff_field=11, min_persistence=0, persistence_dim_max = False): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number. Default value is 11. + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :param persistence_dim_max: If true, the persistent homology for the + maximal dimension in the complex is computed. If false, it is + ignored. Default is false. + :type persistence_dim_max: bool + :returns: The persistence of the simplicial complex, together with the corresponding generators, i.e., the positive and negative top-dimensional cells. + :rtype: list of pairs(dimension, pair(index of positive top-dimensional cell, index of negative top-dimensional cell)) + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Cubical_complex_persistence_interface(self.thisptr, True) + cdef vector[pair[int, pair[pair[double, int], pair[double, int]]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence_cubical_generators(homology_coeff_field, min_persistence) + return persistence_result + def betti_numbers(self): """This function returns the Betti numbers of the complex. diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 1066d44b..9e52a8aa 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -48,6 +48,7 @@ cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": Simplex_tree_persistence_interface(Simplex_tree_interface_full_featured * st, bool persistence_dim_max) vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[pair[int, pair[pair[double, vector[int]], pair[double, vector[int]]]]] get_persistence_generators(int homology_coeff_field, double min_persistence) vector[int] betti_numbers() vector[int] persistent_betti_numbers(double from_value, double to_value) vector[pair[double,double]] intervals_in_dimension(int dimension) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index b18627c4..8cc58f8f 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -412,6 +412,32 @@ cdef class SimplexTree: persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) return persistence_result + def persistence_generators(self, homology_coeff_field=11, min_persistence=0, persistence_dim_max = False): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number. Default value is 11. + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :param persistence_dim_max: If true, the persistent homology for the + maximal dimension in the complex is computed. If false, it is + ignored. Default is false. + :type persistence_dim_max: bool + :returns: The persistence of the simplicial complex, together with the corresponding generators, i.e., the positive and negative simplices. + :rtype: list of pairs(dimension, pair(positive_simplex, negative_simplex)) + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Simplex_tree_persistence_interface(self.get_ptr(), persistence_dim_max) + cdef vector[pair[int, pair[pair[double, vector[int]], pair[double, vector[int]]]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence_generators(homology_coeff_field, min_persistence) + return persistence_result + def betti_numbers(self): """This function returns the Betti numbers of the simplicial complex. @@ -508,7 +534,7 @@ cdef class SimplexTree: """ if self.pcohptr != NULL: if persistence_file != '': - self.pcohptr.write_output_diagram(persistence_file.encode('utf-8')) + self.pcohptr.write_output_diagram(str.encode(persistence_file)) else: print("persistence_file must be specified") else: diff --git a/src/python/include/Persistent_cohomology_interface.h b/src/python/include/Persistent_cohomology_interface.h index 8c79e6f3..774eb56a 100644 --- a/src/python/include/Persistent_cohomology_interface.h +++ b/src/python/include/Persistent_cohomology_interface.h @@ -73,6 +73,82 @@ persistent_cohomology::Persistent_cohomology>, std::pair>>>> get_persistence_generators(int homology_coeff_field, + double min_persistence) { + persistent_cohomology::Persistent_cohomology::init_coefficients(homology_coeff_field); + persistent_cohomology::Persistent_cohomology::compute_persistent_cohomology(min_persistence); + + // Custom sort and output persistence + cmp_intervals_by_dim_then_length cmp(stptr_); + auto persistent_pairs = persistent_cohomology::Persistent_cohomology::get_persistent_pairs(); + std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); + + std::vector>, std::pair>>>> persistence; + for (auto pair : persistent_pairs) { + std::vector splx0, splx1; + for (auto vertex : stptr_->simplex_vertex_range(get<0>(pair))){splx0.push_back(vertex);} + if (isfinite(stptr_->filtration(get<1>(pair)))){ for (auto vertex : stptr_->simplex_vertex_range(get<1>(pair))){splx1.push_back(vertex);}} + persistence.push_back(std::make_pair(stptr_->dimension(get<0>(pair)), std::make_pair(std::make_pair(stptr_->filtration(get<0>(pair)), splx0), std::make_pair(stptr_->filtration(get<1>(pair)), splx1)))); + } + return persistence; + } + + void top_dimensional_cofaces(std::vector & cofaces, int splx){ + if (stptr_->dimension(stptr_->simplex(splx)) == stptr_->dimension()){cofaces.push_back(stptr_->simplex(splx));} + else{ for (auto v : stptr_->coboundary_simplex_range(stptr_->simplex(splx))){top_dimensional_cofaces(cofaces, stptr_->key(v));} } + } + + std::vector, std::pair>>> get_persistence_cubical_generators(int homology_coeff_field, + double min_persistence) { + + // Gather all top-dimensional cells and store their simplex handles + std::vector max_splx; for (auto splx : stptr_->filtration_simplex_range()){ if (stptr_->dimension(splx) == stptr_->dimension()) max_splx.push_back(splx); } + // Sort these simplex handles and compute the ordering function + // This function allows to go directly from the simplex handle to the position of the corresponding top-dimensional cell in the input data + std::map order; std::sort(max_splx.begin(), max_splx.end()); for (int i = 0; i < max_splx.size(); i++) order.insert(std::make_pair(max_splx[i], i)); + + persistent_cohomology::Persistent_cohomology::init_coefficients(homology_coeff_field); + persistent_cohomology::Persistent_cohomology::compute_persistent_cohomology(min_persistence); + + // Custom sort and output persistence + cmp_intervals_by_dim_then_length cmp(stptr_); + auto persistent_pairs = persistent_cohomology::Persistent_cohomology::get_persistent_pairs(); + std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); + + std::vector, std::pair>>> persistence; + for (auto pair : persistent_pairs) { + + int splx0, splx1; + + double f0 = stptr_->filtration(get<0>(pair)); + // Recursively get the top-dimensional cells / cofaces associated to the persistence generator + std::vector faces0; top_dimensional_cofaces(faces0, stptr_->key(get<0>(pair))); + // Find the top-dimensional cell / coface with the same filtration value + int cf; for (int i = 0; i < faces0.size(); i++){ if (stptr_->filtration(faces0[i]) == f0){cf = i; break;}} + // Retrieve the index of the corresponding top-dimensional cell in the input data + splx0 = order[faces0[cf]]; + + if (isfinite(stptr_->filtration(get<1>(pair)))){ + double f1 = stptr_->filtration(get<1>(pair)); + // Recursively get the top-dimensional cells / cofaces associated to the persistence generator + std::vector faces1; top_dimensional_cofaces(faces1, stptr_->key(get<1>(pair))); + // Find the top-dimensional cell / coface with the same filtration value + int cf; for (int i = 0; i < faces0.size(); i++){ if (stptr_->filtration(faces0[i]) == f0){cf = i; break;}} + // Retrieve the index of the corresponding top-dimensional cell in the input data + splx1 = order[faces1[cf]]; + } + + persistence.push_back(std::make_pair(stptr_->dimension(get<0>(pair)), std::make_pair(std::make_pair(stptr_->filtration(get<0>(pair)), splx0), std::make_pair(stptr_->filtration(get<1>(pair)), splx1)))); + } + return persistence; + } + std::vector, std::vector>> persistence_pairs() { auto pairs = persistent_cohomology::Persistent_cohomology::get_persistent_pairs(); -- cgit v1.2.3