From d9780fc1fda42d78038c327b05203e55e3b40fd0 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Mon, 9 May 2016 10:59:11 +0000 Subject: Directory re-organization for Gudhi modules git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/ST_cythonize@1154 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: acfc931aee37c65ee2828e3873e9727b308e5d76 --- src/cython/Makefile | 8 +- src/cython/README | 3 + src/cython/Simplex_tree_UT.py | 73 ---------- src/cython/Simplex_tree_example.py | 65 --------- src/cython/Simplex_tree_interface.h | 128 ----------------- src/cython/cgudhi.pxd | 29 ---- src/cython/example/Simplex_tree_example.py | 65 +++++++++ src/cython/gudhi.pyx | 156 +------------------- src/cython/setup.py | 6 +- src/cython/src/cpp/Simplex_tree_interface.h | 132 +++++++++++++++++ src/cython/src/cython/Simplex_tree.pyx | 212 ++++++++++++++++++++++++++++ src/cython/test/Simplex_tree_UT.py | 73 ++++++++++ 12 files changed, 497 insertions(+), 453 deletions(-) create mode 100644 src/cython/README delete mode 100755 src/cython/Simplex_tree_UT.py delete mode 100755 src/cython/Simplex_tree_example.py delete mode 100644 src/cython/Simplex_tree_interface.h delete mode 100644 src/cython/cgudhi.pxd create mode 100755 src/cython/example/Simplex_tree_example.py create mode 100644 src/cython/src/cpp/Simplex_tree_interface.h create mode 100644 src/cython/src/cython/Simplex_tree.pyx create mode 100755 src/cython/test/Simplex_tree_UT.py (limited to 'src') diff --git a/src/cython/Makefile b/src/cython/Makefile index c17e9e09..a4fa1104 100644 --- a/src/cython/Makefile +++ b/src/cython/Makefile @@ -2,8 +2,12 @@ ext: python setup.py build_ext --inplace test: - python Simplex_tree_UT.py - python Simplex_tree_example.py + python test/Simplex_tree_UT.py + +example: + python example/Simplex_tree_example.py clean: rm -rf build/ *.o *.so *.cpp + +.PHONY: example test diff --git a/src/cython/README b/src/cython/README new file mode 100644 index 00000000..7d2c4491 --- /dev/null +++ b/src/cython/README @@ -0,0 +1,3 @@ + +If you do not want to install the package, just launch the following command to help Python to find the compiled package : +$> export PYTHONPATH=`pwd`:$PYTHONPATH diff --git a/src/cython/Simplex_tree_UT.py b/src/cython/Simplex_tree_UT.py deleted file mode 100755 index 56113370..00000000 --- a/src/cython/Simplex_tree_UT.py +++ /dev/null @@ -1,73 +0,0 @@ -import unittest - -import gudhi - -class TestSimplexTree(unittest.TestCase): - - def test_insertion(self): - st = gudhi.SimplexTree() - - # insert test - self.assertTrue(st.insert([0,1])) - self.assertTrue(st.insert([0,1,2], filtration=4.0)) - self.assertEqual(st.num_simplices(), 7) - self.assertEqual(st.num_vertices(), 3) - - # find test - self.assertTrue(st.find([0,1,2])) - self.assertTrue(st.find([0,1])) - self.assertTrue(st.find([0,2])) - self.assertTrue(st.find([0])) - self.assertTrue(st.find([1])) - self.assertTrue(st.find([2])) - self.assertFalse(st.find([3])) - self.assertFalse(st.find([0,3])) - self.assertFalse(st.find([1,3])) - self.assertFalse(st.find([2,3])) - - # filtration test - st.set_filtration(5.0) - st.initialize_filtration() - self.assertEqual(st.get_filtration(), 5.0) - self.assertEqual(st.filtration([0,1,2]), 4.0) - self.assertEqual(st.filtration([0,2]), 4.0) - self.assertEqual(st.filtration([1,2]), 4.0) - self.assertEqual(st.filtration([2]), 4.0) - self.assertEqual(st.filtration([0,1]), 0.0) - self.assertEqual(st.filtration([0]), 0.0) - self.assertEqual(st.filtration([1]), 0.0) - - # skeleton_tree test - self.assertEqual(st.get_skeleton_tree(2), [([0, 1, 2], 4.0), ([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), ([1, 2], 4.0), ([1], 0.0), ([2], 4.0)]) - self.assertEqual(st.get_skeleton_tree(1), [([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), ([1, 2], 4.0), ([1], 0.0), ([2], 4.0)]) - self.assertEqual(st.get_skeleton_tree(0), [([0], 0.0), ([1], 0.0), ([2], 4.0)]) - - def test_rips(self): - rips_complex = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) - - self.assertEqual(rips_complex.num_simplices(), 10) - self.assertEqual(rips_complex.num_vertices(), 4) - - self.assertEqual(rips_complex.get_filtered_tree(), [([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)]) - self.assertEqual(rips_complex.get_star_tree([0]), [([0], 0.0), ([0, 1], 1.0), ([0, 2], 1.0), ([0, 3], 1.4142135623730951)]) - self.assertEqual(rips_complex.get_coface_tree([0], 1), [([0, 1], 1.0), ([0, 2], 1.0), ([0, 3], 1.4142135623730951)]) - - filtered_rips = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=1.0) - self.assertEqual(filtered_rips.num_simplices(), 8) - self.assertEqual(filtered_rips.num_vertices(), 4) - - def test_split(self): - triangle012 = [0,1,2] - edge03 = [0,3] - mini_st = gudhi.MiniSimplexTree() - self.assertTrue(mini_st.insert(triangle012)) - self.assertTrue(mini_st.insert(edge03)) - # FIXME: Remove this line - mini_st.set_dimension(2); - - edge02 = [0,2] - self.assertTrue(mini_st.find(edge02)) - self.assertEqual(mini_st.get_coface_tree(edge02, 1), [([0, 1, 2], 0.0)]) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/src/cython/Simplex_tree_example.py b/src/cython/Simplex_tree_example.py deleted file mode 100755 index e9459588..00000000 --- a/src/cython/Simplex_tree_example.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python - -import gudhi - -st = gudhi.SimplexTree() - -print("#######################################################################") -print("SimplexTree creation from insertion") -if st.insert([0,1]): - print("Inserted !!") -else: - print("Not inserted...") - -if st.find([0,1]): - print("Found !!") -else: - print("Not found...") - -if st.insert([0,1,2], filtration=4.0): - print("Inserted !!") -else: - print("Not inserted...") - -# FIXME: Remove this line -st.set_dimension(3) -print("dimension=", st.dimension()) - -st.set_filtration(4.0) -st.initialize_filtration() -print("filtration=", st.get_filtration()) -print("filtration[1,2]=", st.filtration([1,2])) -print("filtration[4,2]=", st.filtration([4,2])) - -print("num_simplices=", st.num_simplices()) -print("num_vertices=", st.num_vertices()) - -print("skeleton_tree[2]=", st.get_skeleton_tree(2)) -print("skeleton_tree[1]=", st.get_skeleton_tree(1)) -print("skeleton_tree[0]=", st.get_skeleton_tree(0)) - -print("#######################################################################") -print("SimplexTree creation from Rips") -st_from_rips = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) - -print("filtered_tree=", st_from_rips.get_filtered_tree()) -print("star([0])=", st_from_rips.get_star_tree([0])) -print("coface([0],1)=", st_from_rips.get_coface_tree([0], 1)) - - -print("#######################################################################") -print("MiniSimplexTree creation from insertion") -triangle012 = [0, 1, 2] -edge03 = [0, 3] -mini_st = gudhi.MiniSimplexTree() -mini_st.insert(triangle012) -mini_st.insert(edge03) -# FIXME: Remove this line -mini_st.set_dimension(2); - -edge02 = [0, 2] -if mini_st.find(edge02): - # Only coface is 012 - print("coface(edge02,1)=", mini_st.get_coface_tree(edge02, 1)) -print("filtered_tree=", mini_st.get_filtered_tree()) - diff --git a/src/cython/Simplex_tree_interface.h b/src/cython/Simplex_tree_interface.h deleted file mode 100644 index dc29bed5..00000000 --- a/src/cython/Simplex_tree_interface.h +++ /dev/null @@ -1,128 +0,0 @@ -/* This file is part of the Gudhi Library. The Gudhi library - * (Geometric Understanding in Higher Dimensions) is a generic C++ - * library for computational topology. - * - * Author(s): Vincent Rouvreau - * - * Copyright (C) 2016 INRIA Sophia Antipolis-Méditerranée (France) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SIMPLEX_TREE_INTERFACE_H -#define SIMPLEX_TREE_INTERFACE_H - -#include -#include -#include - -#include -#include // std::pair -#include - -namespace Gudhi { - -template -class Simplex_tree_interface : public Simplex_tree { - typedef typename Simplex_tree::Simplex_handle Simplex_handle; - typedef typename std::pair Insertion_result; - typedef std::vector Simplex; - typedef std::pair Filtered_complex; - typedef std::vector Complex_tree; - - public: - - bool find_simplex(const Simplex& vh) { - return (Simplex_tree::find(vh) != Simplex_tree::null_simplex()); - } - - bool insert_simplex_and_subfaces(const Simplex& complex, Filtration_value filtration = 0) { - Insertion_result result = Simplex_tree::insert_simplex_and_subfaces(complex, filtration); - return (result.second); - } - - Filtration_value simplex_filtration(const Simplex& complex) { - return Simplex_tree::filtration(Simplex_tree::find(complex)); - } - - Complex_tree get_filtered_tree() { - Complex_tree filtered_tree; - for (auto f_simplex : Simplex_tree::filtration_simplex_range()) { - Simplex simplex; - for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { - simplex.insert(simplex.begin(), vertex); - } - filtered_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); - } - return filtered_tree; - - } - - Complex_tree get_skeleton_tree(int dimension) { - Complex_tree skeleton_tree; - for (auto f_simplex : Simplex_tree::skeleton_simplex_range(dimension)) { - Simplex simplex; - for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { - simplex.insert(simplex.begin(), vertex); - } - skeleton_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); - } - return skeleton_tree; - } - - Complex_tree get_star_tree(const Simplex& complex) { - Complex_tree star_tree; - for (auto f_simplex : Simplex_tree::star_simplex_range(Simplex_tree::find(complex))) { - Simplex simplex; - for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { - simplex.insert(simplex.begin(), vertex); - } - star_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); - } - return star_tree; - } - - Complex_tree get_coface_tree(const Simplex& complex, int dimension) { - Complex_tree coface_tree; - for (auto f_simplex : Simplex_tree::cofaces_simplex_range(Simplex_tree::find(complex), dimension)) { - Simplex simplex; - for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { - simplex.insert(simplex.begin(), vertex); - } - coface_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); - } - return coface_tree; - } - - void graph_expansion(std::vector>&points, int max_dimension, double max_edge_length) { - Graph_t prox_graph = compute_proximity_graph(points, max_edge_length, euclidean_distance>); - Simplex_tree::insert_graph(prox_graph); - Simplex_tree::expansion(max_dimension); - Simplex_tree::initialize_filtration(); - } - -}; - -struct Simplex_tree_options_mini : Simplex_tree_options_full_featured { - // Not doing persistence, so we don't need those - static const bool store_key = false; - static const bool store_filtration = false; - // I have few vertices - typedef short Vertex_handle; -}; - -} // namespace Gudhi - -#endif // SIMPLEX_TREE_INTERFACE_H - diff --git a/src/cython/cgudhi.pxd b/src/cython/cgudhi.pxd deleted file mode 100644 index 1be7309d..00000000 --- a/src/cython/cgudhi.pxd +++ /dev/null @@ -1,29 +0,0 @@ -from libcpp.vector cimport vector -from libcpp.utility cimport pair - -cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": - cdef cppclass Simplex_tree_options_full_featured: - pass - cdef cppclass Simplex_tree_options_fast_persistence: - pass - cdef cppclass Simplex_tree_options_mini: - pass - cdef cppclass Simplex_tree_interface[T]: - Simplex_tree() - double filtration() - double simplex_filtration(vector[int] simplex) - void set_filtration(double filtration) - void initialize_filtration() - int num_vertices() - int num_simplices() - void set_dimension(int dimension) - int dimension() - bint find_simplex(vector[int] simplex) - bint insert_simplex_and_subfaces(vector[int] simplex, double filtration) - vector[pair[vector[int], double]] get_filtered_tree() - vector[pair[vector[int], double]] get_skeleton_tree(int dimension) - vector[pair[vector[int], double]] get_star_tree(vector[int] simplex) - vector[pair[vector[int], double]] get_coface_tree(vector[int] simplex, int dimension) - void graph_expansion(vector[vector[double]] points,int max_dimension,double max_edge_length) - - diff --git a/src/cython/example/Simplex_tree_example.py b/src/cython/example/Simplex_tree_example.py new file mode 100755 index 00000000..e9459588 --- /dev/null +++ b/src/cython/example/Simplex_tree_example.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import gudhi + +st = gudhi.SimplexTree() + +print("#######################################################################") +print("SimplexTree creation from insertion") +if st.insert([0,1]): + print("Inserted !!") +else: + print("Not inserted...") + +if st.find([0,1]): + print("Found !!") +else: + print("Not found...") + +if st.insert([0,1,2], filtration=4.0): + print("Inserted !!") +else: + print("Not inserted...") + +# FIXME: Remove this line +st.set_dimension(3) +print("dimension=", st.dimension()) + +st.set_filtration(4.0) +st.initialize_filtration() +print("filtration=", st.get_filtration()) +print("filtration[1,2]=", st.filtration([1,2])) +print("filtration[4,2]=", st.filtration([4,2])) + +print("num_simplices=", st.num_simplices()) +print("num_vertices=", st.num_vertices()) + +print("skeleton_tree[2]=", st.get_skeleton_tree(2)) +print("skeleton_tree[1]=", st.get_skeleton_tree(1)) +print("skeleton_tree[0]=", st.get_skeleton_tree(0)) + +print("#######################################################################") +print("SimplexTree creation from Rips") +st_from_rips = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) + +print("filtered_tree=", st_from_rips.get_filtered_tree()) +print("star([0])=", st_from_rips.get_star_tree([0])) +print("coface([0],1)=", st_from_rips.get_coface_tree([0], 1)) + + +print("#######################################################################") +print("MiniSimplexTree creation from insertion") +triangle012 = [0, 1, 2] +edge03 = [0, 3] +mini_st = gudhi.MiniSimplexTree() +mini_st.insert(triangle012) +mini_st.insert(edge03) +# FIXME: Remove this line +mini_st.set_dimension(2); + +edge02 = [0, 2] +if mini_st.find(edge02): + # Only coface is 012 + print("coface(edge02,1)=", mini_st.get_coface_tree(edge02, 1)) +print("filtered_tree=", mini_st.get_filtered_tree()) + diff --git a/src/cython/gudhi.pyx b/src/cython/gudhi.pyx index c5757039..551226c5 100644 --- a/src/cython/gudhi.pyx +++ b/src/cython/gudhi.pyx @@ -1,155 +1 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair - -cimport cgudhi - - -# SimplexTree python interface -cdef class SimplexTree: - cdef cgudhi.Simplex_tree_interface[cgudhi.Simplex_tree_options_full_featured] *thisptr - def __cinit__(self, points=None, max_dimension=3, max_edge_length=float('inf')): - self.thisptr = new cgudhi.Simplex_tree_interface[cgudhi.Simplex_tree_options_full_featured]() - # Constructor from graph expansion - if points is not None: - self.thisptr.graph_expansion(points,max_dimension,max_edge_length) - def __dealloc__(self): - if self.thisptr != NULL: - del self.thisptr - def get_filtration(self): - return self.thisptr.filtration() - def filtration(self, simplex): - return self.thisptr.simplex_filtration(simplex) - def set_filtration(self, filtration): - self.thisptr.set_filtration(filtration) - def initialize_filtration(self): - self.thisptr.initialize_filtration() - def num_vertices(self): - return self.thisptr.num_vertices() - def num_simplices(self): - return self.thisptr.num_simplices() - def dimension(self): - return self.thisptr.dimension() - def set_dimension(self, dim): - self.thisptr.set_dimension(dim) - def find(self, simplex): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - return self.thisptr.find_simplex(complex) - def insert(self, simplex, filtration = 0.0): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - return self.thisptr.insert_simplex_and_subfaces(complex, filtration) - def get_filtered_tree(self): - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_filtered_tree() - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_skeleton_tree(self, dim): - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_skeleton_tree(dim) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_star_tree(self, simplex): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_star_tree(complex) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_coface_tree(self, simplex, dim): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_coface_tree(complex, dim) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - - -cdef class MiniSimplexTree: - cdef cgudhi.Simplex_tree_interface[cgudhi.Simplex_tree_options_mini] *thisptr - def __cinit__(self): - self.thisptr = new cgudhi.Simplex_tree_interface[cgudhi.Simplex_tree_options_mini]() - def __dealloc__(self): - if self.thisptr != NULL: - del self.thisptr - def num_vertices(self): - return self.thisptr.num_vertices() - def num_simplices(self): - return self.thisptr.num_simplices() - def dimension(self): - return self.thisptr.dimension() - def set_dimension(self, dim): - self.thisptr.set_dimension(dim) - def find(self, simplex): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - return self.thisptr.find_simplex(complex) - def insert(self, simplex, filtration = 0.0): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - return self.thisptr.insert_simplex_and_subfaces(complex, filtration) - def get_filtered_tree(self): - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_filtered_tree() - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_skeleton_tree(self, dim): - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_skeleton_tree(dim) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_star_tree(self, simplex): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_star_tree(complex) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct - def get_coface_tree(self, simplex, dim): - cdef vector[int] complex - for i in simplex: - complex.push_back(i) - cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_coface_tree(complex, dim) - ct = [] - for filtered_complex in coface_tree: - v = [] - for vertex in filtered_complex.first: - v.append(vertex) - ct.append((v,filtered_complex.second)) - return ct +include "src/cython/Simplex_tree.pyx" diff --git a/src/cython/setup.py b/src/cython/setup.py index 5942560d..8439a071 100644 --- a/src/cython/setup.py +++ b/src/cython/setup.py @@ -6,10 +6,14 @@ gudhi = Extension( sources = ['gudhi.pyx',], language = 'c++', extra_compile_args=['-std=c++11'], - include_dirs = ['../include','.'], + include_dirs = ['../include','./src/cpp'], ) setup( name = 'gudhi', + author='Vincent Rouvreau', + author_email='gudhi-contact@lists.gforge.inria.fr', + version='0.1.0', + url='http://gudhi.gforge.inria.fr/', ext_modules = cythonize(gudhi), ) diff --git a/src/cython/src/cpp/Simplex_tree_interface.h b/src/cython/src/cpp/Simplex_tree_interface.h new file mode 100644 index 00000000..2850d7b6 --- /dev/null +++ b/src/cython/src/cpp/Simplex_tree_interface.h @@ -0,0 +1,132 @@ +/* This file is part of the Gudhi Library. The Gudhi library + * (Geometric Understanding in Higher Dimensions) is a generic C++ + * library for computational topology. + * + * Author(s): Vincent Rouvreau + * + * Copyright (C) 2016 INRIA Sophia Antipolis-Méditerranée (France) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SIMPLEX_TREE_INTERFACE_H +#define SIMPLEX_TREE_INTERFACE_H + +#include +#include +#include + +#include +#include // std::pair +#include + +namespace Gudhi { + +template +class Simplex_tree_interface : public Simplex_tree { + typedef typename Simplex_tree::Simplex_handle Simplex_handle; + typedef typename std::pair Insertion_result; + typedef std::vector Simplex; + typedef std::pair Filtered_complex; + typedef std::vector Complex_tree; + + public: + + bool find_simplex(const Simplex& vh) { + return (Simplex_tree::find(vh) != Simplex_tree::null_simplex()); + } + + bool insert_simplex_and_subfaces(const Simplex& complex, Filtration_value filtration = 0) { + Insertion_result result = Simplex_tree::insert_simplex_and_subfaces(complex, filtration); + return (result.second); + } + + Filtration_value simplex_filtration(const Simplex& complex) { + return Simplex_tree::filtration(Simplex_tree::find(complex)); + } + + void remove_maximal_simplex(const Simplex& complex) { + return Simplex_tree::remove_maximal_simplex(Simplex_tree::find(complex)); + } + + Complex_tree get_filtered_tree() { + Complex_tree filtered_tree; + for (auto f_simplex : Simplex_tree::filtration_simplex_range()) { + Simplex simplex; + for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + filtered_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); + } + return filtered_tree; + + } + + Complex_tree get_skeleton_tree(int dimension) { + Complex_tree skeleton_tree; + for (auto f_simplex : Simplex_tree::skeleton_simplex_range(dimension)) { + Simplex simplex; + for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + skeleton_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); + } + return skeleton_tree; + } + + Complex_tree get_star_tree(const Simplex& complex) { + Complex_tree star_tree; + for (auto f_simplex : Simplex_tree::star_simplex_range(Simplex_tree::find(complex))) { + Simplex simplex; + for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + star_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); + } + return star_tree; + } + + Complex_tree get_coface_tree(const Simplex& complex, int dimension) { + Complex_tree coface_tree; + for (auto f_simplex : Simplex_tree::cofaces_simplex_range(Simplex_tree::find(complex), dimension)) { + Simplex simplex; + for (auto vertex : Simplex_tree::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + coface_tree.push_back(std::make_pair(simplex, Simplex_tree::filtration(f_simplex))); + } + return coface_tree; + } + + void graph_expansion(std::vector>&points, int max_dimension, double max_edge_length) { + Graph_t prox_graph = compute_proximity_graph(points, max_edge_length, euclidean_distance>); + Simplex_tree::insert_graph(prox_graph); + Simplex_tree::expansion(max_dimension); + Simplex_tree::initialize_filtration(); + } + +}; + +struct Simplex_tree_options_mini : Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = false; + static const bool store_filtration = false; + // I have few vertices + typedef short Vertex_handle; +}; + +} // namespace Gudhi + +#endif // SIMPLEX_TREE_INTERFACE_H + diff --git a/src/cython/src/cython/Simplex_tree.pyx b/src/cython/src/cython/Simplex_tree.pyx new file mode 100644 index 00000000..91ee9dbe --- /dev/null +++ b/src/cython/src/cython/Simplex_tree.pyx @@ -0,0 +1,212 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": + cdef cppclass Simplex_tree_options_full_featured: + pass + cdef cppclass Simplex_tree_interface_full_featured "Gudhi::Simplex_tree_interface": + Simplex_tree() + double filtration() + double simplex_filtration(vector[int] simplex) + void set_filtration(double filtration) + void initialize_filtration() + int num_vertices() + int num_simplices() + void set_dimension(int dimension) + int dimension() + bint find_simplex(vector[int] simplex) + bint insert_simplex_and_subfaces(vector[int] simplex, double filtration) + vector[pair[vector[int], double]] get_filtered_tree() + vector[pair[vector[int], double]] get_skeleton_tree(int dimension) + vector[pair[vector[int], double]] get_star_tree(vector[int] simplex) + vector[pair[vector[int], double]] get_coface_tree(vector[int] simplex, int dimension) + void graph_expansion(vector[vector[double]] points,int max_dimension,double max_edge_length) + void remove_maximal_simplex(vector[int] simplex) + +# SimplexTree python interface +cdef class SimplexTree: + cdef Simplex_tree_interface_full_featured *thisptr + def __cinit__(self, points=None, max_dimension=3, max_edge_length=float('inf')): + self.thisptr = new Simplex_tree_interface_full_featured() + # Constructor from graph expansion + if points is not None: + self.thisptr.graph_expansion(points,max_dimension,max_edge_length) + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + def get_filtration(self): + return self.thisptr.filtration() + def filtration(self, simplex): + return self.thisptr.simplex_filtration(simplex) + def set_filtration(self, filtration): + self.thisptr.set_filtration(filtration) + def initialize_filtration(self): + self.thisptr.initialize_filtration() + def num_vertices(self): + return self.thisptr.num_vertices() + def num_simplices(self): + return self.thisptr.num_simplices() + def dimension(self): + return self.thisptr.dimension() + def set_dimension(self, dim): + self.thisptr.set_dimension(dim) + def find(self, simplex): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.find_simplex(complex) + def insert(self, simplex, filtration = 0.0): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, filtration) + def get_filtered_tree(self): + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_filtered_tree() + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_skeleton_tree(self, dim): + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_skeleton_tree(dim) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_star_tree(self, simplex): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_star_tree(complex) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_coface_tree(self, simplex, dim): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_coface_tree(complex, dim) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def remove_maximal_simplex(self, simplex): + self.thisptr.remove_maximal_simplex(simplex) + + +cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": + cdef cppclass Simplex_tree_options_mini: + pass + cdef cppclass Simplex_tree_interface_mini "Gudhi::Simplex_tree_interface": + Simplex_tree() + double filtration() + double simplex_filtration(vector[int] simplex) + void set_filtration(double filtration) + void initialize_filtration() + int num_vertices() + int num_simplices() + void set_dimension(int dimension) + int dimension() + bint find_simplex(vector[int] simplex) + bint insert_simplex_and_subfaces(vector[int] simplex, double filtration) + vector[pair[vector[int], double]] get_filtered_tree() + vector[pair[vector[int], double]] get_skeleton_tree(int dimension) + vector[pair[vector[int], double]] get_star_tree(vector[int] simplex) + vector[pair[vector[int], double]] get_coface_tree(vector[int] simplex, int dimension) + void graph_expansion(vector[vector[double]] points,int max_dimension,double max_edge_length) + void remove_maximal_simplex(vector[int] simplex) + +# SimplexTree python interface +cdef class MiniSimplexTree: + cdef Simplex_tree_interface_mini *thisptr + def __cinit__(self, points=None, max_dimension=3, max_edge_length=float('inf')): + self.thisptr = new Simplex_tree_interface_mini() + # Constructor from graph expansion + if points is not None: + self.thisptr.graph_expansion(points,max_dimension,max_edge_length) + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + def get_filtration(self): + return self.thisptr.filtration() + def filtration(self, simplex): + return self.thisptr.simplex_filtration(simplex) + def set_filtration(self, filtration): + self.thisptr.set_filtration(filtration) + def initialize_filtration(self): + self.thisptr.initialize_filtration() + def num_vertices(self): + return self.thisptr.num_vertices() + def num_simplices(self): + return self.thisptr.num_simplices() + def dimension(self): + return self.thisptr.dimension() + def set_dimension(self, dim): + self.thisptr.set_dimension(dim) + def find(self, simplex): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.find_simplex(complex) + def insert(self, simplex, filtration = 0.0): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, filtration) + def get_filtered_tree(self): + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_filtered_tree() + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_skeleton_tree(self, dim): + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_skeleton_tree(dim) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_star_tree(self, simplex): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_star_tree(complex) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def get_coface_tree(self, simplex, dim): + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + cdef vector[pair[vector[int], double]] coface_tree = self.thisptr.get_coface_tree(complex, dim) + ct = [] + for filtered_complex in coface_tree: + v = [] + for vertex in filtered_complex.first: + v.append(vertex) + ct.append((v,filtered_complex.second)) + return ct + def remove_maximal_simplex(self, simplex): + self.thisptr.remove_maximal_simplex(simplex) diff --git a/src/cython/test/Simplex_tree_UT.py b/src/cython/test/Simplex_tree_UT.py new file mode 100755 index 00000000..56113370 --- /dev/null +++ b/src/cython/test/Simplex_tree_UT.py @@ -0,0 +1,73 @@ +import unittest + +import gudhi + +class TestSimplexTree(unittest.TestCase): + + def test_insertion(self): + st = gudhi.SimplexTree() + + # insert test + self.assertTrue(st.insert([0,1])) + self.assertTrue(st.insert([0,1,2], filtration=4.0)) + self.assertEqual(st.num_simplices(), 7) + self.assertEqual(st.num_vertices(), 3) + + # find test + self.assertTrue(st.find([0,1,2])) + self.assertTrue(st.find([0,1])) + self.assertTrue(st.find([0,2])) + self.assertTrue(st.find([0])) + self.assertTrue(st.find([1])) + self.assertTrue(st.find([2])) + self.assertFalse(st.find([3])) + self.assertFalse(st.find([0,3])) + self.assertFalse(st.find([1,3])) + self.assertFalse(st.find([2,3])) + + # filtration test + st.set_filtration(5.0) + st.initialize_filtration() + self.assertEqual(st.get_filtration(), 5.0) + self.assertEqual(st.filtration([0,1,2]), 4.0) + self.assertEqual(st.filtration([0,2]), 4.0) + self.assertEqual(st.filtration([1,2]), 4.0) + self.assertEqual(st.filtration([2]), 4.0) + self.assertEqual(st.filtration([0,1]), 0.0) + self.assertEqual(st.filtration([0]), 0.0) + self.assertEqual(st.filtration([1]), 0.0) + + # skeleton_tree test + self.assertEqual(st.get_skeleton_tree(2), [([0, 1, 2], 4.0), ([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), ([1, 2], 4.0), ([1], 0.0), ([2], 4.0)]) + self.assertEqual(st.get_skeleton_tree(1), [([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), ([1, 2], 4.0), ([1], 0.0), ([2], 4.0)]) + self.assertEqual(st.get_skeleton_tree(0), [([0], 0.0), ([1], 0.0), ([2], 4.0)]) + + def test_rips(self): + rips_complex = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) + + self.assertEqual(rips_complex.num_simplices(), 10) + self.assertEqual(rips_complex.num_vertices(), 4) + + self.assertEqual(rips_complex.get_filtered_tree(), [([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)]) + self.assertEqual(rips_complex.get_star_tree([0]), [([0], 0.0), ([0, 1], 1.0), ([0, 2], 1.0), ([0, 3], 1.4142135623730951)]) + self.assertEqual(rips_complex.get_coface_tree([0], 1), [([0, 1], 1.0), ([0, 2], 1.0), ([0, 3], 1.4142135623730951)]) + + filtered_rips = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=1.0) + self.assertEqual(filtered_rips.num_simplices(), 8) + self.assertEqual(filtered_rips.num_vertices(), 4) + + def test_split(self): + triangle012 = [0,1,2] + edge03 = [0,3] + mini_st = gudhi.MiniSimplexTree() + self.assertTrue(mini_st.insert(triangle012)) + self.assertTrue(mini_st.insert(edge03)) + # FIXME: Remove this line + mini_st.set_dimension(2); + + edge02 = [0,2] + self.assertTrue(mini_st.find(edge02)) + self.assertEqual(mini_st.get_coface_tree(edge02, 1), [([0, 1, 2], 0.0)]) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file -- cgit v1.2.3