From a064f5698fedbe13f6c343cb0b82e0f4d72caffb Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 27 Jan 2020 17:37:31 +0100 Subject: A first naive iterator implementation with yield --- src/python/gudhi/simplex_tree.pyx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index b18627c4..478139de 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -7,6 +7,7 @@ # Modification(s): # - YYYY/MM Author: Description of the modification +from cython.operator import dereference, preincrement from libc.stdint cimport intptr_t from numpy import array as np_array cimport simplex_tree @@ -214,15 +215,14 @@ cdef class SimplexTree: :returns: The simplices sorted by increasing filtration values. :rtype: list of tuples(simplex, filtration) """ - cdef vector[pair[vector[int], double]] filtration \ - = self.get_ptr().get_filtration() - ct = [] - for filtered_complex in filtration: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v, filtered_complex.second)) - return ct + cdef vector[Simplex_tree_simplex_handle].const_iterator it = self.get_ptr().get_filtration_iterator_begin() + cdef vector[Simplex_tree_simplex_handle].const_iterator end = self.get_ptr().get_filtration_iterator_end() + + while True: + yield(self.get_ptr().get_simplex_filtration(dereference(it))) + preincrement(it) + if it == end: + raise StopIteration def get_skeleton(self, dimension): """This function returns the (simplices of the) skeleton of a maximum -- cgit v1.2.3 From ef2c5b53e88321f07ad93496f00dde16dc20f018 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 28 Jan 2020 11:05:39 +0100 Subject: Code review: rename get_simplex_filtration with get_simplex_and_filtration. Remove exception raise. Fix failed tests. Reword documentation --- .../example/alpha_complex_from_points_example.py | 5 +- .../example/rips_complex_from_points_example.py | 5 +- src/python/example/simplex_tree_example.py | 5 +- src/python/gudhi/simplex_tree.pxd | 2 +- src/python/gudhi/simplex_tree.pyx | 10 +-- src/python/include/Simplex_tree_interface.h | 6 +- src/python/test/test_alpha_complex.py | 50 ++++++------ src/python/test/test_euclidean_witness_complex.py | 46 ++++++----- src/python/test/test_rips_complex.py | 53 +++++++------ src/python/test/test_simplex_tree.py | 90 +++++++++++----------- src/python/test/test_tangential_complex.py | 19 +++-- 11 files changed, 161 insertions(+), 130 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/example/alpha_complex_from_points_example.py b/src/python/example/alpha_complex_from_points_example.py index 844d7a82..465632eb 100755 --- a/src/python/example/alpha_complex_from_points_example.py +++ b/src/python/example/alpha_complex_from_points_example.py @@ -47,7 +47,10 @@ else: print("[4] Not found...") print("dimension=", simplex_tree.dimension()) -print("filtrations=", simplex_tree.get_filtration()) +print("filtrations=") +for simplex_with_filtration in simplex_tree.get_filtration(): + print("(%s, %.2f)" % tuple(simplex_with_filtration)) + print("star([0])=", simplex_tree.get_star([0])) print("coface([0], 1)=", simplex_tree.get_cofaces([0], 1)) diff --git a/src/python/example/rips_complex_from_points_example.py b/src/python/example/rips_complex_from_points_example.py index 59d8a261..c05703c6 100755 --- a/src/python/example/rips_complex_from_points_example.py +++ b/src/python/example/rips_complex_from_points_example.py @@ -22,6 +22,9 @@ rips = gudhi.RipsComplex(points=[[0, 0], [1, 0], [0, 1], [1, 1]], max_edge_lengt simplex_tree = rips.create_simplex_tree(max_dimension=1) -print("filtrations=", simplex_tree.get_filtration()) +print("filtrations=") +for simplex_with_filtration in simplex_tree.get_filtration(): + print("(%s, %.2f)" % tuple(simplex_with_filtration)) + print("star([0])=", simplex_tree.get_star([0])) print("coface([0], 1)=", simplex_tree.get_cofaces([0], 1)) diff --git a/src/python/example/simplex_tree_example.py b/src/python/example/simplex_tree_example.py index 30de00da..7f20c389 100755 --- a/src/python/example/simplex_tree_example.py +++ b/src/python/example/simplex_tree_example.py @@ -39,7 +39,10 @@ else: print("dimension=", st.dimension()) st.initialize_filtration() -print("filtration=", st.get_filtration()) +print("filtration=") +for simplex_with_filtration in st.get_filtration(): + print("(%s, %.2f)" % tuple(simplex_with_filtration)) + print("filtration[1, 2]=", st.filtration([1, 2])) print("filtration[4, 2]=", st.filtration([4, 2])) diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index caf3c459..1b0dc881 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -46,7 +46,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool prune_above_filtration(double filtration) bool make_filtration_non_decreasing() # Iterators over Simplex tree - pair[vector[int], double] get_simplex_filtration(Simplex_tree_simplex_handle f_simplex) + pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_begin() vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 478139de..22978b6e 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -209,20 +209,18 @@ cdef class SimplexTree: filtration) def get_filtration(self): - """This function returns a list of all simplices with their given + """This function returns a generator with simplices and their given filtration values. :returns: The simplices sorted by increasing filtration values. - :rtype: list of tuples(simplex, filtration) + :rtype: generator with tuples(simplex, filtration) """ cdef vector[Simplex_tree_simplex_handle].const_iterator it = self.get_ptr().get_filtration_iterator_begin() cdef vector[Simplex_tree_simplex_handle].const_iterator end = self.get_ptr().get_filtration_iterator_end() - while True: - yield(self.get_ptr().get_simplex_filtration(dereference(it))) + while it != end: + yield(self.get_ptr().get_simplex_and_filtration(dereference(it))) preincrement(it) - if it == end: - raise StopIteration def get_skeleton(self, dimension): """This function returns the (simplices of the) skeleton of a maximum diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 843966cd..c0bbc3d9 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -33,8 +33,8 @@ class Simplex_tree_interface : public Simplex_tree { using Simplex_handle = typename Base::Simplex_handle; using Insertion_result = typename std::pair; using Simplex = std::vector; - using Filtered_simplex = std::pair; - using Filtered_simplices = std::vector; + using Simplex_and_filtration = std::pair; + using Filtered_simplices = std::vector; public: bool find_simplex(const Simplex& vh) { @@ -83,7 +83,7 @@ class Simplex_tree_interface : public Simplex_tree { Base::initialize_filtration(); } - Filtered_simplex get_simplex_filtration(Simplex_handle f_simplex) { + Simplex_and_filtration get_simplex_and_filtration(Simplex_handle f_simplex) { Simplex simplex; for (auto vertex : Base::simplex_vertex_range(f_simplex)) { simplex.insert(simplex.begin(), vertex); diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 3761fe16..ceead919 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -40,19 +40,21 @@ def test_infinite_alpha(): assert simplex_tree.num_simplices() == 11 assert simplex_tree.num_vertices() == 4 - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([3], 0.0), - ([0, 1], 0.25), - ([0, 2], 0.25), - ([1, 3], 0.25), - ([2, 3], 0.25), - ([1, 2], 0.5), - ([0, 1, 2], 0.5), - ([1, 2, 3], 0.5), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([3], 0.0)) + assert(next(filtration_generator) == ([0, 1], 0.25)) + assert(next(filtration_generator) == ([0, 2], 0.25)) + assert(next(filtration_generator) == ([1, 3], 0.25)) + assert(next(filtration_generator) == ([2, 3], 0.25)) + assert(next(filtration_generator) == ([1, 2], 0.5)) + assert(next(filtration_generator) == ([0, 1, 2], 0.5)) + assert(next(filtration_generator) == ([1, 2, 3], 0.5)) + with pytest.raises(StopIteration): + next(filtration_generator) + assert simplex_tree.get_star([0]) == [ ([0], 0.0), ([0, 1], 0.25), @@ -105,16 +107,18 @@ def test_filtered_alpha(): else: assert False - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([3], 0.0), - ([0, 1], 0.25), - ([0, 2], 0.25), - ([1, 3], 0.25), - ([2, 3], 0.25), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([3], 0.0)) + assert(next(filtration_generator) == ([0, 1], 0.25)) + assert(next(filtration_generator) == ([0, 2], 0.25)) + assert(next(filtration_generator) == ([1, 3], 0.25)) + assert(next(filtration_generator) == ([2, 3], 0.25)) + with pytest.raises(StopIteration): + next(filtration_generator) + assert simplex_tree.get_star([0]) == [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)] assert simplex_tree.get_cofaces([0], 1) == [([0, 1], 0.25), ([0, 2], 0.25)] diff --git a/src/python/test/test_euclidean_witness_complex.py b/src/python/test/test_euclidean_witness_complex.py index c18d2484..16ff1ef4 100755 --- a/src/python/test/test_euclidean_witness_complex.py +++ b/src/python/test/test_euclidean_witness_complex.py @@ -9,6 +9,7 @@ """ import gudhi +import pytest __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -40,15 +41,16 @@ def test_witness_complex(): assert landmarks[1] == euclidean_witness_complex.get_point(1) assert landmarks[2] == euclidean_witness_complex.get_point(2) - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([0, 1], 0.0), - ([2], 0.0), - ([0, 2], 0.0), - ([1, 2], 0.0), - ([0, 1, 2], 0.0), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([0, 1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([0, 2], 0.0)) + assert(next(filtration_generator) == ([1, 2], 0.0)) + assert(next(filtration_generator) == ([0, 1, 2], 0.0)) + with pytest.raises(StopIteration): + next(filtration_generator) def test_empty_euclidean_strong_witness_complex(): @@ -78,18 +80,24 @@ def test_strong_witness_complex(): assert landmarks[1] == euclidean_strong_witness_complex.get_point(1) assert landmarks[2] == euclidean_strong_witness_complex.get_point(2) - assert simplex_tree.get_filtration() == [([0], 0.0), ([1], 0.0), ([2], 0.0)] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + with pytest.raises(StopIteration): + next(filtration_generator) simplex_tree = euclidean_strong_witness_complex.create_simplex_tree( max_alpha_square=100.0 ) - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([1, 2], 15.0), - ([0, 2], 34.0), - ([0, 1], 37.0), - ([0, 1, 2], 37.0), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([1, 2], 15.0)) + assert(next(filtration_generator) == ([0, 2], 34.0)) + assert(next(filtration_generator) == ([0, 1], 37.0)) + assert(next(filtration_generator) == ([0, 1, 2], 37.0)) + with pytest.raises(StopIteration): + next(filtration_generator) diff --git a/src/python/test/test_rips_complex.py b/src/python/test/test_rips_complex.py index b02a68e1..bd31c47c 100755 --- a/src/python/test/test_rips_complex.py +++ b/src/python/test/test_rips_complex.py @@ -10,6 +10,7 @@ from gudhi import RipsComplex from math import sqrt +import pytest __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -32,18 +33,20 @@ def test_rips_from_points(): assert simplex_tree.num_simplices() == 10 assert simplex_tree.num_vertices() == 4 - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([3], 0.0), - ([0, 1], 1.0), - ([0, 2], 1.0), - ([1, 3], 1.0), - ([2, 3], 1.0), - ([1, 2], 1.4142135623730951), - ([0, 3], 1.4142135623730951), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([3], 0.0)) + assert(next(filtration_generator) == ([0, 1], 1.0)) + assert(next(filtration_generator) == ([0, 2], 1.0)) + assert(next(filtration_generator) == ([1, 3], 1.0)) + assert(next(filtration_generator) == ([2, 3], 1.0)) + assert(next(filtration_generator) == ([1, 2], 1.4142135623730951)) + assert(next(filtration_generator) == ([0, 3], 1.4142135623730951)) + with pytest.raises(StopIteration): + next(filtration_generator) + assert simplex_tree.get_star([0]) == [ ([0], 0.0), ([0, 1], 1.0), @@ -95,18 +98,20 @@ def test_rips_from_distance_matrix(): assert simplex_tree.num_simplices() == 10 assert simplex_tree.num_vertices() == 4 - assert simplex_tree.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([3], 0.0), - ([0, 1], 1.0), - ([0, 2], 1.0), - ([1, 3], 1.0), - ([2, 3], 1.0), - ([1, 2], 1.4142135623730951), - ([0, 3], 1.4142135623730951), - ] + filtration_generator = simplex_tree.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([3], 0.0)) + assert(next(filtration_generator) == ([0, 1], 1.0)) + assert(next(filtration_generator) == ([0, 2], 1.0)) + assert(next(filtration_generator) == ([1, 3], 1.0)) + assert(next(filtration_generator) == ([2, 3], 1.0)) + assert(next(filtration_generator) == ([1, 2], 1.4142135623730951)) + assert(next(filtration_generator) == ([0, 3], 1.4142135623730951)) + with pytest.raises(StopIteration): + next(filtration_generator) + assert simplex_tree.get_star([0]) == [ ([0], 0.0), ([0, 1], 1.0), diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 1822c43b..0f3db7ac 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -9,6 +9,7 @@ """ from gudhi import SimplexTree +import pytest __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -126,55 +127,58 @@ def test_expansion(): assert st.num_vertices() == 7 assert st.num_simplices() == 17 - assert st.get_filtration() == [ - ([2], 0.1), - ([3], 0.1), - ([2, 3], 0.1), - ([0], 0.2), - ([0, 2], 0.2), - ([1], 0.3), - ([0, 1], 0.3), - ([1, 3], 0.4), - ([1, 2], 0.5), - ([5], 0.6), - ([6], 0.6), - ([5, 6], 0.6), - ([4], 0.7), - ([2, 4], 0.7), - ([0, 3], 0.8), - ([4, 6], 0.9), - ([3, 6], 1.0), - ] + + filtration_generator = st.get_filtration() + assert(next(filtration_generator) == ([2], 0.1)) + assert(next(filtration_generator) == ([3], 0.1)) + assert(next(filtration_generator) == ([2, 3], 0.1)) + assert(next(filtration_generator) == ([0], 0.2)) + assert(next(filtration_generator) == ([0, 2], 0.2)) + assert(next(filtration_generator) == ([1], 0.3)) + assert(next(filtration_generator) == ([0, 1], 0.3)) + assert(next(filtration_generator) == ([1, 3], 0.4)) + assert(next(filtration_generator) == ([1, 2], 0.5)) + assert(next(filtration_generator) == ([5], 0.6)) + assert(next(filtration_generator) == ([6], 0.6)) + assert(next(filtration_generator) == ([5, 6], 0.6)) + assert(next(filtration_generator) == ([4], 0.7)) + assert(next(filtration_generator) == ([2, 4], 0.7)) + assert(next(filtration_generator) == ([0, 3], 0.8)) + assert(next(filtration_generator) == ([4, 6], 0.9)) + assert(next(filtration_generator) == ([3, 6], 1.0)) + with pytest.raises(StopIteration): + next(filtration_generator) st.expansion(3) assert st.num_vertices() == 7 assert st.num_simplices() == 22 st.initialize_filtration() - assert st.get_filtration() == [ - ([2], 0.1), - ([3], 0.1), - ([2, 3], 0.1), - ([0], 0.2), - ([0, 2], 0.2), - ([1], 0.3), - ([0, 1], 0.3), - ([1, 3], 0.4), - ([1, 2], 0.5), - ([0, 1, 2], 0.5), - ([1, 2, 3], 0.5), - ([5], 0.6), - ([6], 0.6), - ([5, 6], 0.6), - ([4], 0.7), - ([2, 4], 0.7), - ([0, 3], 0.8), - ([0, 1, 3], 0.8), - ([0, 2, 3], 0.8), - ([0, 1, 2, 3], 0.8), - ([4, 6], 0.9), - ([3, 6], 1.0), - ] + filtration_generator = st.get_filtration() + assert(next(filtration_generator) == ([2], 0.1)) + assert(next(filtration_generator) == ([3], 0.1)) + assert(next(filtration_generator) == ([2, 3], 0.1)) + assert(next(filtration_generator) == ([0], 0.2)) + assert(next(filtration_generator) == ([0, 2], 0.2)) + assert(next(filtration_generator) == ([1], 0.3)) + assert(next(filtration_generator) == ([0, 1], 0.3)) + assert(next(filtration_generator) == ([1, 3], 0.4)) + assert(next(filtration_generator) == ([1, 2], 0.5)) + assert(next(filtration_generator) == ([0, 1, 2], 0.5)) + assert(next(filtration_generator) == ([1, 2, 3], 0.5)) + assert(next(filtration_generator) == ([5], 0.6)) + assert(next(filtration_generator) == ([6], 0.6)) + assert(next(filtration_generator) == ([5, 6], 0.6)) + assert(next(filtration_generator) == ([4], 0.7)) + assert(next(filtration_generator) == ([2, 4], 0.7)) + assert(next(filtration_generator) == ([0, 3], 0.8)) + assert(next(filtration_generator) == ([0, 1, 3], 0.8)) + assert(next(filtration_generator) == ([0, 2, 3], 0.8)) + assert(next(filtration_generator) == ([0, 1, 2, 3], 0.8)) + assert(next(filtration_generator) == ([4, 6], 0.9)) + assert(next(filtration_generator) == ([3, 6], 1.0)) + with pytest.raises(StopIteration): + next(filtration_generator) def test_automatic_dimension(): diff --git a/src/python/test/test_tangential_complex.py b/src/python/test/test_tangential_complex.py index e650e99c..90e2c75b 100755 --- a/src/python/test/test_tangential_complex.py +++ b/src/python/test/test_tangential_complex.py @@ -9,6 +9,7 @@ """ from gudhi import TangentialComplex, SimplexTree +import pytest __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -37,14 +38,16 @@ def test_tangential(): assert st.num_simplices() == 6 assert st.num_vertices() == 4 - assert st.get_filtration() == [ - ([0], 0.0), - ([1], 0.0), - ([2], 0.0), - ([0, 2], 0.0), - ([3], 0.0), - ([1, 3], 0.0), - ] + filtration_generator = st.get_filtration() + assert(next(filtration_generator) == ([0], 0.0)) + assert(next(filtration_generator) == ([1], 0.0)) + assert(next(filtration_generator) == ([2], 0.0)) + assert(next(filtration_generator) == ([0, 2], 0.0)) + assert(next(filtration_generator) == ([3], 0.0)) + assert(next(filtration_generator) == ([1, 3], 0.0)) + with pytest.raises(StopIteration): + next(filtration_generator) + assert st.get_cofaces([0], 1) == [([0, 2], 0.0)] assert point_list[0] == tc.get_point(0) -- cgit v1.2.3 From 3253abd27129595f7fcd2be4c2285a93aea98690 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Tue, 11 Feb 2020 17:05:08 +0100 Subject: Update src/python/gudhi/simplex_tree.pyx Co-Authored-By: Marc Glisse --- src/python/gudhi/simplex_tree.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 22978b6e..308b3d2d 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -219,7 +219,7 @@ cdef class SimplexTree: cdef vector[Simplex_tree_simplex_handle].const_iterator end = self.get_ptr().get_filtration_iterator_end() while it != end: - yield(self.get_ptr().get_simplex_and_filtration(dereference(it))) + yield self.get_ptr().get_simplex_and_filtration(dereference(it)) preincrement(it) def get_skeleton(self, dimension): -- cgit v1.2.3 From 1edb818b38ace05b230319227e60838b796ddfc5 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 13 Feb 2020 11:08:44 +0100 Subject: simplex tree skeleton iterator --- src/python/gudhi/simplex_tree.pxd | 10 +++++++++- src/python/gudhi/simplex_tree.pyx | 15 ++++++--------- src/python/include/Simplex_tree_interface.h | 23 ++++++++++------------- src/python/test/test_simplex_tree.py | 8 ++++---- 4 files changed, 29 insertions(+), 27 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 1b0dc881..66c173a6 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -24,6 +24,13 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_simplex_handle "Gudhi::Simplex_tree_interface::Simplex_handle": pass + cdef cppclass Simplex_tree_skeleton_iterator "Gudhi::Simplex_tree_interface::Skeleton_simplex_iterator": + Simplex_tree_skeleton_iterator() + Simplex_tree_simplex_handle& operator*() + Simplex_tree_skeleton_iterator operator++() + bint operator!=(Simplex_tree_skeleton_iterator) + + cdef cppclass Simplex_tree_interface_full_featured "Gudhi::Simplex_tree_interface": Simplex_tree() double simplex_filtration(vector[int] simplex) @@ -37,7 +44,6 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool find_simplex(vector[int] simplex) bool insert_simplex_and_subfaces(vector[int] simplex, double filtration) - vector[pair[vector[int], double]] get_skeleton(int dimension) vector[pair[vector[int], double]] get_star(vector[int] simplex) vector[pair[vector[int], double]] get_cofaces(vector[int] simplex, int dimension) @@ -49,6 +55,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_begin() vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() + Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) + Simplex_tree_skeleton_iterator get_skeleton_iterator_end(int dimension) 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 308b3d2d..efac2d80 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -231,15 +231,12 @@ cdef class SimplexTree: :returns: The (simplices of the) skeleton of a maximum dimension. :rtype: list of tuples(simplex, filtration) """ - cdef vector[pair[vector[int], double]] skeleton \ - = self.get_ptr().get_skeleton(dimension) - ct = [] - for filtered_simplex in skeleton: - v = [] - for vertex in filtered_simplex.first: - v.append(vertex) - ct.append((v, filtered_simplex.second)) - return ct + cdef Simplex_tree_skeleton_iterator it = self.get_ptr().get_skeleton_iterator_begin(dimension) + cdef Simplex_tree_skeleton_iterator end = self.get_ptr().get_skeleton_iterator_end(dimension) + + while it != end: + yield self.get_ptr().get_simplex_and_filtration(dereference(it)) + preincrement(it) def get_star(self, simplex): """This function returns the star of a given N-simplex. diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 878919cc..55d5af97 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -35,6 +35,7 @@ class Simplex_tree_interface : public Simplex_tree { using Simplex = std::vector; using Simplex_and_filtration = std::pair; using Filtered_simplices = std::vector; + using Skeleton_simplex_iterator = typename Base::Skeleton_simplex_iterator; public: bool find_simplex(const Simplex& vh) { @@ -91,18 +92,6 @@ class Simplex_tree_interface : public Simplex_tree { return std::make_pair(std::move(simplex), Base::filtration(f_simplex)); } - Filtered_simplices get_skeleton(int dimension) { - Filtered_simplices skeletons; - for (auto f_simplex : Base::skeleton_simplex_range(dimension)) { - Simplex simplex; - for (auto vertex : Base::simplex_vertex_range(f_simplex)) { - simplex.insert(simplex.begin(), vertex); - } - skeletons.push_back(std::make_pair(simplex, Base::filtration(f_simplex))); - } - return skeletons; - } - Filtered_simplices get_star(const Simplex& simplex) { Filtered_simplices star; for (auto f_simplex : Base::star_simplex_range(Base::find(simplex))) { @@ -134,13 +123,21 @@ class Simplex_tree_interface : public Simplex_tree { // Iterator over the simplex tree typename std::vector::const_iterator get_filtration_iterator_begin() { - Base::initialize_filtration(); + // Base::initialize_filtration(); already performed in filtration_simplex_range return Base::filtration_simplex_range().begin(); } typename std::vector::const_iterator get_filtration_iterator_end() { return Base::filtration_simplex_range().end(); } + + Skeleton_simplex_iterator get_skeleton_iterator_begin(int dimension) { + return Base::skeleton_simplex_range(dimension).begin(); + } + + Skeleton_simplex_iterator get_skeleton_iterator_end(int dimension) { + return Base::skeleton_simplex_range(dimension).end(); + } }; } // namespace Gudhi diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index fa42f2ac..eca3807b 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -56,7 +56,7 @@ def test_insertion(): assert st.filtration([1]) == 0.0 # skeleton test - assert st.get_skeleton(2) == [ + assert list(st.get_skeleton(2)) == [ ([0, 1, 2], 4.0), ([0, 1], 0.0), ([0, 2], 4.0), @@ -65,7 +65,7 @@ def test_insertion(): ([1], 0.0), ([2], 4.0), ] - assert st.get_skeleton(1) == [ + assert list(st.get_skeleton(1)) == [ ([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), @@ -73,12 +73,12 @@ def test_insertion(): ([1], 0.0), ([2], 4.0), ] - assert st.get_skeleton(0) == [([0], 0.0), ([1], 0.0), ([2], 4.0)] + assert list(st.get_skeleton(0)) == [([0], 0.0), ([1], 0.0), ([2], 4.0)] # remove_maximal_simplex test assert st.get_cofaces([0, 1, 2], 1) == [] st.remove_maximal_simplex([0, 1, 2]) - assert st.get_skeleton(2) == [ + assert list(st.get_skeleton(2)) == [ ([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), -- cgit v1.2.3 From 6ed2a97421a223b4ebe31b91f48d779c2209f470 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 16 Mar 2020 13:38:18 +0100 Subject: Add get_simplices method - contrary to get_filtration method, sort is not performed --- src/Simplex_tree/example/simple_simplex_tree.cpp | 13 +++++++++++-- src/python/example/simplex_tree_example.py | 4 ++++ src/python/gudhi/simplex_tree.pxd | 8 ++++++++ src/python/gudhi/simplex_tree.pyx | 17 ++++++++++++++++- src/python/include/Simplex_tree_interface.h | 11 +++++++++++ src/python/test/test_simplex_tree.py | 12 ++++++++++++ 6 files changed, 62 insertions(+), 3 deletions(-) (limited to 'src/python/gudhi/simplex_tree.pyx') diff --git a/src/Simplex_tree/example/simple_simplex_tree.cpp b/src/Simplex_tree/example/simple_simplex_tree.cpp index 4353939f..47ea7e36 100644 --- a/src/Simplex_tree/example/simple_simplex_tree.cpp +++ b/src/Simplex_tree/example/simple_simplex_tree.cpp @@ -166,10 +166,19 @@ int main(int argc, char* const argv[]) { // ++ GENERAL VARIABLE SET std::cout << "********************************************************************\n"; - // Display the Simplex_tree - Can not be done in the middle of 2 inserts std::cout << "* The complex contains " << simplexTree.num_simplices() << " simplices\n"; std::cout << " - dimension " << simplexTree.dimension() << "\n"; - std::cout << "* Iterator on Simplices in the filtration, with [filtration value]:\n"; + std::cout << "* Iterator on simplices, with [filtration value]:\n"; + for (Simplex_tree::Simplex_handle f_simplex : simplexTree.complex_simplex_range()) { + std::cout << " " + << "[" << simplexTree.filtration(f_simplex) << "] "; + for (auto vertex : simplexTree.simplex_vertex_range(f_simplex)) std::cout << "(" << vertex << ")"; + std::cout << std::endl; + } + + std::cout << "********************************************************************\n"; + // Can not be done in the middle of 2 inserts + std::cout << "* Iterator on simplices sorted by filtration values, with [filtration value]:\n"; for (auto f_simplex : simplexTree.filtration_simplex_range()) { std::cout << " " << "[" << simplexTree.filtration(f_simplex) << "] "; diff --git a/src/python/example/simplex_tree_example.py b/src/python/example/simplex_tree_example.py index 7f20c389..34833899 100755 --- a/src/python/example/simplex_tree_example.py +++ b/src/python/example/simplex_tree_example.py @@ -38,6 +38,10 @@ else: print("dimension=", st.dimension()) +print("simplices=") +for simplex_with_filtration in st.get_simplices(): + print("(%s, %.2f)" % tuple(simplex_with_filtration)) + st.initialize_filtration() print("filtration=") for simplex_with_filtration in st.get_filtration(): diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 66c173a6..82f155de 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -24,6 +24,12 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_simplex_handle "Gudhi::Simplex_tree_interface::Simplex_handle": pass + cdef cppclass Simplex_tree_simplices_iterator "Gudhi::Simplex_tree_interface::Complex_simplex_iterator": + Simplex_tree_simplices_iterator() + Simplex_tree_simplex_handle& operator*() + Simplex_tree_simplices_iterator operator++() + bint operator!=(Simplex_tree_simplices_iterator) + cdef cppclass Simplex_tree_skeleton_iterator "Gudhi::Simplex_tree_interface::Skeleton_simplex_iterator": Simplex_tree_skeleton_iterator() Simplex_tree_simplex_handle& operator*() @@ -53,6 +59,8 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": bool make_filtration_non_decreasing() # Iterators over Simplex tree pair[vector[int], double] get_simplex_and_filtration(Simplex_tree_simplex_handle f_simplex) + Simplex_tree_simplices_iterator get_simplices_iterator_begin() + Simplex_tree_simplices_iterator get_simplices_iterator_end() vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_begin() vector[Simplex_tree_simplex_handle].const_iterator get_filtration_iterator_end() Simplex_tree_skeleton_iterator get_skeleton_iterator_begin(int dimension) diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index efac2d80..c01cc905 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -208,10 +208,25 @@ cdef class SimplexTree: return self.get_ptr().insert_simplex_and_subfaces(csimplex, filtration) - def get_filtration(self): + def get_simplices(self): """This function returns a generator with simplices and their given filtration values. + :returns: The simplices. + :rtype: generator with tuples(simplex, filtration) + """ + cdef Simplex_tree_simplices_iterator it = self.get_ptr().get_simplices_iterator_begin() + cdef Simplex_tree_simplices_iterator end = self.get_ptr().get_simplices_iterator_end() + cdef Simplex_tree_simplex_handle sh = dereference(it) + + while it != end: + yield self.get_ptr().get_simplex_and_filtration(dereference(it)) + preincrement(it) + + def get_filtration(self): + """This function returns a generator with simplices and their given + filtration values sorted by increasing filtration values. + :returns: The simplices sorted by increasing filtration values. :rtype: generator with tuples(simplex, filtration) """ diff --git a/src/python/include/Simplex_tree_interface.h b/src/python/include/Simplex_tree_interface.h index 66ce5afd..4a7062d6 100644 --- a/src/python/include/Simplex_tree_interface.h +++ b/src/python/include/Simplex_tree_interface.h @@ -36,6 +36,7 @@ class Simplex_tree_interface : public Simplex_tree { using Simplex_and_filtration = std::pair; using Filtered_simplices = std::vector; using Skeleton_simplex_iterator = typename Base::Skeleton_simplex_iterator; + using Complex_simplex_iterator = typename Base::Complex_simplex_iterator; public: bool find_simplex(const Simplex& vh) { @@ -122,6 +123,16 @@ class Simplex_tree_interface : public Simplex_tree { } // Iterator over the simplex tree + Complex_simplex_iterator get_simplices_iterator_begin() { + // this specific case works because the range is just a pair of iterators - won't work if range was a vector + return Base::complex_simplex_range().begin(); + } + + Complex_simplex_iterator get_simplices_iterator_end() { + // this specific case works because the range is just a pair of iterators - won't work if range was a vector + return Base::complex_simplex_range().end(); + } + typename std::vector::const_iterator get_filtration_iterator_begin() { // Base::initialize_filtration(); already performed in filtration_simplex_range // this specific case works because the range is just a pair of iterators - won't work if range was a vector diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 04b26e92..f7848379 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -249,3 +249,15 @@ def test_make_filtration_non_decreasing(): assert st.filtration([3, 4, 5]) == 2.0 assert st.filtration([3, 4]) == 2.0 assert st.filtration([4, 5]) == 2.0 + +def test_simplices_iterator(): + st = SimplexTree() + + assert st.insert([0, 1, 2], filtration=4.0) == True + assert st.insert([2, 3, 4], filtration=2.0) == True + + for simplex in st.get_simplices(): + print("simplex is: ", simplex[0]) + assert st.find(simplex[0]) == True + print("filtration is: ", simplex[1]) + assert st.filtration(simplex[0]) == simplex[1] -- cgit v1.2.3