diff options
author | Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> | 2020-11-02 11:21:23 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-02 11:21:23 +0100 |
commit | 5900b2d802a7387f7fd4a87b5251dcbe6931371c (patch) | |
tree | 44fde353aa1e7c41e680c153182af0933b489487 | |
parent | 6b995c03793096459a333c907b606770113b96d7 (diff) | |
parent | af5af2df409576035f2e31564f4048278d4f0f19 (diff) |
Merge pull request #362 from VincentRouvreau/python_stree_boundaries
A fix proposal for boudaries of a simplex python version
-rw-r--r-- | src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h | 6 | ||||
-rw-r--r-- | src/python/gudhi/simplex_tree.pxd | 7 | ||||
-rw-r--r-- | src/python/gudhi/simplex_tree.pyx | 14 | ||||
-rw-r--r-- | src/python/include/Simplex_tree_interface.h | 10 | ||||
-rwxr-xr-x | src/python/test/test_simplex_tree.py | 19 |
5 files changed, 56 insertions, 0 deletions
diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h index 9007b6bd..ee64a277 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree/Simplex_tree_iterators.h @@ -85,6 +85,12 @@ class Simplex_tree_boundary_simplex_iterator : public boost::iterator_facade< typedef typename SimplexTree::Vertex_handle Vertex_handle; typedef typename SimplexTree::Siblings Siblings; + // For cython purpose only. The object it initializes should be overwritten ASAP and never used before it is overwritten. + Simplex_tree_boundary_simplex_iterator() + : sib_(nullptr), + st_(nullptr) { + } + // any end() iterator explicit Simplex_tree_boundary_simplex_iterator(SimplexTree * st) : last_(st->null_vertex()), diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 3b494ba3..3c4cbed3 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -36,6 +36,12 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator operator++() nogil bint operator!=(Simplex_tree_skeleton_iterator) nogil + cdef cppclass Simplex_tree_boundary_iterator "Gudhi::Simplex_tree_interface<Gudhi::Simplex_tree_options_full_featured>::Boundary_simplex_iterator": + Simplex_tree_boundary_iterator() nogil + Simplex_tree_simplex_handle& operator*() nogil + Simplex_tree_boundary_iterator operator++() nogil + bint operator!=(Simplex_tree_boundary_iterator) nogil + cdef cppclass Simplex_tree_interface_full_featured "Gudhi::Simplex_tree_interface<Gudhi::Simplex_tree_options_full_featured>": Simplex_tree() nogil @@ -67,6 +73,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil + pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] get_boundary_iterators(vector[int] simplex) nogil except + cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 910711a9..c671da56 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -285,6 +285,20 @@ cdef class SimplexTree: ct.append((v, filtered_simplex.second)) return ct + def get_boundaries(self, simplex): + """This function returns a generator with the boundaries of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The (simplices of the) boundary of a simplex + :rtype: generator with tuples(simplex, filtration) + """ + cdef pair[Simplex_tree_boundary_iterator, Simplex_tree_boundary_iterator] it = self.get_ptr().get_boundary_iterators(simplex) + + while it.first != it.second: + yield self.get_ptr().get_simplex_and_filtration(dereference(it.first)) + preincrement(it.first) + def remove_maximal_simplex(self, simplex): """This function removes a given maximal N-simplex from the simplicial complex. diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index e288a8cf..baff3850 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -39,6 +39,7 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> { using Skeleton_simplex_iterator = typename Base::Skeleton_simplex_iterator; using Complex_simplex_iterator = typename Base::Complex_simplex_iterator; using Extended_filtration_data = typename Base::Extended_filtration_data; + using Boundary_simplex_iterator = typename Base::Boundary_simplex_iterator; public: @@ -219,6 +220,15 @@ class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> { // this specific case works because the range is just a pair of iterators - won't work if range was a vector return Base::skeleton_simplex_range(dimension).end(); } + + std::pair<Boundary_simplex_iterator, Boundary_simplex_iterator> get_boundary_iterators(const Simplex& simplex) { + auto bd_sh = Base::find(simplex); + if (bd_sh == Base::null_simplex()) + throw std::runtime_error("simplex not found - cannot find boundaries"); + // this specific case works because the range is just a pair of iterators - won't work if range was a vector + auto boundary_srange = Base::boundary_simplex_range(bd_sh); + return std::make_pair(boundary_srange.begin(), boundary_srange.end()); + } }; } // namespace Gudhi diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index ac2b59c7..3b23fa0b 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -380,3 +380,22 @@ def test_reset_filtration(): assert st.filtration(simplex[0]) >= 2. else: assert st.filtration(simplex[0]) == 0. + +def test_boundaries_iterator(): + st = SimplexTree() + + assert st.insert([0, 1, 2, 3], filtration=1.0) == True + assert st.insert([1, 2, 3, 4], filtration=2.0) == True + + assert list(st.get_boundaries([1, 2, 3])) == [([1, 2], 1.0), ([1, 3], 1.0), ([2, 3], 1.0)] + assert list(st.get_boundaries([2, 3, 4])) == [([2, 3], 1.0), ([2, 4], 2.0), ([3, 4], 2.0)] + assert list(st.get_boundaries([2])) == [] + + with pytest.raises(RuntimeError): + list(st.get_boundaries([])) + + with pytest.raises(RuntimeError): + list(st.get_boundaries([0, 4])) # (0, 4) does not exist + + with pytest.raises(RuntimeError): + list(st.get_boundaries([6])) # (6) does not exist |