From 7eb4beac61db2ba22fa0293ac816da87d98ffeff Mon Sep 17 00:00:00 2001 From: vrouvrea Date: Tue, 17 May 2016 13:06:32 +0000 Subject: Separate Rips_complex from Simplex_tree Add Alpha_complex_UT git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/ST_cythonize@1179 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: ae209f9e070dd3e27c8eb93f0a1edf2842e9c561 --- src/cython/Makefile | 3 + src/cython/example/Rips_complex_example.py | 11 +++ src/cython/example/Simplex_tree_example.py | 9 -- src/cython/gudhi.pyx | 1 + src/cython/src/cython/Rips_complex.pyx | 132 +++++++++++++++++++++++++++++ src/cython/src/cython/Simplex_tree.pyx | 6 +- src/cython/test/Alpha_complex_UT.py | 44 ++++++++++ src/cython/test/Rips_complex_UT.py | 24 ++++++ src/cython/test/Simplex_tree_UT.py | 14 --- 9 files changed, 216 insertions(+), 28 deletions(-) create mode 100755 src/cython/example/Rips_complex_example.py create mode 100644 src/cython/src/cython/Rips_complex.pyx create mode 100755 src/cython/test/Alpha_complex_UT.py create mode 100755 src/cython/test/Rips_complex_UT.py diff --git a/src/cython/Makefile b/src/cython/Makefile index 95bbfe6c..530b33c1 100644 --- a/src/cython/Makefile +++ b/src/cython/Makefile @@ -3,9 +3,12 @@ ext: test: python test/Simplex_tree_UT.py + python test/Rips_complex_UT.py + python test/Alpha_complex_UT.py example: python example/Simplex_tree_example.py + python example/Rips_complex_example.py python example/Alpha_complex_example.py clean: diff --git a/src/cython/example/Rips_complex_example.py b/src/cython/example/Rips_complex_example.py new file mode 100755 index 00000000..0e8a0968 --- /dev/null +++ b/src/cython/example/Rips_complex_example.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import gudhi + +print("#######################################################################") +print("RipsComplex creation from points") +rips = gudhi.RipsComplex(points=[[0,0],[1,0],[0,1],[1,1]],max_dimension=1,max_edge_length=42) + +print("filtered_tree=", rips.get_filtered_tree()) +print("star([0])=", rips.get_star_tree([0])) +print("coface([0],1)=", rips.get_coface_tree([0], 1)) diff --git a/src/cython/example/Simplex_tree_example.py b/src/cython/example/Simplex_tree_example.py index 049b2ca4..119fbc65 100755 --- a/src/cython/example/Simplex_tree_example.py +++ b/src/cython/example/Simplex_tree_example.py @@ -38,15 +38,6 @@ 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] diff --git a/src/cython/gudhi.pyx b/src/cython/gudhi.pyx index 8f583129..f79ecbe4 100644 --- a/src/cython/gudhi.pyx +++ b/src/cython/gudhi.pyx @@ -1,2 +1,3 @@ include "src/cython/Simplex_tree.pyx" +include "src/cython/Rips_complex.pyx" include "src/cython/Alpha_complex.pyx" diff --git a/src/cython/src/cython/Rips_complex.pyx b/src/cython/src/cython/Rips_complex.pyx new file mode 100644 index 00000000..7676dde1 --- /dev/null +++ b/src/cython/src/cython/Rips_complex.pyx @@ -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 Saclay (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 .""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA Saclay (France)" +__license__ = "GPL v3" + +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 Rips_complex_interface "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 remove_maximal_simplex(vector[int] simplex) + void graph_expansion(vector[vector[double]] points,int max_dimension,double max_edge_length) + +# RipsComplex python interface +cdef class RipsComplex: + cdef Rips_complex_interface *thisptr + def __cinit__(self, points=None, max_dimension=3, max_edge_length=float('inf')): + self.thisptr = new Rips_complex_interface() + # 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/src/cython/Simplex_tree.pyx b/src/cython/src/cython/Simplex_tree.pyx index 04b7ef08..819ae5f0 100644 --- a/src/cython/src/cython/Simplex_tree.pyx +++ b/src/cython/src/cython/Simplex_tree.pyx @@ -46,17 +46,13 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": 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')): + def __cinit__(self): 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 diff --git a/src/cython/test/Alpha_complex_UT.py b/src/cython/test/Alpha_complex_UT.py new file mode 100755 index 00000000..96331991 --- /dev/null +++ b/src/cython/test/Alpha_complex_UT.py @@ -0,0 +1,44 @@ +import unittest + +import gudhi + +class TestAlphaComplex(unittest.TestCase): + + def test_infinite_alpha(self): + point_list=[[0,0],[1,0],[0,1],[1,1]] + alpha_complex = gudhi.AlphaComplex(points=point_list) + + self.assertEqual(alpha_complex.num_simplices(), 11) + self.assertEqual(alpha_complex.num_vertices(), 4) + + self.assertEqual(alpha_complex.get_filtered_tree(), [([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)]) + self.assertEqual(alpha_complex.get_star_tree([0]), [([0], 0.0), ([0, 1], 0.25), ([0, 1, 2], 0.5), ([0, 2], 0.25)]) + self.assertEqual(alpha_complex.get_coface_tree([0], 1), [([0, 1], 0.25), ([0, 2], 0.25)]) + + self.assertEqual(point_list[0], alpha_complex.get_point(0)) + self.assertEqual(point_list[1], alpha_complex.get_point(1)) + self.assertEqual(point_list[2], alpha_complex.get_point(2)) + self.assertEqual(point_list[3], alpha_complex.get_point(3)) + self.assertEqual([], alpha_complex.get_point(4)) + self.assertEqual([], alpha_complex.get_point(125)) + + def test_filtered_alpha(self): + point_list=[[0,0],[1,0],[0,1],[1,1]] + filtered_alpha = gudhi.AlphaComplex(points=point_list,max_alpha_square=0.25) + + self.assertEqual(filtered_alpha.num_simplices(), 8) + self.assertEqual(filtered_alpha.num_vertices(), 4) + + self.assertEqual(point_list[0], filtered_alpha.get_point(0)) + self.assertEqual(point_list[1], filtered_alpha.get_point(1)) + self.assertEqual(point_list[2], filtered_alpha.get_point(2)) + self.assertEqual(point_list[3], filtered_alpha.get_point(3)) + self.assertEqual([], filtered_alpha.get_point(4)) + self.assertEqual([], filtered_alpha.get_point(125)) + + self.assertEqual(filtered_alpha.get_filtered_tree(), [([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)]) + self.assertEqual(filtered_alpha.get_star_tree([0]), [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)]) + self.assertEqual(filtered_alpha.get_coface_tree([0], 1), [([0, 1], 0.25), ([0, 2], 0.25)]) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/src/cython/test/Rips_complex_UT.py b/src/cython/test/Rips_complex_UT.py new file mode 100755 index 00000000..d27e180c --- /dev/null +++ b/src/cython/test/Rips_complex_UT.py @@ -0,0 +1,24 @@ +import unittest + +import gudhi + +class TestRipsComplex(unittest.TestCase): + + def test_rips(self): + point_list=[[0,0],[1,0],[0,1],[1,1]] + rips_complex = gudhi.RipsComplex(points=point_list,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.RipsComplex(points=point_list,max_dimension=1,max_edge_length=1.0) + + self.assertEqual(filtered_rips.num_simplices(), 8) + self.assertEqual(filtered_rips.num_vertices(), 4) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/src/cython/test/Simplex_tree_UT.py b/src/cython/test/Simplex_tree_UT.py index 9a62e009..050ef289 100755 --- a/src/cython/test/Simplex_tree_UT.py +++ b/src/cython/test/Simplex_tree_UT.py @@ -53,20 +53,6 @@ class TestSimplexTree(unittest.TestCase): self.assertTrue(st.find([1])) self.assertTrue(st.find([2])) - 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_mini(self): triangle012 = [0,1,2] edge03 = [0,3] -- cgit v1.2.3