diff options
Diffstat (limited to 'src/cython')
74 files changed, 6398 insertions, 0 deletions
diff --git a/src/cython/CMakeLists.txt b/src/cython/CMakeLists.txt new file mode 100644 index 00000000..998908e7 --- /dev/null +++ b/src/cython/CMakeLists.txt @@ -0,0 +1,146 @@ +cmake_minimum_required(VERSION 2.8) +project(Cython) + +FIND_PROGRAM( PYTHON_PATH python ) +FIND_PROGRAM( CYTHON_PATH cython ) + +if(PYTHON_PATH AND CYTHON_PATH) + find_package(Boost REQUIRED COMPONENTS system REQUIRED) + + if(NOT Boost_FOUND) + message(FATAL_ERROR "NOTICE: This demo requires Boost and will not be compiled.") + else(NOT Boost_FOUND) + + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${Boost_INCLUDE_DIRS}', ") + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'boost_system', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${Boost_LIBRARY_DIRS}', ") + + # Gudhi and CGAL compilation option + if(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") + else(MSVC) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-std=c++11', ") + endif(MSVC) + if(CMAKE_COMPILER_IS_GNUCXX) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") + endif(CMAKE_COMPILER_IS_GNUCXX) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") + endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + if (DEBUG_TRACES) + # For programs to be more verbose + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") + endif() + + find_package(Eigen3 3.1.0) + + if (EIGEN3_FOUND) + # No problem, even if no CGAL found + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${EIGEN3_INCLUDE_DIR}', ") + endif (EIGEN3_FOUND) + + # Copy recursively include, cython and test repositories before packages finding + # Some tests files are removed in case some packages are not found + file(COPY include DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY cython DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY test DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + if (CGAL_FOUND) + if (NOT CGAL_VERSION VERSION_LESS 4.8.1) + # If CGAL_VERSION >= 4.8.1, include subsampling + # CGAL things are done in CGAL_VERSION >= 4.8.0 + set(GUDHI_CYTHON_SUBSAMPLING "include 'cython/subsampling.pyx'") + else (NOT CGAL_VERSION VERSION_LESS 4.8.1) + # Remove alpha complex unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_subsampling.py) + endif (NOT CGAL_VERSION VERSION_LESS 4.8.1) + if (NOT CGAL_VERSION VERSION_LESS 4.8.0) + # If CGAL_VERSION >= 4.8.0, include alpha and tangential complex + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'CGAL', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${CGAL_LIBRARIES_DIR}', ") + # GMP and GMPXX are not required, but if present, CGAL will link with them. + if(GMP_FOUND) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'gmp', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMP_LIBRARIES_DIR}', ") + if(GMPXX_FOUND) + set(GUDHI_CYTHON_EXTRA_COMPILE_ARGS "${GUDHI_CYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") + set(GUDHI_CYTHON_LIBRARIES "${GUDHI_CYTHON_LIBRARIES}'gmpxx', ") + set(GUDHI_CYTHON_LIBRARY_DIRS "${GUDHI_CYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") + endif(GMPXX_FOUND) + endif(GMP_FOUND) + + set(GUDHI_CYTHON_ALPHA_COMPLEX "include 'cython/alpha_complex.pyx'") + set(GUDHI_CYTHON_TANGENTIAL_COMPLEX "include 'cython/tangential_complex.pyx'") + else (NOT CGAL_VERSION VERSION_LESS 4.8.0) + # Remove alpha complex unitary tests + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_alpha_complex.py) + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test/test_tangential_complex.py) + endif (NOT CGAL_VERSION VERSION_LESS 4.8.0) + endif (CGAL_FOUND) + + # Loop on INCLUDE_DIRECTORIES PROPERTY + get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) + foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") + endforeach() + set(GUDHI_CYTHON_INCLUDE_DIRS "${GUDHI_CYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_CYTHON_PATH}/include', ") + + # Generate cythonize_gudhi.py file to cythonize Gudhi + configure_file(cythonize_gudhi.py.in "${CMAKE_CURRENT_BINARY_DIR}/cythonize_gudhi.py" @ONLY) + # Generate gudhi.pyx - Gudhi cython file + configure_file(gudhi.pyx.in "${CMAKE_CURRENT_BINARY_DIR}/gudhi.pyx" @ONLY) + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND python "${CMAKE_CURRENT_BINARY_DIR}/cythonize_gudhi.py" "build_ext" "--inplace") + + add_custom_target(cythonize_gudhi ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/gudhi.so to your PYTHONPATH before using examples") + + # Unitary tests are available through py.test + find_program( PYTEST_PATH py.test ) + if(PYTEST_PATH) + add_test( + NAME gudhi_cython_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PYTEST_PATH}) + set_tests_properties(gudhi_cython_py_test PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}") + endif(PYTEST_PATH) + + # Documentation generation is available through sphinx + find_program( SPHINX_PATH sphinx-build ) + if(SPHINX_PATH) + file(COPY doc DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + # Developper version + file(GLOB GUDHI_DEV_DOC_IMAGES "${CMAKE_SOURCE_DIR}/src/*/doc/*.png") + file(COPY ${GUDHI_DEV_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + # User version + file(GLOB GUDHI_USER_DOC_IMAGES "${CMAKE_SOURCE_DIR}/doc/*/*.png") + file(COPY ${GUDHI_USER_DOC_IMAGES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/img") + # Biblio + file(GLOB GUDHI_BIB_FILES "${CMAKE_SOURCE_DIR}/biblio/*.bib") + file(COPY ${GUDHI_BIB_FILES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + # Cubical complex perseus doc example + file(GLOB GUDHI_CUBICAL_PERSEUS_FILES "${CMAKE_SOURCE_DIR}/data/bitmap/*cubicalcomplexdoc.txt") + file(COPY ${GUDHI_CUBICAL_PERSEUS_FILES} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/points/alphacomplexdoc.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + # Persistence graphical tools examples + file(COPY "${CMAKE_SOURCE_DIR}/data/bitmap/3d_torus.txt" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + file(COPY "${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/doc/") + if (UNIX) + add_custom_target(html + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMAND make html && make doctest) + else (UNIX) + add_custom_target(html + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc + COMMAND make.bat html) + endif (UNIX) + endif(SPHINX_PATH) + endif(NOT Boost_FOUND) +endif(PYTHON_PATH AND CYTHON_PATH) diff --git a/src/cython/CONVENTIONS b/src/cython/CONVENTIONS new file mode 100644 index 00000000..804e97f3 --- /dev/null +++ b/src/cython/CONVENTIONS @@ -0,0 +1,9 @@ +Gudhi is following PEP8 conventions. + +Please refer to: +https://www.python.org/dev/peps/pep-0008/ + +A summary: + - modules (filenames) should have short, all-lowercase names, and they can contain underscores. + - packages (directories) should have short, all-lowercase names, preferably without underscores. + - classes should use the CapWords convention.
\ No newline at end of file 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/cython/alpha_complex.pyx b/src/cython/cython/alpha_complex.pyx new file mode 100644 index 00000000..6b27594a --- /dev/null +++ b/src/cython/cython/alpha_complex.pyx @@ -0,0 +1,118 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Alpha_complex_interface.h" namespace "Gudhi": + cdef cppclass Alpha_complex_interface "Gudhi::alpha_complex::Alpha_complex_interface": + Alpha_complex_interface(vector[vector[double]] points) + # bool from_file is a workaround for cython to find the correct signature + Alpha_complex_interface(string off_file, bool from_file) + vector[double] get_point(int vertex) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + +# AlphaComplex python interface +cdef class AlphaComplex: + """AlphaComplex is a simplicial complex constructed from the finite cells + of a Delaunay Triangulation. + + The filtration value of each simplex is computed as the square of the + circumradius of the simplex if the circumsphere is empty (the simplex is + then said to be Gabriel), and as the minimum of the filtration values of + the codimension 1 cofaces that make it not Gabriel otherwise. + + All simplices that have a filtration value strictly greater than a given + alpha squared value are not inserted into the complex. + + .. note:: + + When Alpha_complex is constructed with an infinite value of alpha, the + complex is a Delaunay complex. + + """ + + cdef Alpha_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=[], off_file=''): + """AlphaComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + """ + + # The real cython constructor + def __cinit__(self, points=[], off_file=''): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Alpha_complex_interface(off_file, True) + else: + print("file " + off_file + " not found.") + else: + self.thisptr = new Alpha_complex_interface(points) + + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if AlphaComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int + :rtype: list of float + :returns: the point. + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + + def create_simplex_tree(self, max_alpha_square=float('inf')): + """ + :param max_alpha_square: The maximum alpha square threshold the + simplices shall not exceed. Default is set to infinity. + :type max_alpha_square: float + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + self.thisptr.create_simplex_tree(simplex_tree.thisptr, max_alpha_square) + return simplex_tree diff --git a/src/cython/cython/cubical_complex.pyx b/src/cython/cython/cubical_complex.pyx new file mode 100644 index 00000000..321fc22a --- /dev/null +++ b/src/cython/cython/cubical_complex.pyx @@ -0,0 +1,177 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": + cdef cppclass Bitmap_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<>": + Bitmap_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Bitmap_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<>>": + Cubical_complex_persistence_interface(Bitmap_cubical_complex_base_interface * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + + +# CubicalComplex python interface +cdef class CubicalComplex: + """The CubicalComplex is an example of a structured complex useful in + computational mathematics (specially rigorous numerics) and image + analysis. + """ + cdef Bitmap_cubical_complex_base_interface * thisptr + + cdef Cubical_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + """CubicalComplex constructor from dimensions and + top_dimensional_cells or from a perseus file style name. + + :param dimensions: A list of number of top dimensional cells. + :type dimensions: list of int + :param top_dimensional_cells: A list of top dimensional cells. + :type top_dimensional_cells: list of double + + Or + + :param perseus_file: A perseus file style name. + :type perseus_file: string + """ + + # The real cython constructor + def __cinit__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + if (dimensions is not None) and (top_dimensional_cells is not None) and (perseus_file is ''): + self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) + elif (dimensions is None) and (top_dimensional_cells is None) and (perseus_file is not ''): + if os.path.isfile(perseus_file): + self.thisptr = new Bitmap_cubical_complex_base_interface(perseus_file) + else: + print("file " + perseus_file + " not found.") + else: + print("CubicalComplex can be constructed from dimensions and " + "top_dimensional_cells or from a perseus file style name.") + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if CubicalComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + if self.thisptr != NULL: + self.pcohptr = new Cubical_complex_persistence_interface(self.thisptr, True) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + return pbn_result diff --git a/src/cython/cython/mini_simplex_tree.pyx b/src/cython/cython/mini_simplex_tree.pyx new file mode 100644 index 00000000..3ba7e853 --- /dev/null +++ b/src/cython/cython/mini_simplex_tree.pyx @@ -0,0 +1,352 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +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<Gudhi::Simplex_tree_options_mini>": + 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) + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Mini_simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_mini>>": + Mini_simplex_tree_persistence_interface(Simplex_tree_interface_mini * st) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + +# MiniSimplexTree python interface +cdef class MiniSimplexTree: + """The simplex tree is an efficient and flexible data structure for + representing general (filtered) simplicial complexes. The data structure + is described in Jean-Daniel Boissonnat and Clément Maria. The Simplex + Tree: An Efficient Data Structure for General Simplicial Complexes. + Algorithmica, pages 1–22, 2014. + + This class is a non-filtered, with keys, and non contiguous vertices + version of the simplex tree. + """ + cdef Simplex_tree_interface_mini * thisptr + + cdef Mini_simplex_tree_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=[], max_alpha_square=float('inf')): + """MiniSimplexTree constructor. + """ + + # The real cython constructor + def __cinit__(self): + self.thisptr = new Simplex_tree_interface_mini() + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if MiniSimplexTree pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def get_filtration(self): + """This function returns the main simplicial complex filtration value. + + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.filtration() + + def filtration(self, simplex): + """This function returns the simplicial complex filtration value for a + given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.simplex_filtration(simplex) + + def set_filtration(self, filtration): + """This function sets the main simplicial complex filtration value. + + :param filtration: The filtration value. + :type filtration: float. + """ + self.thisptr.set_filtration(<double> filtration) + + def initialize_filtration(self): + """This function initializes and sorts the simplicial complex + filtration vector. + + .. note:: + + This function must be launched before persistence, betti_numbers, + persistent_betti_numbers or get_filtered_tree after inserting or + removing simplices. + """ + self.thisptr.initialize_filtration() + + def num_vertices(self): + """This function returns the number of vertices of the simplicial + complex. + + :returns: int -- the simplicial complex number of vertices. + """ + return self.thisptr.num_vertices() + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def set_dimension(self, dimension): + """This function sets the dimension of the simplicial complex. + + :param dimension: The new dimension value. + :type dimension: int. + """ + self.thisptr.set_dimension(<int>dimension) + + def find(self, simplex): + """This function returns if the N-simplex was found in the simplicial + complex or not. + + :param simplex: The N-simplex to find, represented by a list of vertex. + :type simplex: list of int. + :returns: bool -- true if the simplex was found, false otherwise. + """ + 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): + """This function inserts the given N-simplex with the given filtration + value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: bool -- true if the simplex was found, false otherwise. + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, + <double>filtration) + + def get_filtered_tree(self): + """This function returns the tree sorted by increasing filtration + values. + + :returns: list of tuples(simplex, filtration) -- the tree sorted by + increasing filtration values. + """ + 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, dimension): + """This function returns the tree skeleton of a maximum given + dimension. + + :param dimension: The skeleton dimension value. + :type dimension: int. + :returns: list of tuples(simplex, filtration) -- the skeleton tree + of a maximum dimension. + """ + cdef vector[pair[vector[int], double]] coface_tree \ + = self.thisptr.get_skeleton_tree(<int>dimension) + 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): + """This function returns the star tree of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: list of tuples(simplex, filtration) -- the star tree of a + 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, codimension): + """This function returns the coface tree of a given N-simplex with a + given codimension. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :param codimension: The codimension. If codimension = 0, all cofaces + are returned (equivalent of get_star_tree function) + :type codimension: int. + :returns: list of tuples(simplex, filtration) -- the coface tree of a + simplex. + """ + 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, <int>codimension) + 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): + """This function removes a given maximal N-simplex from the simplicial + complex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + """ + self.thisptr.remove_maximal_simplex(simplex) + + def persistence(self, homology_coeff_field=11): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Mini_simplex_tree_persistence_interface(self.thisptr) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, 0) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + else: + print("betti_numbers function requires persistence function" + " to be launched first.") + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + else: + print("persistent_betti_numbers function requires persistence function" + " to be launched first.") + return pbn_result diff --git a/src/cython/cython/periodic_cubical_complex.pyx b/src/cython/cython/periodic_cubical_complex.pyx new file mode 100644 index 00000000..c1b25f31 --- /dev/null +++ b/src/cython/cython/periodic_cubical_complex.pyx @@ -0,0 +1,177 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Cubical_complex_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_base_interface "Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>": + Periodic_cubical_complex_base_interface(vector[unsigned] dimensions, vector[double] top_dimensional_cells) + Periodic_cubical_complex_base_interface(string perseus_file) + int num_simplices() + int dimension() + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Periodic_cubical_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Cubical_complex::Cubical_complex_interface<Gudhi::cubical_complex::Bitmap_cubical_complex_periodic_boundary_conditions_base<double>>>": + Periodic_cubical_complex_persistence_interface(Periodic_cubical_complex_base_interface * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + + +# PeriodicCubicalComplex python interface +cdef class PeriodicCubicalComplex: + """The PeriodicCubicalComplex is an example of a structured complex useful + in computational mathematics (specially rigorous numerics) and image + analysis. + """ + cdef Periodic_cubical_complex_base_interface * thisptr + + cdef Periodic_cubical_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + """PeriodicCubicalComplex constructor from dimensions and + top_dimensional_cells or from a perseus file style name. + + :param dimensions: A list of number of top dimensional cells. + :type dimensions: list of int + :param top_dimensional_cells: A list of top dimensional cells. + :type top_dimensional_cells: list of double + + Or + + :param perseus_file: A perseus file style name. + :type perseus_file: string + """ + + # The real cython constructor + def __cinit__(self, dimensions=None, top_dimensional_cells=None, + perseus_file=''): + if (dimensions is not None) and (top_dimensional_cells is not None) and (perseus_file is ''): + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells) + elif (dimensions is None) and (top_dimensional_cells is None) and (perseus_file is not ''): + if os.path.isfile(perseus_file): + self.thisptr = new Periodic_cubical_complex_base_interface(perseus_file) + else: + print("file " + perseus_file + " not found.") + else: + print("CubicalComplex can be constructed from dimensions and " + "top_dimensional_cells or from a perseus file style name.") + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if PeriodicCubicalComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + if self.thisptr != NULL: + self.pcohptr = new Periodic_cubical_complex_persistence_interface(self.thisptr, True) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + return pbn_result diff --git a/src/cython/cython/persistence_graphical_tools.py b/src/cython/cython/persistence_graphical_tools.py new file mode 100755 index 00000000..2a3d9f63 --- /dev/null +++ b/src/cython/cython/persistence_graphical_tools.py @@ -0,0 +1,152 @@ +import matplotlib.pyplot as plt +import numpy as np + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +def __min_birth_max_death(persistence): + """This function returns (min_birth, max_death) from the persistence. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :returns: (float, float) -- (min_birth, max_death). + """ + # Look for minimum birth date and maximum death date for plot optimisation + max_death = 0 + min_birth = persistence[0][1][0] + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + if float(interval[1][1]) > max_death: + max_death = float(interval[1][1]) + if float(interval[1][0]) > max_death: + max_death = float(interval[1][0]) + if float(interval[1][0]) < min_birth: + min_birth = float(interval[1][0]) + return (min_birth, max_death) + +""" +Only 13 colors for the palette +""" +palette = ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', + '#000000', '#880000', '#008800', '#000088', '#888800', '#880088', + '#008888'] + +def show_palette_values(alpha=0.6): + """This function shows palette color values in function of the dimension. + + :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). + :type alpha: float. + :returns: plot -- An horizontal bar plot of dimensions color. + """ + colors = [] + for color in palette: + colors.append(color) + + y_pos = np.arange(len(palette)) + + plt.barh(y_pos, y_pos + 1, align='center', alpha=alpha, color=colors) + plt.ylabel('Dimension') + plt.title('Dimension palette values') + + plt.show() + +def barcode_persistence(persistence, alpha=0.6): + """This function plots the persistence bar code. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param alpha: alpha value in [0.0, 1.0] for horizontal bars (default is 0.6). + :type alpha: float. + :returns: plot -- An horizontal bar plot of persistence. + """ + (min_birth, max_death) = __min_birth_max_death(persistence) + ind = 0 + delta = ((max_death - min_birth) / 10.0) + # Replace infinity values with max_death + delta for bar code to be more + # readable + infinity = max_death + delta + axis_start = min_birth - delta + # Draw horizontal bars in loop + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + # Finite death case + plt.barh(ind, (interval[1][1] - interval[1][0]), height=0.8, + left = interval[1][0], alpha=alpha, + color = palette[interval[0]]) + else: + # Infinite death case for diagram to be nicer + plt.barh(ind, (infinity - interval[1][0]), height=0.8, + left = interval[1][0], alpha=alpha, + color = palette[interval[0]]) + ind = ind + 1 + + plt.title('Persistence barcode') + # Ends plot on infinity value and starts a little bit before min_birth + plt.axis([axis_start, infinity, 0, ind]) + plt.show() + +def diagram_persistence(persistence, alpha=0.6): + """This function plots the persistence diagram. + + :param persistence: The persistence to plot. + :type persistence: list of tuples(dimension, tuple(birth, death)). + :param alpha: alpha value in [0.0, 1.0] for points and horizontal infinity line (default is 0.6). + :type alpha: float. + :returns: plot -- An diagram plot of persistence. + """ + (min_birth, max_death) = __min_birth_max_death(persistence) + ind = 0 + delta = ((max_death - min_birth) / 10.0) + # Replace infinity values with max_death + delta for diagram to be more + # readable + infinity = max_death + delta + axis_start = min_birth - delta + + # line display of equation : birth = death + x = np.linspace(axis_start, infinity, 1000) + # infinity line and text + plt.plot(x, x, color='k', linewidth=1.0) + plt.plot(x, [infinity] * len(x), linewidth=1.0, color='k', alpha=alpha) + plt.text(axis_start, infinity, r'$\infty$', color='k', alpha=alpha) + + # Draw points in loop + for interval in reversed(persistence): + if float(interval[1][1]) != float('inf'): + # Finite death case + plt.scatter(interval[1][0], interval[1][1], alpha=alpha, + color = palette[interval[0]]) + else: + # Infinite death case for diagram to be nicer + plt.scatter(interval[1][0], infinity, alpha=alpha, + color = palette[interval[0]]) + ind = ind + 1 + + plt.title('Persistence diagram') + plt.xlabel('Birth') + plt.ylabel('Death') + # Ends plot on infinity value and starts a little bit before min_birth + plt.axis([axis_start, infinity, axis_start, infinity + delta]) + plt.show() diff --git a/src/cython/cython/rips_complex.pyx b/src/cython/cython/rips_complex.pyx new file mode 100644 index 00000000..08bd2388 --- /dev/null +++ b/src/cython/cython/rips_complex.pyx @@ -0,0 +1,385 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +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<Gudhi::Simplex_tree_options_full_featured>": + 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) + void graph_expansion(string off_file, int max_dimension, + double max_edge_length, bool from_file) + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Rips_complex_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>": + Rips_complex_persistence_interface(Rips_complex_interface * st) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + +# RipsComplex python interface +cdef class RipsComplex: + """RipsComplex is a simplicial complex constructed from a list of points. + + Each point Pn is inserted as a vertex in the simplicial complex with a + null filtration value. + + A N-simplex represented by the list of vertices Vi, ..., Vj is inserted in + the simplicial complex if all the points Pi, ..., Pj corresponding to the + vertices are within a distance less or equal to a given maximum edge length + value, and if N (dimension of the N-simplex) is less or equal to a given + maximum dimension. + """ + cdef Rips_complex_interface * thisptr + + cdef Rips_complex_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=[], off_file='', max_dimension=3, + max_edge_length=float('inf')): + """RipsComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param max_dimension: Maximum dimension of the complex to be expanded. + :type max_dimension: int + :param max_edge_length: Maximum edge length value (rips radius). + :type max_edge_length: double + """ + + # The real cython constructor + def __cinit__(self, points=[], off_file='', max_dimension=3, + max_edge_length=float('inf')): + self.thisptr = new Rips_complex_interface() + # Constructor from graph expansion + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr.graph_expansion(off_file, max_dimension, + max_edge_length, True) + else: + print("file " + off_file + " not found.") + else: + self.thisptr.graph_expansion(points, max_dimension, + max_edge_length) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if RipsComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def get_filtration(self): + """This function returns the main simplicial complex filtration value. + + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.filtration() + + def filtration(self, simplex): + """This function returns the simplicial complex filtration value for a + given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.simplex_filtration(simplex) + + def set_filtration(self, filtration): + """This function sets the main simplicial complex filtration value. + + :param filtration: The filtration value. + :type filtration: float. + """ + self.thisptr.set_filtration(<double> filtration) + + def initialize_filtration(self): + """This function initializes and sorts the simplicial complex + filtration vector. + + .. note:: + + This function must be launched before persistence, betti_numbers, + persistent_betti_numbers or get_filtered_tree after inserting or + removing simplices. + """ + self.thisptr.initialize_filtration() + + def num_vertices(self): + """This function returns the number of vertices of the simplicial + complex. + + :returns: int -- the simplicial complex number of vertices. + """ + return self.thisptr.num_vertices() + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def set_dimension(self, dimension): + """This function sets the dimension of the simplicial complex. + + :param dimension: The new dimension value. + :type dimension: int. + """ + self.thisptr.set_dimension(<int>dimension) + + def find(self, simplex): + """This function returns if the N-simplex was found in the simplicial + complex or not. + + :param simplex: The N-simplex to find, represented by a list of vertex. + :type simplex: list of int. + :returns: bool -- true if the simplex was found, false otherwise. + """ + 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): + """This function inserts the given N-simplex with the given filtration + value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: bool -- true if the simplex was found, false otherwise. + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, + <double>filtration) + + def get_filtered_tree(self): + """This function returns the tree sorted by increasing filtration + values. + + :returns: list of tuples(simplex, filtration) -- the tree sorted by + increasing filtration values. + """ + 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, dimension): + """This function returns the tree skeleton of a maximum given + dimension. + + :param dimension: The skeleton dimension value. + :type dimension: int. + :returns: list of tuples(simplex, filtration) -- the skeleton tree + of a maximum dimension. + """ + cdef vector[pair[vector[int], double]] coface_tree \ + = self.thisptr.get_skeleton_tree(<int>dimension) + 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): + """This function returns the star tree of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: list of tuples(simplex, filtration) -- the star tree of a + 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, codimension): + """This function returns the coface tree of a given N-simplex with a + given codimension. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :param codimension: The codimension. If codimension = 0, all cofaces + are returned (equivalent of get_star_tree function) + :type codimension: int. + :returns: list of tuples(simplex, filtration) -- the coface tree of a + simplex. + """ + 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, <int>codimension) + 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): + """This function removes a given maximal N-simplex from the simplicial + complex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + """ + self.thisptr.remove_maximal_simplex(simplex) + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :note: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Rips_complex_persistence_interface(self.thisptr) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + else: + print("betti_numbers function requires persistence function" + " to be launched first.") + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + else: + print("persistent_betti_numbers function requires persistence function" + " to be launched first.") + return pbn_result diff --git a/src/cython/cython/simplex_tree.pyx b/src/cython/cython/simplex_tree.pyx new file mode 100644 index 00000000..8f909398 --- /dev/null +++ b/src/cython/cython/simplex_tree.pyx @@ -0,0 +1,361 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp cimport bool + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +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<Gudhi::Simplex_tree_options_full_featured>": + 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) + +cdef extern from "Persistent_cohomology_interface.h" namespace "Gudhi": + cdef cppclass Simplex_tree_persistence_interface "Gudhi::Persistent_cohomology_interface<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>": + Simplex_tree_persistence_interface(Simplex_tree_interface_full_featured * st, bool persistence_dim_max) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] betti_numbers() + vector[int] persistent_betti_numbers(double from_value, double to_value) + +# SimplexTree python interface +cdef class SimplexTree: + """The simplex tree is an efficient and flexible data structure for + representing general (filtered) simplicial complexes. The data structure + is described in Jean-Daniel Boissonnat and Clément Maria. The Simplex + Tree: An Efficient Data Structure for General Simplicial Complexes. + Algorithmica, pages 1–22, 2014. + + This class is a filtered, with keys, and non contiguous vertices version + of the simplex tree. + """ + cdef Simplex_tree_interface_full_featured * thisptr + + cdef Simplex_tree_persistence_interface * pcohptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self): + """SimplexTree constructor. + """ + + # The real cython constructor + def __cinit__(self): + self.thisptr = new Simplex_tree_interface_full_featured() + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + if self.pcohptr != NULL: + del self.pcohptr + + def __is_defined(self): + """Returns true if SimplexTree pointer is not NULL. + """ + return self.thisptr != NULL + + def __is_persistence_defined(self): + """Returns true if Persistence pointer is not NULL. + """ + return self.pcohptr != NULL + + def get_filtration(self): + """This function returns the main simplicial complex filtration value. + + :returns: The simplicial complex filtration value. + :rtype: float + """ + return self.thisptr.filtration() + + def filtration(self, simplex): + """This function returns the simplicial complex filtration value for a + given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The simplicial complex filtration value. + :rtype: float + """ + return self.thisptr.simplex_filtration(simplex) + + def set_filtration(self, filtration): + """This function sets the main simplicial complex filtration value. + + :param filtration: The filtration value. + :type filtration: float. + """ + self.thisptr.set_filtration(<double> filtration) + + def initialize_filtration(self): + """This function initializes and sorts the simplicial complex + filtration vector. + + .. note:: + + This function must be launched before persistence, betti_numbers, + persistent_betti_numbers or get_filtered_tree after inserting or + removing simplices. + """ + self.thisptr.initialize_filtration() + + def num_vertices(self): + """This function returns the number of vertices of the simplicial + complex. + + :returns: The simplicial complex number of vertices. + :rtype: int + """ + return self.thisptr.num_vertices() + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: the simplicial complex number of simplices. + :rtype: int + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: the simplicial complex dimension. + :rtype: int + """ + return self.thisptr.dimension() + + def set_dimension(self, dimension): + """This function sets the dimension of the simplicial complex. + + :param dimension: The new dimension value. + :type dimension: int. + """ + self.thisptr.set_dimension(<int>dimension) + + def find(self, simplex): + """This function returns if the N-simplex was found in the simplicial + complex or not. + + :param simplex: The N-simplex to find, represented by a list of vertex. + :type simplex: list of int. + :returns: true if the simplex was found, false otherwise. + :rtype: bool + """ + 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): + """This function inserts the given N-simplex with the given filtration + value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: true if the simplex was found, false otherwise. + :rtype: bool + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, + <double>filtration) + + def get_filtered_tree(self): + """This function returns the tree sorted by increasing filtration + values. + + :returns: The tree sorted by increasing filtration values. + :rtype: list of tuples(simplex, filtration) + """ + 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, dimension): + """This function returns the tree skeleton of a maximum given + dimension. + + :param dimension: The skeleton dimension value. + :type dimension: int. + :returns: The skeleton tree of a maximum dimension. + :rtype: list of tuples(simplex, filtration) + """ + cdef vector[pair[vector[int], double]] coface_tree \ + = self.thisptr.get_skeleton_tree(<int>dimension) + 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): + """This function returns the star tree of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: The star tree of a simplex. + :rtype: list of tuples(simplex, filtration) + """ + 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, codimension): + """This function returns the coface tree of a given N-simplex with a + given codimension. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :param codimension: The codimension. If codimension = 0, all cofaces + are returned (equivalent of get_star_tree function) + :type codimension: int. + :returns: The coface tree of a simplex. + :rtype: list of tuples(simplex, filtration) + """ + 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, <int>codimension) + 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): + """This function removes a given maximal N-simplex from the simplicial + complex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + """ + self.thisptr.remove_maximal_simplex(simplex) + + def persistence(self, homology_coeff_field=11, min_persistence=0, persistence_dim_max = False): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :returns: The persistence of the simplicial complex. + :rtype: list of pairs(dimension, pair(birth, death)) + """ + if self.pcohptr != NULL: + del self.pcohptr + self.pcohptr = new Simplex_tree_persistence_interface(self.thisptr, persistence_dim_max) + cdef vector[pair[int, pair[double, double]]] persistence_result + if self.pcohptr != NULL: + persistence_result = self.pcohptr.get_persistence(homology_coeff_field, min_persistence) + return persistence_result + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: The Betti numbers ([B0, B1, ..., Bn]). + :rtype: list of int + + :note: betti_numbers function requires persistence function to be + launched first. + """ + cdef vector[int] bn_result + if self.pcohptr != NULL: + bn_result = self.pcohptr.betti_numbers() + else: + print("betti_numbers function requires persistence function" + " to be launched first.") + return bn_result + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: The persistent Betti numbers ([B0, B1, ..., Bn]). + :rtype: list of int + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + cdef vector[int] pbn_result + if self.pcohptr != NULL: + pbn_result = self.pcohptr.persistent_betti_numbers(<double>from_value, <double>to_value) + else: + print("persistent_betti_numbers function requires persistence function" + " to be launched first.") + return pbn_result diff --git a/src/cython/cython/subsampling.pyx b/src/cython/cython/subsampling.pyx new file mode 100644 index 00000000..5ca38099 --- /dev/null +++ b/src/cython/cython/subsampling.pyx @@ -0,0 +1,73 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Subsampling_interface.h" namespace "Gudhi::subsampling": + vector[vector[double]] subsampling_n_farthest_points(vector[vector[double]] points, unsigned nb_points) + vector[vector[double]] subsampling_n_farthest_points(vector[vector[double]] points, unsigned nb_points, unsigned starting_point) + vector[vector[double]] subsampling_n_farthest_points_from_file(string off_file, unsigned nb_points) + vector[vector[double]] subsampling_n_farthest_points_from_file(string off_file, unsigned nb_points, unsigned starting_point) + +def choose_n_farthest_points(points=[], off_file='', nb_points=0, starting_point = ''): + """Subsample by a greedy strategy of iteratively adding the farthest point + from the current chosen point set to the subsampling. + The iteration starts with the landmark `starting point`. + + :param points: The input point set. + :type points: vector[vector[double]]. + + Or + + :param off_file: An OFF file style name. + :type off_file: string + + :param nb_points: Number of points of the subsample. + :type nb_points: unsigned. + :param starting_point: The iteration starts with the landmark `starting \ + point`,which is the index of the poit to start with. If not set, this \ + index is choosen randomly. + :type starting_point: unsigned. + :returns: The subsamplepoint set. + :rtype: vector[vector[double]] + """ + if off_file is not '': + if os.path.isfile(off_file): + if starting_point is '': + return subsampling_n_farthest_points_from_file(off_file, nb_points) + else: + return subsampling_n_farthest_points_from_file(off_file, nb_points, starting_point) + else: + print("file " + off_file + " not found.") + else: + if starting_point is '': + return subsampling_n_farthest_points(points, nb_points) + else: + return subsampling_n_farthest_points(points, nb_points, starting_point) diff --git a/src/cython/cython/tangential_complex.pyx b/src/cython/cython/tangential_complex.pyx new file mode 100644 index 00000000..c0260577 --- /dev/null +++ b/src/cython/cython/tangential_complex.pyx @@ -0,0 +1,162 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libcpp.string cimport string +from libcpp cimport bool +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Tangential_complex_interface.h" namespace "Gudhi": + cdef cppclass Tangential_complex_interface "Gudhi::tangential_complex::Tangential_complex_interface": + Tangential_complex_interface(vector[vector[double]] points) + # bool from_file is a workaround for cython to find the correct signature + Tangential_complex_interface(string off_file, bool from_file) + vector[double] get_point(unsigned vertex) + unsigned number_of_vertices() + unsigned number_of_simplices() + unsigned number_of_inconsistent_simplices() + unsigned number_of_inconsistent_stars() + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree) + void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) + +# TangentialComplex python interface +cdef class TangentialComplex: + """TangentialComplex is a simplicial complex constructed from the finite cells + of a Delaunay Triangulation. + + The filtration value of each simplex is computed as the square of the + circumradius of the simplex if the circumsphere is empty (the simplex is + then said to be Gabriel), and as the minimum of the filtration values of + the codimension 1 cofaces that make it not Gabriel otherwise. + + All simplices that have a filtration value strictly greater than a given + alpha squared value are not inserted into the complex. + + .. note:: + + When Tangential_complex is constructed with an infinite value of alpha, the + complex is a Delaunay complex. + + """ + + cdef Tangential_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=None, off_file=''): + """TangentialComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + + Or + + :param off_file: An OFF file style name. + :type off_file: string + """ + + # The real cython constructor + def __cinit__(self, points=[], off_file=''): + if off_file is not '': + if os.path.isfile(off_file): + self.thisptr = new Tangential_complex_interface(off_file, True) + else: + print("file " + off_file + " not found.") + else: + self.thisptr = new Tangential_complex_interface(points) + + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if TangentialComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def get_point(self, vertex): + """This function returns the point corresponding to a given vertex. + + :param vertex: The vertex. + :type vertex: int. + :returns: list of float -- the point. + """ + cdef vector[double] point = self.thisptr.get_point(vertex) + return point + + def num_vertices(self): + """This function returns the number of vertices. + + :returns: unsigned -- the number of vertices. + """ + return self.thisptr.number_of_vertices() + + def num_simplices(self): + """This function returns the number of simplices. + + :returns: unsigned -- the number of simplices. + """ + return self.thisptr.number_of_simplices() + + def num_inconsistent_simplices(self): + """This function returns the number of inconsistent simplices. + + :returns: unsigned -- the number of inconsistent simplices. + """ + return self.thisptr.number_of_inconsistent_simplices() + + def num_inconsistent_stars(self): + """This function returns the number of inconsistent stars. + + :returns: unsigned -- the number of inconsistent stars. + """ + return self.thisptr.number_of_inconsistent_stars() + + def create_simplex_tree(self): + """This function creates the given simplex tree from the Delaunay + Triangulation. + + :param simplex_tree: The simplex tree to create (must be empty) + :type simplex_tree: SimplexTree + :returns: A simplex tree created from the Delaunay Triangulation. + :rtype: SimplexTree + """ + simplex_tree = SimplexTree() + self.thisptr.create_simplex_tree(simplex_tree.thisptr) + return simplex_tree + + def fix_inconsistencies_using_perturbation(self, max_perturb, time_limit=-1.0): + """Attempts to fix inconsistencies by perturbing the point positions. + :param max_perturb: Maximum length of the translations used by the + perturbation. + :type max_perturb: double + :param time_limit: Time limit in seconds. If -1, no time limit is set. + :type time_limit: double + """ + self.thisptr.fix_inconsistencies_using_perturbation(max_perturb, + time_limit) diff --git a/src/cython/cython/witness_complex.pyx b/src/cython/cython/witness_complex.pyx new file mode 100644 index 00000000..835244cf --- /dev/null +++ b/src/cython/cython/witness_complex.pyx @@ -0,0 +1,322 @@ +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +cdef extern from "Witness_complex_interface.h" namespace "Gudhi": + cdef cppclass Witness_complex_interface "Gudhi::witness_complex::Witness_complex_interface": + Witness_complex_interface(vector[vector[double]] points, int number_of_landmarks) + 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) + vector[double] get_point(int vertex) + vector[pair[int, pair[double, double]]] get_persistence(int homology_coeff_field, double min_persistence) + vector[int] get_betti_numbers() + vector[int] get_persistent_betti_numbers(double from_value, double to_value) + +# WitnessComplex python interface +cdef class WitnessComplex: + """WitnessComplex is a simplicial complex constructed from ... + + """ + + cdef Witness_complex_interface * thisptr + + # Fake constructor that does nothing but documenting the constructor + def __init__(self, points=[], number_of_landmarks=5): + """WitnessComplex constructor. + + :param points: A list of points in d-Dimension. + :type points: list of list of double + :param number_of_landmarks: Number of landmarks to build the + WitnessComplex. + :type number_of_landmarks: int + """ + + # The real cython constructor + def __cinit__(self, points=None, number_of_landmarks=5): + if points is not None: + self.thisptr = new Witness_complex_interface(points, + number_of_landmarks) + + def __dealloc__(self): + if self.thisptr != NULL: + del self.thisptr + + def __is_defined(self): + """Returns true if AlphaComplex pointer is not NULL. + """ + return self.thisptr != NULL + + def get_filtration(self): + """This function returns the main simplicial complex filtration value. + + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.filtration() + + def filtration(self, simplex): + """This function returns the simplicial complex filtration value for a + given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: float -- the simplicial complex filtration value. + """ + return self.thisptr.simplex_filtration(simplex) + + def set_filtration(self, filtration): + """This function sets the main simplicial complex filtration value. + + :param filtration: The filtration value. + :type filtration: float. + """ + self.thisptr.set_filtration(<double> filtration) + + def initialize_filtration(self): + """This function initializes and sorts the simplicial complex + filtration vector. + + .. note:: + + This function must be launched before persistence, betti_numbers, + persistent_betti_numbers or get_filtered_tree after inserting or + removing simplices. + """ + self.thisptr.initialize_filtration() + + def num_vertices(self): + """This function returns the number of vertices of the simplicial + complex. + + :returns: int -- the simplicial complex number of vertices. + """ + return self.thisptr.num_vertices() + + def num_simplices(self): + """This function returns the number of simplices of the simplicial + complex. + + :returns: int -- the simplicial complex number of simplices. + """ + return self.thisptr.num_simplices() + + def dimension(self): + """This function returns the dimension of the simplicial complex. + + :returns: int -- the simplicial complex dimension. + """ + return self.thisptr.dimension() + + def set_dimension(self, dimension): + """This function sets the dimension of the simplicial complex. + + :param dimension: The new dimension value. + :type dimension: int. + """ + self.thisptr.set_dimension(<int>dimension) + + def find(self, simplex): + """This function returns if the N-simplex was found in the simplicial + complex or not. + + :param simplex: The N-simplex to find, represented by a list of vertex. + :type simplex: list of int. + :returns: bool -- true if the simplex was found, false otherwise. + """ + 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): + """This function inserts the given N-simplex with the given filtration + value (default value is '0.0'). + + :param simplex: The N-simplex to insert, represented by a list of + vertex. + :type simplex: list of int. + :param filtration: The filtration value of the simplex. + :type filtration: float. + :returns: bool -- true if the simplex was found, false otherwise. + """ + cdef vector[int] complex + for i in simplex: + complex.push_back(i) + return self.thisptr.insert_simplex_and_subfaces(complex, + <double>filtration) + + def get_filtered_tree(self): + """This function returns the tree sorted by increasing filtration + values. + + :returns: list of tuples(simplex, filtration) -- the tree sorted by + increasing filtration values. + """ + 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, dimension): + """This function returns the tree skeleton of a maximum given + dimension. + + :param dimension: The skeleton dimension value. + :type dimension: int. + :returns: list of tuples(simplex, filtration) -- the skeleton tree + of a maximum dimension. + """ + cdef vector[pair[vector[int], double]] coface_tree \ + = self.thisptr.get_skeleton_tree(<int>dimension) + 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): + """This function returns the star tree of a given N-simplex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :returns: list of tuples(simplex, filtration) -- the star tree of a + 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, codimension): + """This function returns the coface tree of a given N-simplex with a + given codimension. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + :param codimension: The codimension. If codimension = 0, all cofaces + are returned (equivalent of get_star_tree function) + :type codimension: int. + :returns: list of tuples(simplex, filtration) -- the coface tree of a + simplex. + """ + 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, <int>codimension) + 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): + """This function removes a given maximal N-simplex from the simplicial + complex. + + :param simplex: The N-simplex, represented by a list of vertex. + :type simplex: list of int. + """ + self.thisptr.remove_maximal_simplex(simplex) + + def persistence(self, homology_coeff_field=11, min_persistence=0): + """This function returns the persistence of the simplicial complex. + + :param homology_coeff_field: The homology coefficient field. Must be a + prime number + :type homology_coeff_field: int. + :param min_persistence: The minimum persistence value to take into + account (strictly greater than min_persistence). Default value is + 0.0. + Sets min_persistence to -1.0 to see all values. + :type min_persistence: float. + :note: list of pairs(dimension, pair(birth, death)) -- the + persistence of the simplicial complex. + """ + return self.thisptr.get_persistence(homology_coeff_field, min_persistence) + + def betti_numbers(self): + """This function returns the Betti numbers of the simplicial complex. + + :returns: list of int -- The Betti numbers ([B0, B1, ..., Bn]). + + :note: betti_numbers function requires persistence function to be + launched first. + """ + return self.thisptr.get_betti_numbers() + + def persistent_betti_numbers(self, from_value, to_value): + """This function returns the persistent Betti numbers of the + simplicial complex. + + :param from_value: The persistence birth limit to be added in the + numbers (persistent birth <= from_value). + :type from_value: float. + :param to_value: The persistence death limit to be added in the + numbers (persistent death > to_value). + :type to_value: float. + + :returns: list of int -- The persistent Betti numbers ([B0, B1, ..., + Bn]). + + :note: persistent_betti_numbers function requires persistence + function to be launched first. + """ + return self.thisptr.get_persistent_betti_numbers(from_value, to_value) diff --git a/src/cython/cythonize_gudhi.py.in b/src/cython/cythonize_gudhi.py.in new file mode 100644 index 00000000..46d19c2d --- /dev/null +++ b/src/cython/cythonize_gudhi.py.in @@ -0,0 +1,47 @@ +from distutils.core import setup, Extension +from Cython.Build import cythonize + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +gudhi = Extension( + "gudhi", + sources = ['gudhi.pyx',], + language = 'c++', + extra_compile_args=[@GUDHI_CYTHON_EXTRA_COMPILE_ARGS@], + libraries=[@GUDHI_CYTHON_LIBRARIES@], + library_dirs=[@GUDHI_CYTHON_LIBRARY_DIRS@], + include_dirs = [@GUDHI_CYTHON_INCLUDE_DIRS@], +) + +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/doc/Makefile b/src/cython/doc/Makefile new file mode 100644 index 00000000..fc353a37 --- /dev/null +++ b/src/cython/doc/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pouet.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pouet.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/pouet" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pouet" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/src/cython/doc/alpha_complex_ref.rst b/src/cython/doc/alpha_complex_ref.rst new file mode 100644 index 00000000..6a122b09 --- /dev/null +++ b/src/cython/doc/alpha_complex_ref.rst @@ -0,0 +1,10 @@ +============================== +Alpha complex reference manual +============================== + +.. autoclass:: gudhi.AlphaComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.AlphaComplex.__init__ diff --git a/src/cython/doc/alpha_complex_sum.rst b/src/cython/doc/alpha_complex_sum.rst new file mode 100644 index 00000000..af6c087f --- /dev/null +++ b/src/cython/doc/alpha_complex_sum.rst @@ -0,0 +1,23 @@ +===================================== ===================================== ===================================== +:Author: Vincent Rouvreau :Introduced in: GUDHI 1.3.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== +:Requires: CGAL ≥ 4.7.0 Eigen3 +===================================== ===================================== ===================================== + ++-------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | Alpha_complex is a simplicial complex constructed from the finite | +| img/alpha_complex_representation.png | cells of a Delaunay Triangulation. | +| | | +| | The filtration value of each simplex is computed as the square of the| +| | circumradius of the simplex if the circumsphere is empty (the simplex| +| | is then said to be Gabriel), and as the minimum of the filtration | +| | values of the codimension 1 cofaces that make it not Gabriel | +| | otherwise. All simplices that have a filtration value strictly | +| | greater than a given alpha squared value are not inserted into the | +| | complex. | +| | | +| | This package requires having CGAL version 4.7 or higher (4.8.1 is | +| | advised for better perfomances). | ++-------------------------------------------+----------------------------------------------------------------------+ +| :doc:`alpha_complex_user` | :doc:`alpha_complex_ref` | ++-------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/alpha_complex_user.rst b/src/cython/doc/alpha_complex_user.rst new file mode 100644 index 00000000..ed2a470c --- /dev/null +++ b/src/cython/doc/alpha_complex_user.rst @@ -0,0 +1,193 @@ +========================= +Alpha complex user manual +========================= +Definition +---------- + +.. include:: alpha_complex_sum.rst + +Alpha_complex is constructing a :doc:`Simplex_tree <simplex_tree_sum>` using +`Delaunay Triangulation <http://doc.cgal.org/latest/Triangulation/index.html#Chapter_Triangulations>`_ +:cite:`cgal:hdj-t-15b` from `CGAL <http://www.cgal.org/>`_ (the Computational Geometry Algorithms Library +:cite:`cgal:eb-15b`). + +Remarks +^^^^^^^ +When Alpha_complex is constructed with an infinite value of :math:`\alpha`, the complex is a Delaunay complex. + +Example from points +------------------- + +This example builds the Delaunay triangulation from the given points, and initializes the alpha complex with it: + +.. testcode:: + + import gudhi + alpha_complex = gudhi.AlphaComplex(points=[[1, 1], [7, 0], [4, 6], [9, 6], [0, 14], [2, 19], [9, 17]]) + + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=60.0) + result_str = 'Alpha complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +The output is: + +.. testoutput:: + + Alpha complex is of dimension 2 - 25 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 6.25) + ([4, 5], 7.25) + ([0, 2], 8.5) + ([0, 1], 9.25) + ([1, 3], 10.0) + ([1, 2], 11.25) + ([1, 2, 3], 12.5) + ([0, 1, 2], 12.995867768595042) + ([5, 6], 13.25) + ([2, 4], 20.0) + ([4, 6], 22.736686390532547) + ([4, 5, 6], 22.736686390532547) + ([3, 6], 30.25) + ([2, 6], 36.5) + ([2, 3, 6], 36.5) + ([2, 4, 6], 37.24489795918368) + ([0, 4], 59.710743801652896) + ([0, 2, 4], 59.710743801652896) + + +Algorithm +--------- + +Data structure +^^^^^^^^^^^^^^ + +In order to build the alpha complex, first, a Simplex tree is built from the cells of a Delaunay Triangulation. +(The filtration value is set to NaN, which stands for unknown value): + +.. image:: + img/alpha_complex_doc.png + :align: center + :alt: Simplex tree structure construction example + +Filtration value computation algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + **for** i : dimension :math:`\rightarrow` 0 **do** + **for all** :math:`\sigma` of dimension i + **if** filtration(:math:`\sigma`) is NaN **then** + filtration(:math:`\sigma`) = :math:`\alpha^2(\sigma)` + **end if** + + *//propagate alpha filtration value* + + **for all** :math:`\tau` face of :math:`\sigma` + **if** filtration(:math:`\tau`) is not NaN **then** + filtration(:math:`\tau`) = filtration(:math:`\sigma`) + **end if** + **end for** + **end for** + **end for** + + make_filtration_non_decreasing() + + prune_above_filtration() + +Dimension 2 +^^^^^^^^^^^ + +From the example above, it means the algorithm looks into each triangle ([0,1,2], [0,2,4], [1,2,3], ...), +computes the filtration value of the triangle, and then propagates the filtration value as described +here: + +.. image:: + img/alpha_complex_doc_420.png + :align: center + :alt: Filtration value propagation example + +Dimension 1 +^^^^^^^^^^^ + +Then, the algorithm looks into each edge ([0,1], [0,2], [1,2], ...), +computes the filtration value of the edge (in this case, propagation will have no effect). + +Dimension 0 +^^^^^^^^^^^ + +Finally, the algorithm looks into each vertex ([0], [1], [2], [3], [4], [5] and [6]) and +sets the filtration value (0 in case of a vertex - propagation will have no effect). + +Non decreasing filtration values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As the squared radii computed by CGAL are an approximation, it might happen that these alpha squared values do not +quite define a proper filtration (i.e. non-decreasing with respect to inclusion). +We fix that up by calling `Simplex_tree::make_filtration_non_decreasing()` (cf. +`C++ version <http://gudhi.gforge.inria.fr/doc/latest/index.html>`_). + +Prune above given filtration value +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The simplex tree is pruned from the given maximum alpha squared value (cf. `Simplex_tree::prune_above_filtration()` +int he `C++ version <http://gudhi.gforge.inria.fr/doc/latest/index.html>`_). +In the following example, the value is given by the user as argument of the program. + + +Example from OFF file +^^^^^^^^^^^^^^^^^^^^^ + +This example builds the Delaunay triangulation from the points given by an OFF file, and initializes the alpha complex +with it. + + +Then, it is asked to display information about the alpha complex: + +.. testcode:: + + import gudhi + alpha_complex = gudhi.AlphaComplex(off_file='alphacomplexdoc.off') + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=59.0) + result_str = 'Alpha complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ + repr(simplex_tree.num_simplices()) + ' simplices - ' + \ + repr(simplex_tree.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in simplex_tree.get_filtered_tree(): + print(filtered_value) + +the program output is: + +.. testoutput:: + + Alpha complex is of dimension 2 - 23 simplices - 7 vertices. + ([0], 0.0) + ([1], 0.0) + ([2], 0.0) + ([3], 0.0) + ([4], 0.0) + ([5], 0.0) + ([6], 0.0) + ([2, 3], 6.25) + ([4, 5], 7.25) + ([0, 2], 8.5) + ([0, 1], 9.25) + ([1, 3], 10.0) + ([1, 2], 11.25) + ([1, 2, 3], 12.5) + ([0, 1, 2], 12.995867768595042) + ([5, 6], 13.25) + ([2, 4], 20.0) + ([4, 6], 22.736686390532547) + ([4, 5, 6], 22.736686390532547) + ([3, 6], 30.25) + ([2, 6], 36.5) + ([2, 3, 6], 36.5) + ([2, 4, 6], 37.24489795918368) diff --git a/src/cython/doc/biblio.rst b/src/cython/doc/biblio.rst new file mode 100644 index 00000000..b8e733ed --- /dev/null +++ b/src/cython/doc/biblio.rst @@ -0,0 +1,7 @@ +============ +Bibliography +============ + +.. bibliography:: bibliography.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/cgal_citation.rst b/src/cython/doc/cgal_citation.rst new file mode 100644 index 00000000..bbc4ef9e --- /dev/null +++ b/src/cython/doc/cgal_citation.rst @@ -0,0 +1,8 @@ +============== +CGAL citations +============== + +.. + bibliography:: how_to_cite_cgal.bib + :filter: docnames + :style: unsrt diff --git a/src/cython/doc/conf.py b/src/cython/doc/conf.py new file mode 100755 index 00000000..8b42ce37 --- /dev/null +++ b/src/cython/doc/conf.py @@ -0,0 +1,274 @@ +# -*- coding: utf-8 -*- +# +# GUDHI documentation build configuration file, created by +# sphinx-quickstart on Thu Jun 30 09:55:51 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# Path to Gudhi.so from source path +sys.path.insert(0, os.path.abspath('..')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'matplotlib.sphinxext.plot_directive', + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinxcontrib.bibtex', +] + +todo_include_todos = True +# plot option : do not show hyperlinks (Source code, png, hires.png, pdf) +plot_html_show_source_link = False +plot_html_show_formats = False +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'GUDHI' +copyright = u'2016, Vincent Rouvreau' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.4.beta' +# The full version, including alpha/beta/rc tags. +release = '1.4.beta' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GUDHIdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'GUDHI.tex', u'GUDHI Documentation', + u'Vincent Rouvreau', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gudhi', u'GUDHI Documentation', + [u'Vincent Rouvreau'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'GUDHI', u'GUDHI Documentation', + u'Vincent Rouvreau', 'GUDHI', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/src/cython/doc/cubical_complex_ref.rst b/src/cython/doc/cubical_complex_ref.rst new file mode 100644 index 00000000..84aa4223 --- /dev/null +++ b/src/cython/doc/cubical_complex_ref.rst @@ -0,0 +1,9 @@ +Cubical complex reference manual +################################ + +.. autoclass:: gudhi.CubicalComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.CubicalComplex.__init__ diff --git a/src/cython/doc/cubical_complex_sum.rst b/src/cython/doc/cubical_complex_sum.rst new file mode 100644 index 00000000..98e23849 --- /dev/null +++ b/src/cython/doc/cubical_complex_sum.rst @@ -0,0 +1,12 @@ +===================================== ===================================== ===================================== +:Author: Pawel Dlotko :Introduced in: GUDHI 1.3.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | The cubical complex is an example of a structured complex useful in | +| img/Cubical_complex_representation.png | computational mathematics (specially rigorous numerics) and image | +| | analysis. | ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/cubical_complex_user.rst b/src/cython/doc/cubical_complex_user.rst new file mode 100644 index 00000000..2cd85c0a --- /dev/null +++ b/src/cython/doc/cubical_complex_user.rst @@ -0,0 +1,150 @@ +=========================== +Cubical complex user manual +=========================== +Definition +---------- + +===================================== ===================================== ===================================== +:Author: Pawel Dlotko :Introduced in: GUDHI PYTHON 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`cubical_complex_user` | * :doc:`cubical_complex_ref` | +| | * :doc:`periodic_cubical_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + +The cubical complex is an example of a structured complex useful in computational mathematics (specially rigorous +numerics) and image analysis. + +An *elementary interval* is an interval of a form :math:`[n,n+1]`, or :math:`[n,n]`, for :math:`n \in \mathcal{Z}`. +The first one is called *non-degenerate*, while the second one is a *degenerate* interval. A +*boundary of a elementary interval* is a chain :math:`\partial [n,n+1] = [n+1,n+1]-[n,n]` in case of +non-degenerated elementary interval and :math:`\partial [n,n] = 0` in case of degenerate elementary interval. An +*elementary cube* :math:`C` is a product of elementary intervals, :math:`C=I_1 \times \ldots \times I_n`. +*Embedding dimension* of a cube is n, the number of elementary intervals (degenerate or not) in the product. +A *dimension of a cube* :math:`C=I_1 \times ... \times I_n` is the number of non degenerate elementary +intervals in the product. A *boundary of a cube* :math:`C=I_1 \times \ldots \times I_n` is a chain obtained +in the following way: + +.. math:: + + \partial C = (\partial I_1 \times \ldots \times I_n) + (I_1 \times \partial I_2 \times \ldots \times I_n) + + \ldots + (I_1 \times I_2 \times \ldots \times \partial I_n). + +A *cubical complex* :math:`\mathcal{K}` is a collection of cubes closed under operation of taking boundary +(i.e. boundary of every cube from the collection is in the collection). A cube :math:`C` in cubical complex +:math:`\mathcal{K}` is *maximal* if it is not in a boundary of any other cube in :math:`\mathcal{K}`. A +*support* of a cube :math:`C` is the set in :math:`\mathbb{R}^n` occupied by :math:`C` (:math:`n` is the embedding +dimension of :math:`C`). + +Cubes may be equipped with a filtration values in which case we have filtered cubical complex. All the cubical +complexes considered in this implementation are filtered cubical complexes (although, the range of a filtration may +be a set of two elements). + +For further details and theory of cubical complexes, please consult :cite:`kaczynski2004computational` as well as the +following paper :cite:`peikert2012topological`. + +Data structure. +--------------- + +The implementation of Cubical complex provides a representation of complexes that occupy a rectangular region in +:math:`\mathbb{R}^n`. This extra assumption allows for a memory efficient way of storing cubical complexes in a form +of so called bitmaps. Let +:math:`R = [b_1,e_1] \times \ldots \times [b_n,e_n]`, for :math:`b_1,...b_n,e_1,...,e_n \in \mathbb{Z}`, +:math:`b_i \leq d_i` be the considered rectangular region and let :math:`\mathcal{K}` be a filtered +cubical complex having the rectangle :math:`R` as its support. Note that the structure of the coordinate system gives +a way a lexicographical ordering of cells of :math:`\mathcal{K}`. This ordering is a base of the presented +bitmap-based implementation. In this implementation, the whole cubical complex is stored as a vector of the values +of filtration. This, together with dimension of :math:`\mathcal{K}` and the sizes of :math:`\mathcal{K}` in all +directions, allows to determine, dimension, neighborhood, boundary and coboundary of every cube +:math:`C \in \mathcal{K}`. + +.. image:: + img/Cubical_complex_representation.png + :align: center + :alt: Cubical complex. + +Note that the cubical complex in the figure above is, in a natural way, a product of one dimensional cubical +complexes in :math:`\mathbb{R}`. The number of all cubes in each direction is equal :math:`2n+1`, where :math:`n` is +the number of maximal cubes in the considered direction. Let us consider a cube at the position :math:`k` in the +bitmap. +Knowing the sizes of the bitmap, by a series of modulo operation, we can determine which elementary intervals are +present in the product that gives the cube :math:`C`. In a similar way, we can compute boundary and the coboundary of +each cube. Further details can be found in the literature. + +Input Format. +------------- + +In the current implantation, filtration is given at the maximal cubes, and it is then extended by the lower star +filtration to all cubes. There are a number of constructors that can be used to construct cubical complex by users +who want to use the code directly. They can be found in the :doc:`cubical_complex_ref`. +Currently one input from a text file is used. It uses a format used already in +`Perseus software <http://www.sas.upenn.edu/~vnanda/perseus/>`_ by Vidit Nanda. +Below we are providing a description of the format. The first line contains a number d begin the dimension of the +bitmap (2 in the example below). Next d lines are the numbers of top dimensional cubes in each dimensions (3 and 3 +in the example below). Next, in lexicographical order, the filtration of top dimensional cubes is given (1 4 6 8 +20 4 7 6 5 in the example below). + +.. image:: + img/exampleBitmap.png + :align: center + :alt: Example of a input data. + +The input file for the following complex is: + +.. literalinclude:: cubicalcomplexdoc.txt + +.. centered:: cubicalcomplexdoc.txt + +.. testcode:: + + import gudhi + cubical_complex = gudhi.CubicalComplex(perseus_file='cubicalcomplexdoc.txt') + result_str = 'Cubical complex is of dimension ' + repr(cubical_complex.dimension()) + ' - ' + \ + repr(cubical_complex.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Cubical complex is of dimension 2 - 49 simplices. + +Periodic boundary conditions. +----------------------------- + +Often one would like to impose periodic boundary conditions to the cubical complex (cf. +:doc:`periodic_cubical_complex_ref`). +Let :math:`I_1\times ... \times I_n` be a box that is decomposed with a cubical complex :math:`\mathcal{K}`. +Imposing periodic boundary conditions in the direction i, means that the left and the right side of a complex +:math:`\mathcal{K}` are considered the same. In particular, if for a bitmap :math:`\mathcal{K}` periodic boundary +conditions are imposed in all directions, then complex :math:`\mathcal{K}` became n-dimensional torus. One can use +various constructors from the file Bitmap_cubical_complex_periodic_boundary_conditions_base.h to construct cubical +complex with periodic boundary conditions. One can also use Perseus style input files. To indicate periodic boundary +conditions in a given direction, then number of top dimensional cells in this direction have to be multiplied by -1. +For instance: + +.. literalinclude:: periodiccubicalcomplexdoc.txt + +.. centered:: periodiccubicalcomplexdoc.txt + +Indicate that we have imposed periodic boundary conditions in the direction x, but not in the direction y. + +.. testcode:: + + import gudhi + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='periodiccubicalcomplexdoc.txt') + result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ + repr(periodic_cc.num_simplices()) + ' simplices.' + print(result_str) + +the program output is: + +.. testoutput:: + + Periodic cubical complex is of dimension 2 - 42 simplices. + +Examples. +--------- + +End user programs are available in cython/example/ folder. diff --git a/src/cython/doc/img/graphical_tools_representation.png b/src/cython/doc/img/graphical_tools_representation.png Binary files differnew file mode 100644 index 00000000..9759f7ba --- /dev/null +++ b/src/cython/doc/img/graphical_tools_representation.png diff --git a/src/cython/doc/index.rst b/src/cython/doc/index.rst new file mode 100644 index 00000000..91e31ff6 --- /dev/null +++ b/src/cython/doc/index.rst @@ -0,0 +1,73 @@ +.. GUDHI documentation master file, created by + sphinx-quickstart on Thu Jun 30 09:55:51 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +GUDHI's documentation +##################### + +.. image:: img/Gudhi_banner.png + :align: center + +Introduction +************ + +The Gudhi library (Geometry Understanding in Higher Dimensions) is a generic +open source C++ library for Computational Topology and Topological Data +Analysis (`TDA <https://en.wikipedia.org/wiki/Topological_data_analysis>`_). +The GUDHI library intends to help the development of new algorithmic solutions +in TDA and their transfer to applications. It provides robust, efficient, +flexible and easy to use implementations of state-of-the-art algorithms and +data structures. + +The current release of the GUDHI library includes: + +* Data structures to represent, construct and manipulate simplicial complexes. +* Algorithms to compute persistent homology and multi-field persistent homology. +* Simplication of simplicial complexes by edge contraction. + +All data-structures are generic and several of their aspects can be +parameterized via template classes. We refer to :cite:`gudhilibrary_ICMS14` +for a detailed description of the design of the library. + +Data structures +*************** + +Alpha complex +============= + +.. include:: alpha_complex_sum.rst + +Cubical complex +=============== + +.. include:: cubical_complex_sum.rst + +Simplex tree +============ + +.. include:: simplex_tree_sum.rst + +Tangential complex +================== + +.. include:: tangential_complex_sum.rst + +Witness complex +=============== + +.. include:: witness_complex_sum.rst + + +Toolbox +******* + +Persistence cohomology +====================== + +.. include:: persistent_cohomology_sum.rst + +Persistence graphical tools +=========================== + +.. include:: persistence_graphical_tools_sum.rst diff --git a/src/cython/doc/make.bat b/src/cython/doc/make.bat new file mode 100644 index 00000000..656c0105 --- /dev/null +++ b/src/cython/doc/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pouet.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pouet.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+:end
diff --git a/src/cython/doc/periodic_cubical_complex_ref.rst b/src/cython/doc/periodic_cubical_complex_ref.rst new file mode 100644 index 00000000..c6190a1b --- /dev/null +++ b/src/cython/doc/periodic_cubical_complex_ref.rst @@ -0,0 +1,9 @@ +Periodic cubical complex reference manual +######################################### + +.. autoclass:: gudhi.PeriodicCubicalComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.PeriodicCubicalComplex.__init__ diff --git a/src/cython/doc/persistence_graphical_tools_ref.rst b/src/cython/doc/persistence_graphical_tools_ref.rst new file mode 100644 index 00000000..a12021c4 --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_ref.rst @@ -0,0 +1,8 @@ +============================================ +Persistence graphical tools reference manual +============================================ + +.. autofunction:: gudhi.__min_birth_max_death +.. autofunction:: gudhi.show_palette_values +.. autofunction:: gudhi.barcode_persistence +.. autofunction:: gudhi.diagram_persistence diff --git a/src/cython/doc/persistence_graphical_tools_sum.rst b/src/cython/doc/persistence_graphical_tools_sum.rst new file mode 100644 index 00000000..a4ee4398 --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_sum.rst @@ -0,0 +1,13 @@ +===================================== ===================================== ===================================== +:Author: Vincent Rouvreau :Introduced in: GUDHI 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== +:Requires: Matplotlib Numpy +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | These graphical tools comes on top of persistence results and allows | +| img/graphical_tools_representation.png | the user to build easily barcode and persistence diagram. | +| | | ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`persistence_graphical_tools_user` | :doc:`persistence_graphical_tools_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/persistence_graphical_tools_user.rst b/src/cython/doc/persistence_graphical_tools_user.rst new file mode 100644 index 00000000..43c695bf --- /dev/null +++ b/src/cython/doc/persistence_graphical_tools_user.rst @@ -0,0 +1,46 @@ +======================================= +Persistence graphical tools user manual +======================================= +Definition +---------- +.. include:: persistence_graphical_tools_sum.rst + + +Show palette values +------------------- + +This function is useful to show the color palette values of dimension: + + +.. testcode:: + + import gudhi + gudhi.show_palette_values(alpha=1.0) + +Show persistence as a barcode +----------------------------- + +This function can display the persistence result as a barcode: + +.. testcode:: + + import gudhi + + periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='3d_torus.txt') + diag = periodic_cc.persistence() + gudhi.barcode_persistence(diag) + + +Show persistence as a diagram +----------------------------- + +This function can display the persistence result as a diagram: + +.. testcode:: + + import gudhi + + alpha_complex = gudhi.AlphaComplex(off_file='tore3D_300.off') + simplex_tree = alpha_complex.create_simplex_tree() + diag = simplex_tree.persistence() + gudhi.diagram_persistence(diag) diff --git a/src/cython/doc/persistent_cohomology_sum.rst b/src/cython/doc/persistent_cohomology_sum.rst new file mode 100644 index 00000000..b306b3d4 --- /dev/null +++ b/src/cython/doc/persistent_cohomology_sum.rst @@ -0,0 +1,28 @@ +===================================== ===================================== ===================================== +:Author: Clément Maria :Introduced in: GUDHI 1.0.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | The theory of homology consists in attaching to a topological space | +| img/3DTorus_poch.png | a sequence of (homology) groups, capturing global topological | +| | features like connected components, holes, cavities, etc. Persistent | +| | homology studies the evolution -- birth, life and death -- of these | +| | features when the topological space is changing. Consequently, the | +| | theory is essentially composed of three elements: topological spaces,| +| | their homology groups and an evolution scheme. | +| | | +| | Computation of persistent cohomology using the algorithm of | +| | :cite:`DBLP:journals/dcg/SilvaMV11` and | +| | :cite:`DBLP:journals/corr/abs-1208-5018` and the Compressed | +| | Annotation Matrix implementation of | +| | :cite:`DBLP:conf/esa/BoissonnatDM13`. | +| | | ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`alpha_complex_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`witness_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/persistent_cohomology_user.rst b/src/cython/doc/persistent_cohomology_user.rst new file mode 100644 index 00000000..33b19ce2 --- /dev/null +++ b/src/cython/doc/persistent_cohomology_user.rst @@ -0,0 +1,104 @@ +================================= +Persistent cohomology user manual +================================= +Definition +---------- +===================================== ===================================== ===================================== +:Author: Clément Maria :Introduced in: GUDHI PYTHON 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`persistent_cohomology_user` | Please refer to each data structure that contains persistence | +| | feature for reference: | +| | | +| | * :doc:`alpha_complex_ref` | +| | * :doc:`cubical_complex_ref` | +| | * :doc:`simplex_tree_ref` | +| | * :doc:`witness_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ + + +Computation of persistent cohomology using the algorithm of :cite:`DBLP:journals/dcg/SilvaMV11` and +:cite:`DBLP:journals/corr/abs-1208-5018` and the Compressed Annotation Matrix implementation of +:cite:`DBLP:conf/esa/BoissonnatDM13`. + +The theory of homology consists in attaching to a topological space a sequence of (homology) groups, capturing global +topological features like connected components, holes, cavities, etc. Persistent homology studies the evolution -- +birth, life and death -- of these features when the topological space is changing. Consequently, the theory is +essentially composed of three elements: + +* topological spaces +* their homology groups +* an evolution scheme. + +Topological Spaces +------------------ + +Topological spaces are represented by simplicial complexes. +Let :math:`V = \{1, \cdots ,|V|\}` be a set of *vertices*. +A *simplex* :math:`\sigma` is a subset of vertices :math:`\sigma \subseteq V`. +A *simplicial complex* :math:`\mathbf{K}` on :math:`V` is a collection of simplices :math:`\{\sigma\}`, +:math:`\sigma \subseteq V`, such that :math:`\tau \subseteq \sigma \in \mathbf{K} \Rightarrow \tau \in \mathbf{K}`. +The dimension :math:`n=|\sigma|-1` of :math:`\sigma` is its number of elements minus 1. +A *filtration* of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. + +Homology +-------- + +For a ring :math:`\mathcal{R}`, the group of *n-chains*, denoted :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})`, of +:math:`\mathbf{K}` is the group of formal sums of n-simplices with :math:`\mathcal{R}` coefficients. The +*boundary operator* is a linear operator +:math:`\partial_n: \mathbf{C}_n(\mathbf{K},\mathcal{R}) \rightarrow \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R})` +such that :math:`\partial_n \sigma = \partial_n [v_0, \cdots , v_n] = \sum_{i=0}^n (-1)^{i}[v_0,\cdots ,\widehat{v_i}, \cdots,v_n]`, +where :math:`\widehat{v_i}` means :math:`v_i` is omitted from the list. The chain groups form a sequence: + +.. math:: + + \cdots \ \ \mathbf{C}_n(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_n\ } + \mathbf{C}_{n-1}(\mathbf{K},\mathcal{R}) \xrightarrow{\partial_{n-1}} \cdots \xrightarrow{\ \partial_2 \ } + \mathbf{C}_1(\mathbf{K},\mathcal{R}) \xrightarrow{\ \partial_1 \ } \mathbf{C}_0(\mathbf{K},\mathcal{R}) + +of finitely many groups :math:`\mathbf{C}_n(\mathbf{K},\mathcal{R})` and homomorphisms :math:`\partial_n`, indexed by +the dimension :math:`n \geq 0`. The boundary operators satisfy the property :math:`\partial_n \circ \partial_{n+1}=0` +for every :math:`n > 0` and we define the homology groups: + +.. math:: + + \mathbf{H}_n(\mathbf{K},\mathcal{R}) = \ker \partial_n / \mathrm{im} \ \partial_{n+1} + +We refer to :cite:`Munkres-elementsalgtop1984` for an introduction to homology +theory and to :cite:`DBLP:books/daglib/0025666` for an introduction to persistent homology. + +Indexing Scheme +--------------- + +"Changing" a simplicial complex consists in applying a simplicial map. An *indexing scheme* is a directed graph +together with a traversal order, such that two consecutive nodes in the graph are connected by an arrow (either forward +or backward). +The nodes represent simplicial complexes and the directed edges simplicial maps. + +From the computational point of view, there are two types of indexing schemes of interest in persistent homology: + +* linear ones + :math:`\bullet \longrightarrow \bullet \longrightarrow \cdots \longrightarrow \bullet \longrightarrow \bullet` + in persistent homology :cite:`DBLP:journals/dcg/ZomorodianC05`, +* zigzag ones + :math:`\bullet \longrightarrow \bullet \longleftarrow \cdots \longrightarrow \bullet \longleftarrow \bullet` + in zigzag persistent homology :cite:`DBLP:journals/focm/CarlssonS10`. + +These indexing schemes have a natural left-to-right traversal order, and we describe them with ranges and iterators. +In the current release of the Gudhi library, only the linear case is implemented. + +In the following, we consider the case where the indexing scheme is induced by a filtration. + +Ordering the simplices by increasing filtration values (breaking ties so as a simplex appears after its subsimplices of +same filtration value) provides an indexing scheme. + +Examples +-------- + +We provide several example files: run these examples with -h for details on their use. + +.. todo:: + examples for persistence diff --git a/src/cython/doc/pyplots/barcode_persistence.py b/src/cython/doc/pyplots/barcode_persistence.py new file mode 100755 index 00000000..95bbd343 --- /dev/null +++ b/src/cython/doc/pyplots/barcode_persistence.py @@ -0,0 +1,5 @@ +import gudhi + +periodic_cc = gudhi.PeriodicCubicalComplex(perseus_file='../3d_torus.txt') +diag = periodic_cc.persistence() +gudhi.barcode_persistence(diag) diff --git a/src/cython/doc/pyplots/diagram_persistence.py b/src/cython/doc/pyplots/diagram_persistence.py new file mode 100755 index 00000000..b006b0bf --- /dev/null +++ b/src/cython/doc/pyplots/diagram_persistence.py @@ -0,0 +1,5 @@ +import gudhi + +alpha_complex = gudhi.AlphaComplex(off_file='../tore3D_300.off') +diag = alpha_complex.persistence() +gudhi.diagram_persistence(diag) diff --git a/src/cython/doc/pyplots/show_palette_values.py b/src/cython/doc/pyplots/show_palette_values.py new file mode 100755 index 00000000..e72a55fd --- /dev/null +++ b/src/cython/doc/pyplots/show_palette_values.py @@ -0,0 +1,2 @@ +import gudhi +gudhi.show_palette_values(alpha=1.0) diff --git a/src/cython/doc/simplex_tree_ref.rst b/src/cython/doc/simplex_tree_ref.rst new file mode 100644 index 00000000..6d196843 --- /dev/null +++ b/src/cython/doc/simplex_tree_ref.rst @@ -0,0 +1,10 @@ +============================= +Simplex tree reference manual +============================= + +.. autoclass:: gudhi.SimplexTree + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.SimplexTree.__init__ diff --git a/src/cython/doc/simplex_tree_sum.rst b/src/cython/doc/simplex_tree_sum.rst new file mode 100644 index 00000000..0f34888a --- /dev/null +++ b/src/cython/doc/simplex_tree_sum.rst @@ -0,0 +1,13 @@ +===================================== ===================================== ===================================== +:Author: Clément Maria :Introduced in: GUDHI 1.0.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++-------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | The simplex tree is an efficient and flexible data structure for | +| img/Simplex_tree_representation.png | representing general (filtered) simplicial complexes. | +| | | +| | The data structure is described in | +| | :cite:`boissonnatmariasimplextreealgorithmica` | ++-------------------------------------------+----------------------------------------------------------------------+ +| :doc:`simplex_tree_user` | :doc:`simplex_tree_ref` | ++-------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/simplex_tree_user.rst b/src/cython/doc/simplex_tree_user.rst new file mode 100644 index 00000000..3a00f1ac --- /dev/null +++ b/src/cython/doc/simplex_tree_user.rst @@ -0,0 +1,67 @@ +======================== +Simplex tree user manual +======================== +Definition +---------- + +.. include:: simplex_tree_sum.rst + +A simplicial complex :math:`\mathbf{K}` on a set of vertices :math:`V = \{1, \cdots ,|V|\}` is a collection of +simplices :math:`\{\sigma\}`, :math:`\sigma \subseteq V` such that +:math:`\tau \subseteq \sigma \in \mathbf{K} \rightarrow \tau \in \mathbf{K}`. The dimension :math:`n=|\sigma|-1` of +:math:`\sigma` is its number of elements minus `1`. + +A filtration of a simplicial complex is a function :math:`f:\mathbf{K} \rightarrow \mathbb{R}` satisfying +:math:`f(\tau)\leq f(\sigma)` whenever :math:`\tau \subseteq \sigma`. Ordering the simplices by increasing filtration +values (breaking ties so as a simplex appears after its subsimplices of same filtration value) provides an indexing +scheme. + + +Implementation +-------------- + +There are two implementation of complexes. The first on is the Simplex_tree data structure. +The simplex tree is an efficient and flexible data structure for representing general (filtered) simplicial complexes. +The data structure is described in :cite`boissonnatmariasimplextreealgorithmica`. + +The second one is the Hasse_complex. The Hasse complex is a data structure representing explicitly all co-dimension 1 +incidence relations in a complex. It is consequently faster when accessing the boundary of a simplex, but is less +compact and harder to construct from scratch. + +Example +------- + +.. testcode:: + + import gudhi + st = gudhi.SimplexTree() + if st.insert([0, 1]): + print("[0, 1] inserted") + if st.insert([0, 1, 2], filtration=4.0): + print("[0, 1, 2] inserted") + if st.find([0, 1]): + print("[0, 1] found") + print("num_vertices=", st.num_vertices()) + print("num_simplices=", st.num_simplices()) + print("skeleton_tree(2) =") + for sk_value in st.get_skeleton_tree(2): + print(sk_value) + + +The output is: + +.. testoutput:: + + [0, 1] inserted + [0, 1, 2] inserted + [0, 1] found + ('num_vertices=', 3) + ('num_simplices=', 7) + 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) diff --git a/src/cython/doc/tangential_complex_ref.rst b/src/cython/doc/tangential_complex_ref.rst new file mode 100644 index 00000000..35589475 --- /dev/null +++ b/src/cython/doc/tangential_complex_ref.rst @@ -0,0 +1,10 @@ +=================================== +Tangential complex reference manual +=================================== + +.. autoclass:: gudhi.TangentialComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.TangentialComplex.__init__ diff --git a/src/cython/doc/tangential_complex_sum.rst b/src/cython/doc/tangential_complex_sum.rst new file mode 100644 index 00000000..4e358a7b --- /dev/null +++ b/src/cython/doc/tangential_complex_sum.rst @@ -0,0 +1,16 @@ +===================================== ===================================== ===================================== +:Author: Clément Jamin :Introduced in: GUDHI 1.4.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== +:Requires: CGAL ≥ 4.8.0 Eigen3 +===================================== ===================================== ===================================== + ++-------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | A Tangential Delaunay complex is a simplicial complex designed to | +| img/tc_examples.png | reconstruct a :math:`k`-dimensional manifold embedded in :math:`d`- | +| | dimensional Euclidean space. The input is a point sample coming from | +| | an unknown manifold. The running time depends only linearly on the | +| | extrinsic dimension :math:`d` and exponentially on the intrinsic | +| | dimension :math:`k`. | ++-------------------------------------------+----------------------------------------------------------------------+ +| :doc:`tangential_complex_user` | :doc:`tangential_complex_ref` | ++-------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/tangential_complex_user.rst b/src/cython/doc/tangential_complex_user.rst new file mode 100644 index 00000000..30c97b8f --- /dev/null +++ b/src/cython/doc/tangential_complex_user.rst @@ -0,0 +1,192 @@ +============================== +Tangential complex user manual +============================== +.. include:: tangential_complex_sum.rst + +Definition +---------- + +A Tangential Delaunay complex is a simplicial complex designed to reconstruct a +:math:`k`-dimensional smooth manifold embedded in :math:`d`-dimensional +Euclidean space. The input is a point sample coming from an unknown manifold, +which means that the points lie close to a structure of "small" intrinsic +dimension. The running time depends only linearly on the extrinsic dimension +:math:`d` and exponentially on the intrinsic dimension :math:`k`. + +An extensive description of the Tangential complex can be found in +:cite:`tangentialcomplex2014`). + +What is a Tangential Complex? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Let us start with the description of the Tangential complex of a simple +example, with :math:`k = 1` and :math:`d = 2`. The input data is 4 points +:math:`P` located on a curve embedded in 2D. + +.. figure:: img/tc_example_01.png + :alt: The input + :figclass: align-center + The input + +For each point :math:`p`, estimate its tangent subspace :math:`T_p` (e.g. +using PCA). + +.. figure:: img/tc_example_02.png + :alt: The estimated normals + :figclass: align-center + The estimated normals + +Let us add the Voronoi diagram of the points in orange. For each point +:math:`p`, construct its star in the Delaunay triangulation of :math:`P` +restricted to :math:`T_p`. + +.. figure:: img/tc_example_03.png + :alt: The Voronoi diagram + :figclass: align-center + The Voronoi diagram + +The Tangential Delaunay complex is the union of those stars. + +In practice, neither the ambient Voronoi diagram nor the ambient Delaunay +triangulation is computed. Instead, local :math:`k`-dimensional regular +triangulations are computed with a limited number of points as we only need the +star of each point. More details can be found in :cite:`tangentialcomplex2014`. + +Inconsistencies +^^^^^^^^^^^^^^^ +Inconsistencies between the stars can occur. An inconsistency occurs when a +simplex is not in the star of all its vertices. + +Let us take the same example. + +.. figure:: img/tc_example_07_before.png + :alt: Before + :figclass: align-center + Before + +Let us slightly move the tangent subspace :math:`T_q` + +.. figure:: img/tc_example_07_after.png + :alt: After + :figclass: align-center + After + +Now, the star of :math:`Q` contains :math:`QP`, but the star of :math:`P` does +not contain :math:`QP`. We have an inconsistency. + +.. figure:: img/tc_example_08.png + :alt: After + :figclass: align-center + After + +One way to solve inconsistencies is to randomly perturb the positions of the +points involved in an inconsistency. In the current implementation, this +perturbation is done in the tangent subspace of each point. The maximum +perturbation radius is given as a parameter to the constructor. + +In most cases, we recommend to provide a point set where the minimum distance +between any two points is not too small. This can be achieved using the +functions provided by the Subsampling module. Then, a good value to start with +for the maximum perturbation radius would be around half the minimum distance +between any two points. The Example with perturbation below shows an example of +such a process. + +In most cases, this process is able to dramatically reduce the number of +inconsistencies, but is not guaranteed to succeed. + +Output +^^^^^^ +The result of the computation is exported as a Simplex_tree. It is the union of +the stars of all the input points. A vertex in the Simplex Tree is the index of +the point in the range provided by the user. The point corresponding to a +vertex can also be obtained through the Tangential_complex::get_point function. +Note that even if the positions of the points are perturbed, their original +positions are kept (e.g. Tangential_complex::get_point returns the original +position of the point). + +The result can be obtained after the computation of the Tangential complex +itself and/or after the perturbation process. + + +Simple example +-------------- + +This example builds the Tangential complex of point set read in an OFF file. + +.. testcode:: + + import gudhi + tc = gudhi.TangentialComplex(off_file='alphacomplexdoc.off') + result_str = 'Tangential contains ' + repr(tc.num_simplices()) + \ + ' simplices - ' + repr(tc.num_vertices()) + ' vertices.' + print(result_str) + + st = tc.create_simplex_tree() + result_str = 'Simplex tree is of dimension ' + repr(st.dimension()) + \ + ' - ' + repr(st.num_simplices()) + ' simplices - ' + \ + repr(st.num_vertices()) + ' vertices.' + print(result_str) + for filtered_value in st.get_filtered_tree(): + print(filtered_value) + +The output is: + +.. testoutput:: + + Tangential contains 18 simplices - 7 vertices. + Simplex tree is of dimension 2 - 25 simplices - 7 vertices. + ([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) + ([3], 0.0) + ([1, 3], 0.0) + ([2, 3], 0.0) + ([1, 2, 3], 0.0) + ([4], 0.0) + ([0, 4], 0.0) + ([2, 4], 0.0) + ([0, 2, 4], 0.0) + ([5], 0.0) + ([4, 5], 0.0) + ([6], 0.0) + ([2, 6], 0.0) + ([3, 6], 0.0) + ([2, 3, 6], 0.0) + ([4, 6], 0.0) + ([2, 4, 6], 0.0) + ([5, 6], 0.0) + ([4, 5, 6], 0.0) + + +Example with perturbation +------------------------- + +This example builds the Tangential complex of a point set, then tries to solve +inconsistencies by perturbing the positions of points involved in inconsistent +simplices. + +.. testcode:: + + import gudhi + tc = gudhi.TangentialComplex(points=[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]) + result_str = 'Tangential contains ' + repr(tc.num_vertices()) + ' vertices.' + print(result_str) + + if tc.num_inconsistent_simplices() > 0: + print('Tangential contains inconsistencies.') + + tc.fix_inconsistencies_using_perturbation(10, 60) + if tc.num_inconsistent_simplices() == 0: + print('Inconsistencies has been fixed.') + +The output is: + +.. testoutput:: + + Tangential contains 4 vertices. + Tangential contains inconsistencies. + Inconsistencies has been fixed. diff --git a/src/cython/doc/todos.rst b/src/cython/doc/todos.rst new file mode 100644 index 00000000..78972a4c --- /dev/null +++ b/src/cython/doc/todos.rst @@ -0,0 +1,5 @@ +========== +To be done +========== + +.. todolist:: diff --git a/src/cython/doc/witness_complex_ref.rst b/src/cython/doc/witness_complex_ref.rst new file mode 100644 index 00000000..c78760cb --- /dev/null +++ b/src/cython/doc/witness_complex_ref.rst @@ -0,0 +1,10 @@ +================================ +Witness complex reference manual +================================ + +.. autoclass:: gudhi.WitnessComplex + :members: + :undoc-members: + :show-inheritance: + + .. automethod:: gudhi.WitnessComplex.__init__ diff --git a/src/cython/doc/witness_complex_sum.rst b/src/cython/doc/witness_complex_sum.rst new file mode 100644 index 00000000..005a5a41 --- /dev/null +++ b/src/cython/doc/witness_complex_sum.rst @@ -0,0 +1,25 @@ +===================================== ===================================== ===================================== +:Author: Siargey Kachanovich :Introduced in: GUDHI 1.3.0 :Copyright: GPL v3 +===================================== ===================================== ===================================== + ++---------------------------------------------+----------------------------------------------------------------------+ +| .. image:: | Witness complex :math:`Wit(W,L)` is a simplicial complex defined on | +| img/Witness_complex_representation.png | two sets of points in :math:`\mathbb{R}^D`:Wit(W,L)` is a simplicial | +| | complex defined on two sets of points in :math:`\mathbb{R}^D`: | +| | | +| | * :math:`W` set of **witnesses** and | +| | * :math:`L \subseteq W` set of **landmarks**. | +| | | +| | The simplices are based on landmarks and a simplex belongs to the | +| | witness complex if and only if it is witnessed, that is: | +| | | +| | :math:`\sigma \subset L` is witnessed if there exists a point | +| | :math:`w \in W` such that w is closer to the vertices of | +| | :math:`\sigma` than other points in :math:`L` and all of its faces | +| | are witnessed as well. | +| | | +| | The data structure is described in | +| | :cite:`boissonnatmariasimplextreealgorithmica`. | ++---------------------------------------------+----------------------------------------------------------------------+ +| :doc:`witness_complex_user` | :doc:`witness_complex_ref` | ++---------------------------------------------+----------------------------------------------------------------------+ diff --git a/src/cython/doc/witness_complex_user.rst b/src/cython/doc/witness_complex_user.rst new file mode 100644 index 00000000..604c7357 --- /dev/null +++ b/src/cython/doc/witness_complex_user.rst @@ -0,0 +1,31 @@ +=========================== +Witness complex user manual +=========================== +Definition +---------- + +.. include:: witness_complex_sum.rst + +Implementation +-------------- + +The principal class of this module is Gudhi::Witness_complex. + +In both cases, the constructor for this class takes a {witness}x{closest_landmarks} table, where each row represents a +witness and consists of landmarks sorted by distance to this witness. + +.. todo:: + This table can be constructed by two additional classes Landmark_choice_by_furthest_point and + Landmark_choice_by_random_point also included in the module. + +.. figure:: + img/bench_Cy8.png + :align: center + + Running time as function on number of landmarks. + +.. figure:: + img/bench_sphere.png + :align: center + + Running time as function on number of witnesses for |L|=300. diff --git a/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py new file mode 100755 index 00000000..ae03aa67 --- /dev/null +++ b/src/cython/example/alpha_complex_diagram_persistence_from_off_file_example.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='AlphaComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/alpha_complex_diagram_persistence_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off -a 0.6' + '- Constructs a alpha complex with the ' + 'points from the given OFF file.') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-a", "--max_alpha_square", type=float, default=0.5) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("AlphaComplex creation from points read in a OFF file") + + message = "AlphaComplex with max_edge_length=" + repr(args.max_alpha_square) + print(message) + + alpha_complex = gudhi.AlphaComplex(off_file=args.file) + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=args.max_alpha_square) + + message = "Number of simplices=" + repr(simplex_tree.num_simplices()) + print(message) + + diag = simplex_tree.persistence() + + print("betti_numbers()=") + print(simplex_tree.betti_numbers()) + + if args.no_diagram == False: + gudhi.diagram_persistence(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/alpha_complex_from_points_example.py b/src/cython/example/alpha_complex_from_points_example.py new file mode 100755 index 00000000..ae21c711 --- /dev/null +++ b/src/cython/example/alpha_complex_from_points_example.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +from gudhi import AlphaComplex, SimplexTree + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("AlphaComplex creation from points") +alpha_complex = AlphaComplex(points=[[0, 0], [1, 0], [0, 1], [1, 1]]) +simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=60.0) + +if simplex_tree.find([0, 1]): + print("[0, 1] Found !!") +else: + print("[0, 1] Not found...") + +if simplex_tree.find([4]): + print("[4] Found !!") +else: + print("[4] Not found...") + +if simplex_tree.insert([0, 1, 2], filtration=4.0): + print("[0, 1, 2] Inserted !!") +else: + print("[0, 1, 2] Not inserted...") + +if simplex_tree.insert([0, 1, 4], filtration=4.0): + print("[0, 1, 4] Inserted !!") +else: + print("[0, 1, 4] Not inserted...") + +if simplex_tree.find([4]): + print("[4] Found !!") +else: + print("[4] Not found...") + +print("dimension=", simplex_tree.dimension()) +print("filtered_tree=", simplex_tree.get_filtered_tree()) +print("star([0])=", simplex_tree.get_star_tree([0])) +print("coface([0], 1)=", simplex_tree.get_coface_tree([0], 1)) + +print("point[0]=", alpha_complex.get_point(0)) +print("point[5]=", alpha_complex.get_point(5)) diff --git a/src/cython/example/gudhi_graphical_tools_example.py b/src/cython/example/gudhi_graphical_tools_example.py new file mode 100755 index 00000000..40558bee --- /dev/null +++ b/src/cython/example/gudhi_graphical_tools_example.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import gudhi + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("Show palette colors values for dimension") + +gudhi.show_palette_values() + +print("#####################################################################") +print("Show barcode persistence example") + +persistence = [(2, (1.0, float('inf'))), (1, (1.4142135623730951, float('inf'))), + (1, (1.4142135623730951, float('inf'))), (0, (0.0, float('inf'))), + (0, (0.0, 1.0)), (0, (0.0, 1.0)), (0, (0.0, 1.0))] +gudhi.barcode_persistence(persistence) + +print("#####################################################################") +print("Show diagram persistence example") + +gudhi.diagram_persistence(persistence) diff --git a/src/cython/example/mini_simplex_tree_example.py b/src/cython/example/mini_simplex_tree_example.py new file mode 100755 index 00000000..7b65a9d6 --- /dev/null +++ b/src/cython/example/mini_simplex_tree_example.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +import gudhi + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("MiniSimplexTree creation from insertion") + +""" Complex to build. + 1 3 + o---o + /X\ / + o---o o + 2 0 4 +""" + +triangle012 = [0, 1, 2] +edge03 = [0, 3] +edge13 = [1, 3] +vertex4 = [4] +mini_st = gudhi.MiniSimplexTree() +mini_st.insert(triangle012) +mini_st.insert(edge03) +mini_st.insert(edge13) +mini_st.insert(vertex4) + +# FIXME: Remove this line +mini_st.set_dimension(2) + +# initialize_filtration required before plain_homology +mini_st.initialize_filtration() + +print("persistence(homology_coeff_field=2)=") +print(mini_st.persistence(homology_coeff_field=2)) + +edge02 = [0, 2] +if mini_st.find(edge02): + # Only coface is 012 + print("coface(edge02,1)=", mini_st.get_coface_tree(edge02, 1)) + +if mini_st.get_coface_tree(triangle012, 1) == []: + # Precondition: Check the simplex has no coface before removing it. + mini_st.remove_maximal_simplex(triangle012) + +# initialize_filtration required after removing +mini_st.initialize_filtration() + +print("filtered_tree after triangle012 removal =", mini_st.get_filtered_tree()) diff --git a/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py b/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py new file mode 100755 index 00000000..a9545ee9 --- /dev/null +++ b/src/cython/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +def is_file_perseus(file): + num_lines = open(file).read().count('\n') + try: + f = open(file) + num_dim = int(f.readline()) + coeff = 1 + for dim in range(0, num_dim): + try: + line = int(f.readline()) + coeff *= abs(line) + except ValueError: + return False + if num_lines == (1 + num_dim + coeff): + return True + else: + return False + except ValueError: + return False + +parser = argparse.ArgumentParser(description='Periodic cubical complex from a ' + 'perseus file style name.', + epilog='Example: ' + './periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py' + ' -f ../data/bitmap/CubicalTwoSphere.txt') + +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument('--no-barcode', default=False, action='store_true' , help='Flag for not to display the barcodes') + +args = parser.parse_args() + +if is_file_perseus(args.file): + print("#####################################################################") + print("PeriodicCubicalComplex creation") + periodic_cubical_complex = gudhi.PeriodicCubicalComplex(perseus_file=args.file) + + print("persistence(homology_coeff_field=3, min_persistence=0)=") + diag = periodic_cubical_complex.persistence(homology_coeff_field=3, min_persistence=0) + print(diag) + + print("betti_numbers()=") + print(periodic_cubical_complex.betti_numbers()) + if args.no_barcode == False: + gudhi.barcode_persistence(diag) +else: + print(args.file, "is not a valid perseus style file") diff --git a/src/cython/example/random_cubical_complex_persistence_example.py b/src/cython/example/random_cubical_complex_persistence_example.py new file mode 100755 index 00000000..1c55f777 --- /dev/null +++ b/src/cython/example/random_cubical_complex_persistence_example.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import gudhi +import numpy +import argparse +import operator + + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='Random cubical complex.', + epilog='Example: ' + './random_cubical_complex_persistence_example.py' + ' 10 10 10 - Constructs a random cubical ' + 'complex in a dimension [10, 10, 10] (aka. ' + '1000 random top dimensional cells).') +parser.add_argument('dimension', type=int, nargs="*", + help='Cubical complex dimensions') + +args = parser.parse_args() +dimension_multiplication = reduce(operator.mul, args.dimension, 1) + +if dimension_multiplication > 1: + print("#####################################################################") + print("CubicalComplex creation") + cubical_complex = gudhi.CubicalComplex(dimensions=args.dimension, + top_dimensional_cells = numpy.random.rand(dimension_multiplication)) + + print("persistence(homology_coeff_field=2, min_persistence=0)=") + print(cubical_complex.persistence(homology_coeff_field=2, min_persistence=0)) + + print("betti_numbers()=") + print(cubical_complex.betti_numbers())
\ No newline at end of file diff --git a/src/cython/example/rips_complex_diagram_persistence_with_pandas_interface_example.py b/src/cython/example/rips_complex_diagram_persistence_with_pandas_interface_example.py new file mode 100755 index 00000000..bcf2fbcb --- /dev/null +++ b/src/cython/example/rips_complex_diagram_persistence_with_pandas_interface_example.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +import gudhi +import pandas +import argparse + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("RipsComplex creation from points read in a file") + +parser = argparse.ArgumentParser(description='RipsComplex creation from ' + 'points read in a file.', + epilog='Example: ' + 'example/rips_complex_diagram_persistence_with_pandas_interface_example.py ' + '../data/2000_random_points_on_3D_Torus.csv ' + '- Constructs a rips complex with the ' + 'points from the given file. File format ' + 'is X1, X2, ..., Xn') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument("-e", "--max-edge-length", type=float, default=0.5) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +points = pandas.read_csv(args.file, header=None) + +message = "RipsComplex with max_edge_length=" + repr(args.max_edge_length) +print(message) + +rips_complex = gudhi.RipsComplex(points=points.values, + max_dimension=len(points.values[0]), max_edge_length=args.max_edge_length) + +message = "Number of simplices=" + repr(rips_complex.num_simplices()) +print(message) + +rips_complex.initialize_filtration() +diag = rips_complex.persistence() + +print("betti_numbers()=") +print(rips_complex.betti_numbers()) + +if args.no_diagram == False: + gudhi.diagram_persistence(diag) diff --git a/src/cython/example/rips_complex_from_points_example.py b/src/cython/example/rips_complex_from_points_example.py new file mode 100755 index 00000000..1a22d8e3 --- /dev/null +++ b/src/cython/example/rips_complex_from_points_example.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +import gudhi + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +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/rips_persistence_diagram.py b/src/cython/example/rips_persistence_diagram.py new file mode 100755 index 00000000..fddea298 --- /dev/null +++ b/src/cython/example/rips_persistence_diagram.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import gudhi + +"""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): Marc Glisse + + Copyright (C) 2016 INRIA + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Marc Glisse" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +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) + +diag = rips.persistence(homology_coeff_field=2, min_persistence=0) +print("diag=", diag) + +gudhi.diagram_persistence(diag) diff --git a/src/cython/example/simplex_tree_example.py b/src/cython/example/simplex_tree_example.py new file mode 100755 index 00000000..bf5f17a2 --- /dev/null +++ b/src/cython/example/simplex_tree_example.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import gudhi + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("SimplexTree creation from insertion") + +st = gudhi.SimplexTree() + +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)) diff --git a/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py new file mode 100755 index 00000000..be4c40be --- /dev/null +++ b/src/cython/example/tangential_complex_plain_homology_from_off_file_example.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import gudhi +import argparse + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +parser = argparse.ArgumentParser(description='TangentialComplex creation from ' + 'points read in a OFF file.', + epilog='Example: ' + 'example/tangential_complex_plain_homology_from_off_file_example.py ' + '-f ../data/points/tore3D_300.off' + '- Constructs a tangential complex with the ' + 'points from the given OFF file') +parser.add_argument("-f", "--file", type=str, required=True) +parser.add_argument('--no-diagram', default=False, action='store_true' , help='Flag for not to display the diagrams') + +args = parser.parse_args() + +with open(args.file, 'r') as f: + first_line = f.readline() + if (first_line == 'OFF\n') or (first_line == 'nOFF\n'): + print("#####################################################################") + print("TangentialComplex creation from points read in a OFF file") + + tc = gudhi.TangentialComplex(off_file=args.file) + st = tc.create_simplex_tree() + + message = "Number of simplices=" + repr(st.num_simplices()) + print(message) + + diag = st.persistence(persistence_dim_max = True) + + print("betti_numbers()=") + print(st.betti_numbers()) + + if args.no_diagram == False: + gudhi.diagram_persistence(diag) + else: + print(args.file, "is not a valid OFF file") + + f.close() diff --git a/src/cython/example/witness_complex_from_file_example.py b/src/cython/example/witness_complex_from_file_example.py new file mode 100755 index 00000000..82a5b49a --- /dev/null +++ b/src/cython/example/witness_complex_from_file_example.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +import gudhi +import pandas +import argparse + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +print("#####################################################################") +print("WitnessComplex creation from points read in a file") + +parser = argparse.ArgumentParser(description='WitnessComplex creation from ' + 'points read in a file.', + epilog='Example: ' + 'example/witness_complex_from_file_example.py' + ' data/2000_random_points_on_3D_Torus.csv ' + '- Constructs a witness complex with the ' + 'points from the given file. File format ' + 'is X1, X2, ..., Xn') +parser.add_argument('file', type=argparse.FileType('r')) +args = parser.parse_args() + +points = pandas.read_csv(args.file, header=None) + +print("WitnessComplex with number_of_landmarks=100") + +witness_complex = gudhi.WitnessComplex(points=points.values, + number_of_landmarks=100) + +witness_complex.initialize_filtration() + +print("filtered_tree=", witness_complex.get_filtered_tree()) diff --git a/src/cython/gudhi.pyx.in b/src/cython/gudhi.pyx.in new file mode 100644 index 00000000..60f4c30b --- /dev/null +++ b/src/cython/gudhi.pyx.in @@ -0,0 +1,36 @@ +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + +include "cython/simplex_tree.pyx" +include "cython/mini_simplex_tree.pyx" +include "cython/rips_complex.pyx" +include "cython/cubical_complex.pyx" +include "cython/periodic_cubical_complex.pyx" +include "cython/persistence_graphical_tools.py" +include "cython/witness_complex.pyx" +@GUDHI_CYTHON_ALPHA_COMPLEX@ +@GUDHI_CYTHON_SUBSAMPLING@ +@GUDHI_CYTHON_TANGENTIAL_COMPLEX@ diff --git a/src/cython/include/Alpha_complex_interface.h b/src/cython/include/Alpha_complex_interface.h new file mode 100644 index 00000000..81761c77 --- /dev/null +++ b/src/cython/include/Alpha_complex_interface.h @@ -0,0 +1,85 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef ALPHA_COMPLEX_INTERFACE_H +#define ALPHA_COMPLEX_INTERFACE_H + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Alpha_complex.h> +#include <CGAL/Epick_d.h> + +#include "Simplex_tree_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> + +namespace Gudhi { + +namespace alpha_complex { + +class Alpha_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + typedef typename Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair<Simplex_handle, bool> Insertion_result; + using Simplex = std::vector<Vertex_handle>; + using Filtered_complex = std::pair<Simplex, Filtration_value>; + using Complex_tree = std::vector<Filtered_complex>; + + typedef typename Simplex_tree<>::Simplex_key Simplex_key; + + public: + Alpha_complex_interface(std::vector<std::vector<double>>&points) { + alpha_complex_ = new Alpha_complex<Dynamic_kernel>(points); + } + + Alpha_complex_interface(std::string off_file_name, bool from_file = true) { + alpha_complex_ = new Alpha_complex<Dynamic_kernel>(off_file_name); + } + + std::vector<double> get_point(int vh) { + std::vector<double> vd; + try { + Point_d ph = alpha_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } catch (std::out_of_range outofrange) { + // std::out_of_range is thrown in case not found. Other exceptions must be re-thrown + } + return vd; + } + + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square) { + alpha_complex_->create_complex(*simplex_tree, max_alpha_square); + simplex_tree->initialize_filtration(); + } + + private: + Alpha_complex<Dynamic_kernel>* alpha_complex_; +}; + +} // namespace alpha_complex + +} // namespace Gudhi + +#endif // ALPHA_COMPLEX_INTERFACE_H diff --git a/src/cython/include/Cubical_complex_interface.h b/src/cython/include/Cubical_complex_interface.h new file mode 100644 index 00000000..5d17ff6b --- /dev/null +++ b/src/cython/include/Cubical_complex_interface.h @@ -0,0 +1,58 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef CUBICAL_COMPLEX_INTERFACE_H +#define CUBICAL_COMPLEX_INTERFACE_H + +#include <gudhi/Bitmap_cubical_complex.h> +#include <gudhi/Bitmap_cubical_complex_base.h> +#include <gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h> + +#include <vector> +#include <utility> // std::pair +#include <iostream> + +namespace Gudhi { + +namespace cubical_complex { + +template<typename CubicalComplexOptions = Bitmap_cubical_complex_base<double>> +class Cubical_complex_interface : public Bitmap_cubical_complex<CubicalComplexOptions> { + public: + + Cubical_complex_interface(const std::vector<unsigned>& dimensions, + const std::vector<double>& top_dimensional_cells) + : Bitmap_cubical_complex<CubicalComplexOptions>(dimensions, top_dimensional_cells) { + } + + Cubical_complex_interface(const std::string& perseus_file) + : Bitmap_cubical_complex<CubicalComplexOptions>(perseus_file.c_str()) { + } + +}; + +} // namespace cubical_complex + +} // namespace Gudhi + +#endif // CUBICAL_COMPLEX_INTERFACE_H + diff --git a/src/cython/include/Persistent_cohomology_interface.h b/src/cython/include/Persistent_cohomology_interface.h new file mode 100644 index 00000000..1ff0e09b --- /dev/null +++ b/src/cython/include/Persistent_cohomology_interface.h @@ -0,0 +1,96 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef PERSISTENT_COHOMOLOGY_INTERFACE_H +#define PERSISTENT_COHOMOLOGY_INTERFACE_H + +#include <gudhi/Persistent_cohomology.h> + +#include <vector> +#include <utility> // for std::pair + +namespace Gudhi { + +template<class FilteredComplex> +class Persistent_cohomology_interface : public +persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp> { + private: + + /* + * Compare two intervals by dimension, then by length. + */ + struct cmp_intervals_by_dim_then_length { + + explicit cmp_intervals_by_dim_then_length(FilteredComplex * sc) + : sc_(sc) { } + + template<typename Persistent_interval> + bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) { + if (sc_->dimension(get < 0 > (p1)) == sc_->dimension(get < 0 > (p2))) + return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1)) + > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2))); + else + return (sc_->dimension(get < 0 > (p1)) > sc_->dimension(get < 0 > (p2))); + } + FilteredComplex* sc_; + }; + + public: + + Persistent_cohomology_interface(FilteredComplex* stptr) + : persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>(*stptr), + stptr_(stptr) { } + + Persistent_cohomology_interface(FilteredComplex* stptr, bool persistence_dim_max) + : persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>(*stptr, + persistence_dim_max), + stptr_(stptr) { } + + std::vector<std::pair<int, std::pair<double, double>>> get_persistence(int homology_coeff_field, double min_persistence) { + persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::init_coefficients(homology_coeff_field); + persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::compute_persistent_cohomology(min_persistence); + + // Custom sort and output persistence + cmp_intervals_by_dim_then_length cmp(stptr_); + auto persistent_pairs = persistent_cohomology::Persistent_cohomology<FilteredComplex, persistent_cohomology::Field_Zp>::get_persistent_pairs(); + std::sort(std::begin(persistent_pairs), std::end(persistent_pairs), cmp); + + std::vector<std::pair<int, std::pair<double, double>>> persistence; + for (auto pair : persistent_pairs) { + persistence.push_back(std::make_pair(stptr_->dimension(get<0>(pair)), + std::make_pair(stptr_->filtration(get<0>(pair)), + stptr_->filtration(get<1>(pair))))); + } + return persistence; + + } + + private: + // A copy + FilteredComplex* stptr_; + +}; + +} // namespace Gudhi + +#endif // PERSISTENT_COHOMOLOGY_INTERFACE_H + diff --git a/src/cython/include/Simplex_tree_interface.h b/src/cython/include/Simplex_tree_interface.h new file mode 100644 index 00000000..8e9dd966 --- /dev/null +++ b/src/cython/include/Simplex_tree_interface.h @@ -0,0 +1,157 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef SIMPLEX_TREE_INTERFACE_H +#define SIMPLEX_TREE_INTERFACE_H + +#include <gudhi/graph_simplicial_complex.h> +#include <gudhi/distance_functions.h> +#include <gudhi/Simplex_tree.h> +#include <gudhi/Points_off_io.h> + +#include "Persistent_cohomology_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> + +namespace Gudhi { + +template<typename SimplexTreeOptions = Simplex_tree_options_full_featured> +class Simplex_tree_interface : public Simplex_tree<SimplexTreeOptions> { + public: + typedef typename Simplex_tree<SimplexTreeOptions>::Simplex_handle Simplex_handle; + typedef typename std::pair<Simplex_handle, bool> Insertion_result; + using Simplex = std::vector<Vertex_handle>; + using Filtered_complex = std::pair<Simplex, Filtration_value>; + using Complex_tree = std::vector<Filtered_complex>; + + public: + + bool find_simplex(const Simplex& vh) { + return (Simplex_tree<SimplexTreeOptions>::find(vh) != Simplex_tree<SimplexTreeOptions>::null_simplex()); + } + + bool insert_simplex_and_subfaces(const Simplex& complex, Filtration_value filtration = 0) { + Insertion_result result = Simplex_tree<SimplexTreeOptions>::insert_simplex_and_subfaces(complex, filtration); + Simplex_tree<SimplexTreeOptions>::initialize_filtration(); + return (result.second); + } + + Filtration_value simplex_filtration(const Simplex& complex) { + return Simplex_tree<SimplexTreeOptions>::filtration(Simplex_tree<SimplexTreeOptions>::find(complex)); + } + + void remove_maximal_simplex(const Simplex& complex) { + Simplex_tree<SimplexTreeOptions>::remove_maximal_simplex(Simplex_tree<SimplexTreeOptions>::find(complex)); + Simplex_tree<SimplexTreeOptions>::initialize_filtration(); + } + + Complex_tree get_filtered_tree() { + Complex_tree filtered_tree; + for (auto f_simplex : Simplex_tree<SimplexTreeOptions>::filtration_simplex_range()) { + Simplex simplex; + for (auto vertex : Simplex_tree<SimplexTreeOptions>::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + filtered_tree.push_back(std::make_pair(simplex, Simplex_tree<SimplexTreeOptions>::filtration(f_simplex))); + } + return filtered_tree; + + } + + Complex_tree get_skeleton_tree(int dimension) { + Complex_tree skeleton_tree; + for (auto f_simplex : Simplex_tree<SimplexTreeOptions>::skeleton_simplex_range(dimension)) { + Simplex simplex; + for (auto vertex : Simplex_tree<SimplexTreeOptions>::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + skeleton_tree.push_back(std::make_pair(simplex, Simplex_tree<SimplexTreeOptions>::filtration(f_simplex))); + } + return skeleton_tree; + } + + Complex_tree get_star_tree(const Simplex& complex) { + Complex_tree star_tree; + for (auto f_simplex : Simplex_tree<SimplexTreeOptions>::star_simplex_range(Simplex_tree<SimplexTreeOptions>::find(complex))) { + Simplex simplex; + for (auto vertex : Simplex_tree<SimplexTreeOptions>::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + star_tree.push_back(std::make_pair(simplex, Simplex_tree<SimplexTreeOptions>::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<SimplexTreeOptions>::cofaces_simplex_range(Simplex_tree<SimplexTreeOptions>::find(complex), dimension)) { + Simplex simplex; + for (auto vertex : Simplex_tree<SimplexTreeOptions>::simplex_vertex_range(f_simplex)) { + simplex.insert(simplex.begin(), vertex); + } + coface_tree.push_back(std::make_pair(simplex, Simplex_tree<SimplexTreeOptions>::filtration(f_simplex))); + } + return coface_tree; + } + + void graph_expansion(std::vector<std::vector<double>>&points, int max_dimension, double max_edge_length) { + Graph_t prox_graph = compute_proximity_graph(points, max_edge_length, euclidean_distance<std::vector<double>>); + Simplex_tree<SimplexTreeOptions>::insert_graph(prox_graph); + Simplex_tree<SimplexTreeOptions>::expansion(max_dimension); + Simplex_tree<SimplexTreeOptions>::initialize_filtration(); + } + + void graph_expansion(std::string& off_file_name, int max_dimension, double max_edge_length, bool from_file=true) { + Gudhi::Points_off_reader<std::vector <double>> off_reader(off_file_name); + // Check the read operation was correct + if (!off_reader.is_valid()) { + std::cerr << "Unable to read file " << off_file_name << std::endl; + } else { + std::vector<std::vector <double>> points = off_reader.get_point_cloud(); + Graph_t prox_graph = compute_proximity_graph(points, max_edge_length, + euclidean_distance<std::vector<double>>); + Simplex_tree<SimplexTreeOptions>::insert_graph(prox_graph); + Simplex_tree<SimplexTreeOptions>::expansion(max_dimension); + Simplex_tree<SimplexTreeOptions>::initialize_filtration(); + } + } + + void create_persistence(Gudhi::Persistent_cohomology_interface<Simplex_tree<SimplexTreeOptions>>* pcoh) { + pcoh = new Gudhi::Persistent_cohomology_interface<Simplex_tree<SimplexTreeOptions>>(*this); + } + +}; + +struct Simplex_tree_options_mini : Simplex_tree_options_full_featured { + // Not doing persistence, so we don't need those + static const bool store_key = true; + 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/include/Subsampling_interface.h b/src/cython/include/Subsampling_interface.h new file mode 100644 index 00000000..12c48012 --- /dev/null +++ b/src/cython/include/Subsampling_interface.h @@ -0,0 +1,79 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef SUBSAMPLING_INTERFACE_H +#define SUBSAMPLING_INTERFACE_H + +#include <gudhi/choose_n_farthest_points.h> +#include <gudhi/Points_off_io.h> +#include <CGAL/Epick_d.h> + +#include <vector> +#include <iostream> + +namespace Gudhi { + +namespace subsampling { + +using Subsampling_dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; +using Subsampling_point_d = Subsampling_dynamic_kernel::Point_d; +using Subsampling_ft = Subsampling_dynamic_kernel::FT; + +std::vector<std::vector<double>> subsampling_n_farthest_points(std::vector<std::vector<double>>& points, unsigned nb_points) { + std::vector<Subsampling_point_d> input, output; + for (auto point : points) + input.push_back(Subsampling_point_d(point.size(), point.begin(), point.end())); + std::vector<std::vector<double>> landmarks; + Subsampling_dynamic_kernel k; + choose_n_farthest_points(k, points, nb_points, std::back_inserter(landmarks)); + + return landmarks; +} + +std::vector<std::vector<double>> subsampling_n_farthest_points(std::vector<std::vector<double>>& points, unsigned nb_points, unsigned starting_point) { + std::vector<Subsampling_point_d> input, output; + for (auto point : points) + input.push_back(Subsampling_point_d(point.size(), point.begin(), point.end())); + std::vector<std::vector<double>> landmarks; + Subsampling_dynamic_kernel k; + choose_n_farthest_points(k, points, nb_points, starting_point, std::back_inserter(landmarks)); + + return landmarks; +} + +std::vector<std::vector<double>> subsampling_n_farthest_points_from_file(std::string& off_file, unsigned nb_points) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_n_farthest_points(points, nb_points); +} + +std::vector<std::vector<double>> subsampling_n_farthest_points_from_file(std::string& off_file, unsigned nb_points, unsigned starting_point) { + Gudhi::Points_off_reader<std::vector<double>> off_reader(off_file); + std::vector<std::vector<double>> points = off_reader.get_point_cloud(); + return subsampling_n_farthest_points(points, nb_points, starting_point); +} +} // namespace subsampling + +} // namespace Gudhi + +#endif // SUBSAMPLING_INTERFACE_H + diff --git a/src/cython/include/Tangential_complex_interface.h b/src/cython/include/Tangential_complex_interface.h new file mode 100644 index 00000000..9da32757 --- /dev/null +++ b/src/cython/include/Tangential_complex_interface.h @@ -0,0 +1,124 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef TANGENTIAL_COMPLEX_INTERFACE_H +#define TANGENTIAL_COMPLEX_INTERFACE_H + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Tangential_complex.h> +#include <gudhi/Points_off_io.h> +#include <CGAL/Epick_d.h> + +#include "Simplex_tree_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> + +namespace Gudhi { + +namespace tangential_complex { + +class Tangential_complex_interface { + using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Point_d = Dynamic_kernel::Point_d; + typedef typename Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair<Simplex_handle, bool> Insertion_result; + using Simplex = std::vector<Vertex_handle>; + using Filtered_complex = std::pair<Simplex, Filtration_value>; + using Complex_tree = std::vector<Filtered_complex>; + using TC = Tangential_complex<Dynamic_kernel, CGAL::Dynamic_dimension_tag, CGAL::Parallel_tag>; + + public: + Tangential_complex_interface(std::vector<std::vector<double>>&points) { + Dynamic_kernel k; + unsigned intrisic_dim = 0; + if (points.size() > 0) + intrisic_dim = points[0].size() - 1; + + tangential_complex_ = new TC(points, intrisic_dim, k); + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + Tangential_complex_interface(std::string off_file_name, bool from_file = true) { + Gudhi::Points_off_reader<Point_d> off_reader(off_file_name); + Dynamic_kernel k; + unsigned intrisic_dim = 0; + std::vector<Point_d> points = off_reader.get_point_cloud(); + if (points.size() > 0) + intrisic_dim = points[0].size() - 1; + + tangential_complex_ = new TC(points, intrisic_dim, k); + tangential_complex_->compute_tangential_complex(); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + std::vector<double> get_point(unsigned vh) { + std::vector<double> vd; + if (vh < tangential_complex_->number_of_vertices()) { + Point_d ph = tangential_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + vd.push_back(*coord); + } + return vd; + } + + unsigned number_of_vertices() { + return tangential_complex_->number_of_vertices(); + } + + unsigned number_of_simplices() { + return num_inconsistencies_.num_simplices; + } + + unsigned number_of_inconsistent_simplices() { + return num_inconsistencies_.num_inconsistent_simplices; + } + + unsigned number_of_inconsistent_stars() { + return num_inconsistencies_.num_inconsistent_stars; + } + + void fix_inconsistencies_using_perturbation(double max_perturb, double time_limit) { + tangential_complex_->fix_inconsistencies_using_perturbation(max_perturb, time_limit); + num_inconsistencies_ = tangential_complex_->number_of_inconsistent_simplices(); + } + + void create_simplex_tree(Simplex_tree<>* simplex_tree) { + int max_dim = tangential_complex_->create_complex<Gudhi::Simplex_tree<Gudhi::Simplex_tree_options_full_featured>>(*simplex_tree); + // FIXME + simplex_tree->set_dimension(max_dim); + simplex_tree->initialize_filtration(); + } + + private: + TC* tangential_complex_; + TC::Num_inconsistencies num_inconsistencies_; +}; + +} // namespace tangential_complex + +} // namespace Gudhi + +#endif // TANGENTIAL_COMPLEX_INTERFACE_H + diff --git a/src/cython/include/Witness_complex_interface.h b/src/cython/include/Witness_complex_interface.h new file mode 100644 index 00000000..ab99adf5 --- /dev/null +++ b/src/cython/include/Witness_complex_interface.h @@ -0,0 +1,189 @@ +/* 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 + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef WITNESS_COMPLEX_INTERFACE_H +#define WITNESS_COMPLEX_INTERFACE_H + +#include <gudhi/Simplex_tree.h> +#include <gudhi/Witness_complex.h> +#include <gudhi/Construct_closest_landmark_table.h> +#include <gudhi/pick_n_random_points.h> + +#include "Persistent_cohomology_interface.h" + +#include <vector> +#include <utility> // std::pair +#include <iostream> + +namespace Gudhi { + +namespace witness_complex { + +class Witness_complex_interface { + typedef typename Simplex_tree<>::Simplex_handle Simplex_handle; + typedef typename std::pair<Simplex_handle, bool> Insertion_result; + using Simplex = std::vector<Vertex_handle>; + using Filtered_complex = std::pair<Simplex, Filtration_value>; + using Complex_tree = std::vector<Filtered_complex>; + + public: + Witness_complex_interface(std::vector<std::vector<double>>&points, int number_of_landmarks) + : pcoh_(nullptr) { + std::vector<std::vector< int > > knn; + std::vector<std::vector<double>> landmarks; + Gudhi::subsampling::pick_n_random_points(points, number_of_landmarks, std::back_inserter(landmarks)); + Gudhi::witness_complex::construct_closest_landmark_table(points, landmarks, knn); + + Gudhi::witness_complex::witness_complex(knn, number_of_landmarks, points[0].size(), simplex_tree_); + } + + 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; + } + + // Specific to Witness complex because no inheritance + Filtration_value filtration() const { + return simplex_tree_.filtration(); + } + + void set_filtration(Filtration_value fil) { + simplex_tree_.set_filtration(fil); + } + + void initialize_filtration() { + simplex_tree_.initialize_filtration(); + } + + size_t num_vertices() const { + return simplex_tree_.num_vertices(); + } + + size_t num_simplices() { + return simplex_tree_.num_simplices(); + } + + int dimension() const { + return simplex_tree_.dimension(); + } + + void set_dimension(int dimension) { + simplex_tree_.set_dimension(dimension); + } + + std::vector<std::pair<int, std::pair<double, double>>> get_persistence(int homology_coeff_field, double min_persistence) { + if (pcoh_ != nullptr) { + delete pcoh_; + } + pcoh_ = new Persistent_cohomology_interface<Simplex_tree<>>(&simplex_tree_); + return pcoh_->get_persistence(homology_coeff_field, min_persistence); + } + + std::vector<int> get_betti_numbers() const { + if (pcoh_ != nullptr) { + return pcoh_->betti_numbers(); + } + std::vector<int> betti_numbers; + return betti_numbers; + } + + std::vector<int> get_persistent_betti_numbers(Filtration_value from, Filtration_value to) const { + if (pcoh_ != nullptr) { + return pcoh_->persistent_betti_numbers(from, to); + } + std::vector<int> persistent_betti_numbers; + return persistent_betti_numbers; + } + + private: + Simplex_tree<> simplex_tree_; + Persistent_cohomology_interface<Simplex_tree<>>* pcoh_; + +}; + +} // namespace witness_complex + +} // namespace Gudhi + +#endif // WITNESS_COMPLEX_INTERFACE_H + diff --git a/src/cython/test/test_alpha_complex.py b/src/cython/test/test_alpha_complex.py new file mode 100755 index 00000000..b08ac0d7 --- /dev/null +++ b/src/cython/test/test_alpha_complex.py @@ -0,0 +1,86 @@ +from gudhi import AlphaComplex, SimplexTree + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_alpha(): + alpha_complex = AlphaComplex(points=[[0,0]]) + assert alpha_complex.__is_defined() == True + +def test_infinite_alpha(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + alpha_complex = AlphaComplex(points=point_list) + assert alpha_complex.__is_defined() == True + + simplex_tree = alpha_complex.create_simplex_tree() + assert simplex_tree.__is_persistence_defined() == False + + assert simplex_tree.num_simplices() == 11 + assert simplex_tree.num_vertices() == 4 + + assert simplex_tree.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)] + assert simplex_tree.get_star_tree([0]) == \ + [([0], 0.0), ([0, 1], 0.25), ([0, 1, 2], 0.5), + ([0, 2], 0.25)] + assert simplex_tree.get_coface_tree([0], 1) == \ + [([0, 1], 0.25), ([0, 2], 0.25)] + + assert point_list[0] == alpha_complex.get_point(0) + assert point_list[1] == alpha_complex.get_point(1) + assert point_list[2] == alpha_complex.get_point(2) + assert point_list[3] == alpha_complex.get_point(3) + assert alpha_complex.get_point(4) == [] + assert alpha_complex.get_point(125) == [] + +def test_filtered_alpha(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_alpha = AlphaComplex(points=point_list) + + simplex_tree = filtered_alpha.create_simplex_tree(max_alpha_square=0.25) + + assert simplex_tree.num_simplices() == 8 + assert simplex_tree.num_vertices() == 4 + + assert point_list[0] == filtered_alpha.get_point(0) + assert point_list[1] == filtered_alpha.get_point(1) + assert point_list[2] == filtered_alpha.get_point(2) + assert point_list[3] == filtered_alpha.get_point(3) + assert filtered_alpha.get_point(4) == [] + assert filtered_alpha.get_point(125) == [] + + assert simplex_tree.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)] + assert simplex_tree.get_star_tree([0]) == \ + [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)] + assert simplex_tree.get_coface_tree([0], 1) == \ + [([0, 1], 0.25), ([0, 2], 0.25)] diff --git a/src/cython/test/test_cubical_complex.py b/src/cython/test/test_cubical_complex.py new file mode 100755 index 00000000..c8df8089 --- /dev/null +++ b/src/cython/test/test_cubical_complex.py @@ -0,0 +1,86 @@ +from gudhi import CubicalComplex + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_constructor(): + # Try to create an empty CubicalComplex + cub = CubicalComplex() + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_non_existing_perseus_file_constructor(): + # Try to open a non existing file + cub = CubicalComplex(perseus_file='pouetpouettralala.toubiloubabdou') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_dimension_or_perseus_file_constructor(): + # Create test file + test_file = open('CubicalOneSphere.txt', 'w') + test_file.write('2\n3\n3\n0\n0\n0\n0\n100\n0\n0\n0\n0\n') + test_file.close() + # CubicalComplex can be constructed from dimensions and + # top_dimensional_cells OR from a perseus file style name. + cub = CubicalComplex(dimensions=[3, 3], + top_dimensional_cells = [1,2,3,4,5,6,7,8,9], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + + cub = CubicalComplex(top_dimensional_cells = [1,2,3,4,5,6,7,8,9], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + + cub = CubicalComplex(dimensions=[3, 3], + perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == False + assert cub.__is_persistence_defined() == False + +def test_dimension_constructor(): + cub = CubicalComplex(dimensions=[3, 3], + top_dimensional_cells = [1,2,3,4,5,6,7,8,9]) + assert cub.__is_defined() == True + assert cub.__is_persistence_defined() == False + assert cub.persistence() == [(1, (0.0, 100.0)), (0, (0.0, 1.8446744073709552e+19))] + assert cub.__is_persistence_defined() == True + assert cub.betti_numbers() == [1, 0] + assert cub.persistent_betti_numbers(0, 1000) == [0, 0] + +def test_dimension_constructor(): + # Create test file + test_file = open('CubicalOneSphere.txt', 'w') + test_file.write('2\n3\n3\n0\n0\n0\n0\n100\n0\n0\n0\n0\n') + test_file.close() + cub = CubicalComplex(perseus_file='CubicalOneSphere.txt') + assert cub.__is_defined() == True + assert cub.__is_persistence_defined() == False + assert cub.persistence() == [(1, (0.0, 100.0)), (0, (0.0, 1.8446744073709552e+19))] + assert cub.__is_persistence_defined() == True + assert cub.betti_numbers() == [1, 0, 0] + assert cub.persistent_betti_numbers(0, 1000) == [1, 0, 0] diff --git a/src/cython/test/test_mini_simplex_tree.py b/src/cython/test/test_mini_simplex_tree.py new file mode 100755 index 00000000..e44bfdbc --- /dev/null +++ b/src/cython/test/test_mini_simplex_tree.py @@ -0,0 +1,50 @@ +from gudhi import MiniSimplexTree + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_mini(): + triangle012 = [0, 1, 2] + edge03 = [0, 3] + mini_st = MiniSimplexTree() + assert mini_st.__is_defined() == True + assert mini_st.__is_persistence_defined() == False + assert mini_st.insert(triangle012) == True + assert mini_st.insert(edge03) == True + # FIXME: Remove this line + mini_st.set_dimension(2) + + edge02 = [0, 2] + assert mini_st.find(edge02) == True + assert mini_st.get_coface_tree(edge02, 1) == \ + [([0, 1, 2], 0.0)] + + # remove_maximal_simplex test + assert mini_st.get_coface_tree(triangle012, 1) == [] + mini_st.remove_maximal_simplex(triangle012) + assert mini_st.find(edge02) == True + assert mini_st.find(triangle012) == False diff --git a/src/cython/test/test_rips_complex.py b/src/cython/test/test_rips_complex.py new file mode 100755 index 00000000..877289cf --- /dev/null +++ b/src/cython/test/test_rips_complex.py @@ -0,0 +1,65 @@ +from gudhi import RipsComplex + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_rips(): + rips_complex = RipsComplex() + assert rips_complex.__is_defined() == True + assert rips_complex.__is_persistence_defined() == False + +def test_rips(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + rips_complex = RipsComplex(points=point_list, max_dimension=1, + max_edge_length=42) + assert rips_complex.__is_defined() == True + assert rips_complex.__is_persistence_defined() == False + + assert rips_complex.num_simplices() == 10 + assert rips_complex.num_vertices() == 4 + + assert 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)] + assert rips_complex.get_star_tree([0]) == \ + [([0], 0.0), ([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + assert rips_complex.get_coface_tree([0], 1) == \ + [([0, 1], 1.0), ([0, 2], 1.0), + ([0, 3], 1.4142135623730951)] + +def test_filtered_rips(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + filtered_rips = RipsComplex(points=point_list, max_dimension=1, + max_edge_length=1.0) + assert filtered_rips.__is_defined() == True + assert filtered_rips.__is_persistence_defined() == False + + assert filtered_rips.num_simplices() == 8 + assert filtered_rips.num_vertices() == 4 diff --git a/src/cython/test/test_simplex_tree.py b/src/cython/test/test_simplex_tree.py new file mode 100755 index 00000000..0b9899f8 --- /dev/null +++ b/src/cython/test/test_simplex_tree.py @@ -0,0 +1,98 @@ +from gudhi import SimplexTree + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_insertion(): + st = SimplexTree() + assert st.__is_defined() == True + assert st.__is_persistence_defined() == False + + # insert test + assert st.insert([0, 1]) == True + assert st.insert([0, 1, 2], filtration=4.0) == True + # FIXME: Remove this line + st.set_dimension(2) + assert st.num_simplices() == 7 + assert st.num_vertices() == 3 + + # find test + assert st.find([0, 1, 2]) == True + assert st.find([0, 1]) == True + assert st.find([0, 2]) == True + assert st.find([0]) == True + assert st.find([1]) == True + assert st.find([2]) == True + assert st.find([3]) == False + assert st.find([0, 3]) == False + assert st.find([1, 3]) == False + assert st.find([2, 3]) == False + + # filtration test + st.set_filtration(5.0) + st.initialize_filtration() + assert st.get_filtration() == 5.0 + assert st.filtration([0, 1, 2]) == 4.0 + assert st.filtration([0, 2]) == 4.0 + assert st.filtration([1, 2]) == 4.0 + assert st.filtration([2]) == 4.0 + assert st.filtration([0, 1]) == 0.0 + assert st.filtration([0]) == 0.0 + assert st.filtration([1]) == 0.0 + + # skeleton_tree test + assert 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)] + assert 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)] + assert st.get_skeleton_tree(0) == \ + [([0], 0.0), ([1], 0.0), ([2], 4.0)] + + # remove_maximal_simplex test + assert st.get_coface_tree([0, 1, 2], 1) == [] + st.remove_maximal_simplex([0, 1, 2]) + assert st.get_skeleton_tree(2) == \ + [([0, 1], 0.0), ([0, 2], 4.0), ([0], 0.0), + ([1, 2], 4.0), ([1], 0.0), ([2], 4.0)] + assert st.find([0, 1, 2]) == False + assert st.find([0, 1]) == True + assert st.find([0, 2]) == True + assert st.find([0]) == True + assert st.find([1]) == True + assert st.find([2]) == True + + st.initialize_filtration() + assert st.persistence() == [(1, (4.0, float('inf'))), (0, (0.0, float('inf')))] + assert st.__is_persistence_defined() == True + assert st.betti_numbers() == [1, 1] + assert st.persistent_betti_numbers(-0.1, 10000.0) == [0, 0] + assert st.persistent_betti_numbers(0.0, 10000.0) == [1, 0] + assert st.persistent_betti_numbers(3.9, 10000.0) == [1, 0] + assert st.persistent_betti_numbers(4.0, 10000.0) == [1, 1] + assert st.persistent_betti_numbers(9999.0, 10000.0) == [1, 1] diff --git a/src/cython/test/test_subsampling.py b/src/cython/test/test_subsampling.py new file mode 100755 index 00000000..e5f2d70a --- /dev/null +++ b/src/cython/test/test_subsampling.py @@ -0,0 +1,94 @@ +import gudhi +import os + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_write_off_file_for_tests(): + file = open("n_farthest.off", "w") + file.write("nOFF\n") + file.write("2 7 0 0\n") + file.write("1.0 1.0\n") + file.write("7.0 0.0\n") + file.write("4.0 6.0\n") + file.write("9.0 6.0\n") + file.write("0.0 14.0\n") + file.write("2.0 19.0\n") + file.write("9.0 17.0\n") + file.close() + +def test_simple_choose_n_farthest_points_with_a_starting_point(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + i = 0 + for point in point_set: + # The iteration starts with the given starting point + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 1, starting_point = i) + assert sub_set[0] == point_set[i] + i = i + 1 + + # The iteration finds then the farthest + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 1) + assert sub_set[1] == point_set[3] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 3) + assert sub_set[1] == point_set[1] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 0) + assert sub_set[1] == point_set[2] + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = 2, starting_point = 2) + assert sub_set[1] == point_set[0] + + # Test the limits + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0, starting_point = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1, starting_point = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0, starting_point = 1) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1, starting_point = 1) == [] + + print(os.getcwd()) + # From off file test + for i in range (0, 7): + assert len(gudhi.choose_n_farthest_points(off_file = 'n_farthest.off', nb_points = i, starting_point = i)) == i + +def test_simple_choose_n_farthest_points_randomed(): + point_set = [[0,1], [0,0], [1,0], [1,1]] + + # Test the limits + assert gudhi.choose_n_farthest_points(points = [], nb_points = 0) == [] + assert gudhi.choose_n_farthest_points(points = [], nb_points = 1) == [] + assert gudhi.choose_n_farthest_points(points = point_set, nb_points = 0) == [] + # Go furter than point set on purpose + for iter in range(1,10): + sub_set = gudhi.choose_n_farthest_points(points = point_set, nb_points = iter) + for sub in sub_set: + found = False + for point in point_set: + if point == sub: + found = True + assert found == True + + print(os.getcwd()) + # From off file test + for i in range (0, 7): + assert len(gudhi.choose_n_farthest_points(off_file = 'n_farthest.off', nb_points = i)) == i diff --git a/src/cython/test/test_tangential_complex.py b/src/cython/test/test_tangential_complex.py new file mode 100755 index 00000000..8e1b5c51 --- /dev/null +++ b/src/cython/test/test_tangential_complex.py @@ -0,0 +1,56 @@ +from gudhi import TangentialComplex, SimplexTree + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_tangential(): + point_list = [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]] + tc = TangentialComplex(points=point_list) + assert tc.__is_defined() == True + assert tc.num_vertices() == 4 + + st = tc.create_simplex_tree() + assert st.__is_defined() == True + assert st.__is_persistence_defined() == False + + assert st.num_simplices() == 13 + assert st.num_vertices() == 4 + + assert st.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([0, 1], 0.0), ([2], 0.0), ([0, 2], 0.0), + ([1, 2], 0.0), ([3], 0.0), ([0, 3], 0.0), ([1, 3], 0.0), + ([0, 1, 3], 0.0), ([2, 3], 0.0), ([0, 2, 3], 0.0), + ([1, 2, 3], 0.0)] + assert st.get_coface_tree([0], 1) == \ + [([0, 1], 0.0), ([0, 2], 0.0), ([0, 3], 0.0)] + + assert point_list[0] == tc.get_point(0) + assert point_list[1] == tc.get_point(1) + assert point_list[2] == tc.get_point(2) + assert point_list[3] == tc.get_point(3) + assert tc.get_point(4) == [] + assert tc.get_point(125) == [] diff --git a/src/cython/test/test_witness_complex.py b/src/cython/test/test_witness_complex.py new file mode 100755 index 00000000..9f4a3523 --- /dev/null +++ b/src/cython/test/test_witness_complex.py @@ -0,0 +1,55 @@ +from gudhi import WitnessComplex + +"""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 + + 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 <http://www.gnu.org/licenses/>. +""" + +__author__ = "Vincent Rouvreau" +__copyright__ = "Copyright (C) 2016 INRIA" +__license__ = "GPL v3" + + +def test_empty_witness_complex(): + witness = WitnessComplex() + assert witness.__is_defined() == False + +def test_witness_complex(): + point_list = [[0, 0], [1, 0], [0, 1], [1, 1]] + witness = WitnessComplex(points=point_list, number_of_landmarks=10) + assert witness.__is_defined() == True + + # FIXME: Remove this line + witness.set_dimension(2) + + assert witness.num_simplices() == 13 + assert witness.num_vertices() == 10 + witness.initialize_filtration() + + assert witness.get_filtered_tree() == \ + [([0], 0.0), ([1], 0.0), ([2], 0.0), ([0, 2], 0.0), + ([1, 2], 0.0), ([3], 0.0), ([4], 0.0), ([3, 4], 0.0), + ([5], 0.0), ([6], 0.0), ([7], 0.0), ([8], 0.0), + ([9], 0.0)] + + assert witness.get_coface_tree([2], 1) == \ + [([0, 2], 0.0), ([1, 2], 0.0)] + assert witness.get_star_tree([2]) == \ + [([0, 2], 0.0), ([1, 2], 0.0), ([2], 0.0)] |