From cea821f9ca34c270a5ccc047342c2c21ae79a6c0 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 28 Aug 2020 17:42:12 +0200 Subject: A prototype to fix #364 --- src/python/gudhi/simplex_tree.pxd | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/python/gudhi/simplex_tree.pxd') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 75e94e0b..44533d7f 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -66,6 +66,9 @@ 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 + # + ctypedef bool (*blocker_func)(vector[int], void *user_data) + void expansion_with_blockers_callback(int dimension, blocker_func user_func, void *user_data) cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": -- cgit v1.2.3 From c2eb0484191f89fcbe40bc4ab04943eb808f12a9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 1 Sep 2020 14:51:25 +0200 Subject: expansion with blocker and how to modify filtration value --- src/python/gudhi/simplex_tree.pxd | 2 +- src/python/gudhi/simplex_tree.pyx | 23 +++++++++--------- src/python/test/test_simplex_tree.py | 46 +++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 31 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pxd') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 44533d7f..80c6ffca 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -66,7 +66,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 - # + # Expansion with blockers ctypedef bool (*blocker_func)(vector[int], void *user_data) void expansion_with_blockers_callback(int dimension, blocker_func user_func, void *user_data) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index e297cfbd..debe92c0 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -413,21 +413,22 @@ cdef class SimplexTree: return self.get_ptr().compute_extended_persistence_subdiagrams(persistence_result, min_persistence) def expansion_with_blocker(self, max_dim, blocker_func): - """Expands the Simplex_tree containing only its one skeleton - until dimension max_dim. + """Expands the Simplex_tree containing only a graph. Simplices corresponding to cliques in the graph are added + incrementally, faces before cofaces, unless the simplex has dimension larger than `max_dim` or `blocker_func` + returns `True` for this simplex. - The expanded simplicial complex until dimension :math:`d` - attached to a graph :math:`G` is the maximal simplicial complex of - dimension at most :math:`d` admitting the graph :math:`G` as - :math:`1`-skeleton. - The filtration value assigned to a simplex is the maximal filtration - value of one of its edges. + The function identifies a candidate simplex whose faces are all already in the complex, inserts it with a + filtration value corresponding to the maximum of the filtration values of the faces, then calls `blocker_func` + with this new simplex (represented as a list of int). If `blocker_func` returns `True`, the simplex is removed, + otherwise it is kept. The algorithm then proceeds with the next candidate. - The Simplex_tree must contain no simplex of dimension bigger than - 1 when calling the method. + Note that you cannot update the filtration value of the simplex during the evaluation of `blocker_func`, as it + would segfault. - :param max_dim: The maximal dimension. + :param max_dim: Expansion maximal dimension value. :type max_dim: int + :param blocker_func: Blocker oracle. + :type blocker_func: Its concept is `Boolean blocker_func(list of int)` """ self.get_ptr().expansion_with_blockers_callback(max_dim, callback, blocker_func) diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 7aad8259..33b0ac99 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -359,16 +359,6 @@ def test_collapse_edges(): for simplex in st.get_skeleton(0): assert simplex[1] == 1. -def blocker(simplex): - try: - # Block all simplices that countains vertex 6 - simplex.index(6) - print(simplex, ' is blocked') - return True - except ValueError: - print(simplex, ' is accepted') - return False - def test_expansion_with_blocker(): st=SimplexTree() st.insert([0,1],0) @@ -384,21 +374,39 @@ def test_expansion_with_blocker(): st.insert([5,6],10) st.insert([6],10) + # One cannot modify filtration inside blocker - segfault - Let's record accepted simplices + accepted_simp = [] + def blocker(simplex): + try: + # Block all simplices that countains vertex 6 + simplex.index(6) + print(simplex, ' is blocked') + return True + except ValueError: + print(simplex, ' is accepted') + accepted_simp.append(simplex) + return False + st.expansion_with_blocker(2, blocker) + for simplex in accepted_simp: + st.assign_filtration(simplex, st.filtration(simplex) + 1.) assert st.num_simplices() == 22 assert st.dimension() == 2 assert st.find([4,5,6]) == False - assert st.filtration([0,1,2]) == 3. - assert st.filtration([0,1,3]) == 4. - assert st.filtration([0,2,3]) == 5. - assert st.filtration([1,2,3]) == 5. + assert st.filtration([0,1,2]) == 4. + assert st.filtration([0,1,3]) == 5. + assert st.filtration([0,2,3]) == 6. + assert st.filtration([1,2,3]) == 6. + accepted_simp = [] st.expansion_with_blocker(3, blocker) + for simplex in accepted_simp: + st.assign_filtration(simplex, st.filtration(simplex) + 1.) assert st.num_simplices() == 23 assert st.dimension() == 3 assert st.find([4,5,6]) == False - assert st.filtration([0,1,2]) == 3. - assert st.filtration([0,1,3]) == 4. - assert st.filtration([0,2,3]) == 5. - assert st.filtration([1,2,3]) == 5. - assert st.filtration([0,1,2,3]) == 5. + assert st.filtration([0,1,2]) == 4. + assert st.filtration([0,1,3]) == 5. + assert st.filtration([0,2,3]) == 6. + assert st.filtration([1,2,3]) == 6. + assert st.filtration([0,1,2,3]) == 6. -- cgit v1.2.3 From f4f5992e9025d055e35c86589923f1b0299f552e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 22 Apr 2021 08:39:03 +0200 Subject: code review: rename block_func when it is a type. Type is a 'callable' --- src/python/gudhi/simplex_tree.pxd | 4 ++-- src/python/gudhi/simplex_tree.pyx | 2 +- src/python/include/Simplex_tree_interface.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pxd') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 80c6ffca..ff750af9 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -67,8 +67,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) nogil Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) nogil # Expansion with blockers - ctypedef bool (*blocker_func)(vector[int], void *user_data) - void expansion_with_blockers_callback(int dimension, blocker_func user_func, void *user_data) + ctypedef bool (*blocker_func_t)(vector[int], void *user_data) + void expansion_with_blockers_callback(int dimension, blocker_func_t user_func, void *user_data) cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface>": diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index debe92c0..383d1949 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -428,7 +428,7 @@ cdef class SimplexTree: :param max_dim: Expansion maximal dimension value. :type max_dim: int :param blocker_func: Blocker oracle. - :type blocker_func: Its concept is `Boolean blocker_func(list of int)` + :type blocker_func: Callable[[List[int]], bool] """ self.get_ptr().expansion_with_blockers_callback(max_dim, callback, blocker_func) diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 9f92b349..a859bec0 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -39,7 +39,7 @@ class Simplex_tree_interface : public Simplex_tree { 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; - typedef bool (*blocker_func)(Simplex simplex, void *user_data); + typedef bool (*blocker_func_t)(Simplex simplex, void *user_data); public: @@ -189,7 +189,7 @@ class Simplex_tree_interface : public Simplex_tree { return collapsed_stree_ptr; } - void expansion_with_blockers_callback(int dimension, blocker_func user_func, void *user_data) { + void expansion_with_blockers_callback(int dimension, blocker_func_t user_func, void *user_data) { Base::expansion_with_blockers(dimension, [&](Simplex_handle sh){ Simplex simplex; for (auto vertex : Base::simplex_vertex_range(sh)) { -- cgit v1.2.3