From 55ae0517b44744253a6aa4b1aec276e177d3b524 Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 16 Feb 2016 13:54:34 +0000 Subject: First version of Simplex tree cythonized git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/ST_cythonize@1024 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: 353f73e3d8035dfecb65c0885f2caf2a72588538 --- src/cython/Simplex_tree_interface.h | 133 ++++++++++++++++++++++++++++++++++++ src/cython/cgudhi.pxd | 27 +++++++- src/cython/gudhi.pyx | 71 +++++++++++++++++-- src/cython/main.py | 59 ++++++++++++++++ src/cython/setup.py | 2 +- 5 files changed, 282 insertions(+), 10 deletions(-) create mode 100644 src/cython/Simplex_tree_interface.h (limited to 'src') diff --git a/src/cython/Simplex_tree_interface.h b/src/cython/Simplex_tree_interface.h new file mode 100644 index 00000000..df35b335 --- /dev/null +++ b/src/cython/Simplex_tree_interface.h @@ -0,0 +1,133 @@ +/* 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 Complex; + typedef std::pair Filtered_complex; + typedef std::vector Complex_tree; + + public: + + bool find_simplex(const Complex& vh) { + return (Simplex_tree::find(vh) != Simplex_tree::null_simplex()); + } + + bool insert_simplex(const Complex& vh, Filtration_value filtration = 0) { + Insertion_result result = Simplex_tree::insert_simplex(vh, filtration); + return (result.second); + } + + bool insert_simplex_and_subfaces(const Complex& complex, Filtration_value filtration = 0) { + Insertion_result result = Simplex_tree::insert_simplex_and_subfaces(complex, filtration); + return (result.second); + } + + Filtration_value simplex_filtration(const Complex& 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()) { + Complex 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)) { + Complex 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 Complex& complex) { + Complex_tree star_tree; + for (auto f_simplex : Simplex_tree::star_simplex_range(Simplex_tree::find(complex))) { + Complex 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 Complex& complex, int dimension) { + Complex_tree coface_tree; + for (auto f_simplex : Simplex_tree::cofaces_simplex_range(Simplex_tree::find(complex), dimension)) { + Complex 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 index 9ba40999..9d055c44 100644 --- a/src/cython/cgudhi.pxd +++ b/src/cython/cgudhi.pxd @@ -1,9 +1,30 @@ +from libcpp.vector cimport vector +from libcpp.utility cimport pair -cdef extern from "include/gudhi/Simplex_tree.h" namespace "Gudhi": +cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": cdef cppclass Simplex_tree_options_full_featured: pass - cdef Simplex_tree_options_fast_persistence: + cdef cppclass Simplex_tree_options_fast_persistence: pass - cdef cppclass Simplex_tree[T]: + 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(vector[int] simplex, double filtration) + 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/gudhi.pyx b/src/cython/gudhi.pyx index 6fab0726..37a49460 100644 --- a/src/cython/gudhi.pyx +++ b/src/cython/gudhi.pyx @@ -1,18 +1,77 @@ 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[cgudhi.Simplex_tree_options_full_featured] *thisptr - def __cinit__(self): - self.thisptr = new cgudhi.Simplex_tree[cgudhi.Simplex_tree_options_full_featured]() + 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): + return self.thisptr.insert_simplex(simplex, filtration) + def insert_with_subfaces(self, simplex, filtration = 0.0): + return self.thisptr.insert_simplex_and_subfaces(simplex, filtration) + def get_filtered_tree(self): + return self.thisptr.get_filtered_tree() + def get_skeleton_tree(self, dim): + return self.thisptr.get_skeleton_tree(dim) + def get_star_tree(self, simplex): + return self.thisptr.get_star_tree(simplex) + def get_coface_tree(self, simplex, dim): + return self.thisptr.get_coface_tree(simplex, dim) -cdef class MiniSimplexTree: - cdef cgudhi.Simplex_tree[cgudhi.Simplex_tree_options_fast_persistence] *thisptr + +#cdef class MiniSimplexTree: + cdef cgudhi.Simplex_tree_interface[cgudhi.Simplex_tree_options_mini] *thisptr def __cinit__(self): - self.thisptr = new cgudhi.Simplex_tree[cgudhi.Simplex_tree_options_fast_persistence]() + 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 get_filtered_tree(self): + return self.thisptr.get_filtered_tree() + def get_skeleton_tree(self, dim): + return self.thisptr.get_skeleton_tree(dim) diff --git a/src/cython/main.py b/src/cython/main.py index cb7a4754..a36b4fa8 100755 --- a/src/cython/main.py +++ b/src/cython/main.py @@ -3,3 +3,62 @@ 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_with_subfaces([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 graph expansion") +st_from_graph_expansion = gudhi.SimplexTree(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) + +print("filtered_tree=", st_from_graph_expansion.get_filtered_tree()) +print("star([0])=", st_from_graph_expansion.get_star_tree([0])) +print("coface([0],1)=", st_from_graph_expansion.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_simplex_and_subfaces(triangle012) +mini_st.insert_simplex_and_subfaces(edge03) +# FIXME: Remove this line +mini_st.set_dimension(2); + +edge02 = [0, 2] +if st.st.find(edge02): + # Only coface is 012 + print("coface(edge02,1)=", st_from_graph_expansion.get_coface_tree(edge02, 1)) + diff --git a/src/cython/setup.py b/src/cython/setup.py index 26a46590..5942560d 100644 --- a/src/cython/setup.py +++ b/src/cython/setup.py @@ -6,7 +6,7 @@ gudhi = Extension( sources = ['gudhi.pyx',], language = 'c++', extra_compile_args=['-std=c++11'], - include_dirs = ['..'], + include_dirs = ['../include','.'], ) setup( -- cgit v1.2.3