From f87a1026d5d1accbb6a558ef5d50f5c4c035e0d8 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Dec 2019 16:51:09 +0100 Subject: Fix #134 --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6b4d8463..6f19cb6c 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -121,8 +121,8 @@ class Alpha_complex { // size_type type from CGAL. typedef typename Delaunay_triangulation::size_type size_type; - // Map type to switch from simplex tree vertex handle to CGAL vertex iterator. - typedef typename std::map< std::size_t, CGAL_vertex_iterator > Vector_vertex_iterator; + // Structure to switch from simplex tree vertex handle to CGAL vertex iterator. + typedef typename std::vector< CGAL_vertex_iterator > Vector_vertex_iterator; private: /** \brief Vertex iterator vector to switch from simplex tree vertex handle to CGAL vertex iterator. @@ -238,14 +238,16 @@ class Alpha_complex { hint = pos->full_cell(); } // -------------------------------------------------------------------------------------------- - // double map to retrieve simplex tree vertex handles from CGAL vertex iterator and vice versa + // structure to retrieve CGAL points from vertex handle - one vertex handle per point. + // Needs to be constructed before as vertex handles arrives in no particular order. + vertex_handle_to_iterator_.resize(point_cloud.size()); // Loop on triangulation vertices list for (CGAL_vertex_iterator vit = triangulation_->vertices_begin(); vit != triangulation_->vertices_end(); ++vit) { if (!triangulation_->is_infinite(*vit)) { #ifdef DEBUG_TRACES std::cout << "Vertex insertion - " << vit->data() << " -> " << vit->point() << std::endl; #endif // DEBUG_TRACES - vertex_handle_to_iterator_.emplace(vit->data(), vit); + vertex_handle_to_iterator_[vit->data()] = vit; } } // -------------------------------------------------------------------------------------------- -- cgit v1.2.3 From 10e7b9ff243260887c54c5ca49d92a27c281c68f Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 3 Dec 2019 17:45:14 +0100 Subject: Fix #118 - protect some bottleneck tests --- .../test/bottleneck_unit_test.cpp | 37 +++++++++++----------- src/common/include/gudhi/Unitary_tests_utils.h | 11 +++++++ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Bottleneck_distance/test/bottleneck_unit_test.cpp b/src/Bottleneck_distance/test/bottleneck_unit_test.cpp index 3fc6fc7b..2c520045 100644 --- a/src/Bottleneck_distance/test/bottleneck_unit_test.cpp +++ b/src/Bottleneck_distance/test/bottleneck_unit_test.cpp @@ -15,6 +15,7 @@ #include #include +#include using namespace Gudhi::persistence_diagram; @@ -59,24 +60,24 @@ BOOST_AUTO_TEST_CASE(persistence_graph) { BOOST_CHECK(g.size() == (n1 + n2)); // BOOST_CHECK((int) d.size() == (n1 + n2)*(n1 + n2) + n1 + n2 + 1); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, 0)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, n1 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, n1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, n2 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, n2)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(0, (n1 + n2) - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, 0)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, n1 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, n1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, n2 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, n2)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance(n1, (n1 + n2) - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, 0)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, n1 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, n1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, n2 - 1)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, n2)) > 0); - BOOST_CHECK(std::count(d.begin(), d.end(), g.distance((n1 + n2) - 1, (n1 + n2) - 1)) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, 0))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, n1 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, n1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, n2 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, n2))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(0, (n1 + n2) - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, 0))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, n1 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, n1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, n2 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, n2))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance(n1, (n1 + n2) - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, 0))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, n1 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, n1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, n2 - 1))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, n2))) > 0); + BOOST_CHECK(std::count(d.begin(), d.end(), GUDHI_PROTECT_FLOAT(g.distance((n1 + n2) - 1, (n1 + n2) - 1))) > 0); } BOOST_AUTO_TEST_CASE(neighbors_finder) { diff --git a/src/common/include/gudhi/Unitary_tests_utils.h b/src/common/include/gudhi/Unitary_tests_utils.h index 7d039304..9b86460a 100644 --- a/src/common/include/gudhi/Unitary_tests_utils.h +++ b/src/common/include/gudhi/Unitary_tests_utils.h @@ -26,4 +26,15 @@ void GUDHI_TEST_FLOAT_EQUALITY_CHECK(FloatingType a, FloatingType b, BOOST_CHECK(std::fabs(a - b) <= epsilon); } +// That's the usual x86 issue where a+b==a+b can return false (without any NaN) because one of them was stored in +// memory (and thus rounded to 64 bits) while the other is still in a register (80 bits). +template +FloatingType GUDHI_PROTECT_FLOAT(FloatingType value) { + volatile FloatingType protected_value = value; +#ifdef DEBUG_TRACES + std::cout << "GUDHI_PROTECT_FLOAT - " << protected_value << std::endl; +#endif + return protected_value; +} + #endif // UNITARY_TESTS_UTILS_H_ -- cgit v1.2.3 From 9fc45aafa4588b86ccd903b9173a8cdf48db68a1 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 5 Dec 2019 16:01:45 +0100 Subject: Add MPFR dependency for python module. Use Epeck_d by default for Alpha complex. Add boolean exact version mechanism --- src/cmake/modules/FindMPFR.cmake | 51 ++++++++++++++++++ .../modules/GUDHI_third_party_libraries.cmake | 2 + src/python/CMakeLists.txt | 61 +++++++++++++--------- src/python/gudhi/alpha_complex.pyx | 13 +++-- src/python/include/Alpha_complex_interface.h | 9 ++-- 5 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 src/cmake/modules/FindMPFR.cmake diff --git a/src/cmake/modules/FindMPFR.cmake b/src/cmake/modules/FindMPFR.cmake new file mode 100644 index 00000000..6c963272 --- /dev/null +++ b/src/cmake/modules/FindMPFR.cmake @@ -0,0 +1,51 @@ +# Try to find the MPFR libraries +# MPFR_FOUND - system has MPFR lib +# MPFR_INCLUDE_DIR - the MPFR include directory +# MPFR_LIBRARIES_DIR - Directory where the MPFR libraries are located +# MPFR_LIBRARIES - the MPFR libraries + +# TODO: support MacOSX + +include(FindPackageHandleStandardArgs) + +if(MPFR_INCLUDE_DIR) + set(MPFR_in_cache TRUE) +else() + set(MPFR_in_cache FALSE) +endif() +if(NOT MPFR_LIBRARIES) + set(MPFR_in_cache FALSE) +endif() + +# Is it already configured? +if (MPFR_in_cache) + set(MPFR_FOUND TRUE) +else() + find_path(MPFR_INCLUDE_DIR + NAMES mpfr.h + HINTS ENV MPFR_INC_DIR + ENV MPFR_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include + PATH_SUFFIXES include + DOC "The directory containing the MPFR header files" + ) + + find_library(MPFR_LIBRARIES NAMES mpfr libmpfr-4 libmpfr-1 + HINTS ENV MPFR_LIB_DIR + ENV MPFR_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/lib + PATH_SUFFIXES lib + DOC "Path to the MPFR library" + ) + + if ( MPFR_LIBRARIES ) + get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH CACHE ) + endif() + + # Attempt to load a user-defined configuration for MPFR if couldn't be found + if ( NOT MPFR_INCLUDE_DIR OR NOT MPFR_LIBRARIES_DIR ) + include( MPFRConfig OPTIONAL ) + endif() + + find_package_handle_standard_args(MPFR "DEFAULT_MSG" MPFR_LIBRARIES MPFR_INCLUDE_DIR) +endif() diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 24a34150..d8c7a428 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -6,6 +6,8 @@ if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") endif(NOT Boost_FOUND) +find_package(MPFR) + find_package(GMP) if(GMP_FOUND) INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 9af85eac..13a8a909 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -114,9 +114,9 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'nerve_gic', ") endif () if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'alpha_complex', ") set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'subsampling', ") set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'tangential_complex', ") - set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'alpha_complex', ") set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'euclidean_witness_complex', ") set(GUDHI_PYTHON_MODULES_TO_COMPILE "${GUDHI_PYTHON_MODULES_TO_COMPILE}'euclidean_strong_witness_complex', ") endif () @@ -162,10 +162,17 @@ if(PYTHONINTERP_FOUND) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") add_GUDHI_PYTHON_lib("${GMPXX_LIBRARIES}") set(GUDHI_PYTHON_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}'${GMPXX_LIBRARIES_DIR}', ") - message("** Add gmpxx ${GMPXX_LIBRARIES_DIR}") + message("** Add gmpxx ${GMPXX_LIBRARIES_DIR}") endif(GMPXX_FOUND) endif(GMP_FOUND) - endif(CGAL_FOUND) + if(MPFR_FOUND) + add_gudhi_debug_info("MPFR_LIBRARIES = ${MPFR_LIBRARIES}") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_MPFR', ") + add_GUDHI_PYTHON_lib("${MPFR_LIBRARIES}") + set(GUDHI_PYTHON_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}'${MPFR_LIBRARIES_DIR}', ") + message("** Add mpfr ${MPFR_LIBRARIES}") + endif(MPFR_FOUND) +endif(CGAL_FOUND) # Specific for Mac if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -223,13 +230,14 @@ if(PYTHONINTERP_FOUND) # Test examples if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - # Bottleneck and Alpha - add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" - -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) - + if (MPFR_FOUND) + # Bottleneck and Alpha + add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" + -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) + endif(MPFR_FOUND) if(MATPLOTLIB_FOUND AND NUMPY_FOUND) # Tangential add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test @@ -300,22 +308,23 @@ if(PYTHONINTERP_FOUND) endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - # Alpha - add_test(NAME alpha_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") - - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) - endif() - - add_gudhi_py_test(test_alpha_complex) - + if (MPFR_FOUND) + # Alpha + add_test(NAME alpha_complex_from_points_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") + + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) + endif() + + add_gudhi_py_test(test_alpha_complex) + endif(MPFR_FOUND) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index 8f2c98d5..abac6e7b 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -28,7 +28,7 @@ cdef extern from "Alpha_complex_interface.h" namespace "Gudhi": # 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) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, bool exact_version) # AlphaComplex python interface cdef class AlphaComplex: @@ -66,7 +66,7 @@ cdef class AlphaComplex: """ # The real cython constructor - def __cinit__(self, points=None, off_file=''): + def __cinit__(self, points = None, off_file = ''): if off_file: if os.path.isfile(off_file): self.thisptr = new Alpha_complex_interface(str.encode(off_file), True) @@ -99,17 +99,22 @@ cdef class AlphaComplex: cdef vector[double] point = self.thisptr.get_point(vertex) return point - def create_simplex_tree(self, max_alpha_square=float('inf')): + def create_simplex_tree(self, max_alpha_square = float('inf'), + exact_version = False): """ :param max_alpha_square: The maximum alpha square threshold the simplices shall not exceed. Default is set to infinity, and there is very little point using anything else since it does not save time. :type max_alpha_square: float + :param exact_version: Exact computation version. Default is false + which means Safe version is used. + :type exact_version: bool :returns: A simplex tree created from the Delaunay Triangulation. :rtype: SimplexTree """ stree = SimplexTree() cdef intptr_t stree_int_ptr=stree.thisptr - self.thisptr.create_simplex_tree(stree_int_ptr, max_alpha_square) + self.thisptr.create_simplex_tree(stree_int_ptr, + max_alpha_square, exact_version) return stree diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index 96353cc4..a7621f2b 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -28,7 +29,7 @@ namespace Gudhi { namespace alpha_complex { class Alpha_complex_interface { - using Dynamic_kernel = CGAL::Epick_d< CGAL::Dynamic_dimension_tag >; + using Dynamic_kernel = CGAL::Epeck_d< CGAL::Dynamic_dimension_tag >; using Point_d = Dynamic_kernel::Point_d; public: @@ -51,7 +52,7 @@ class Alpha_complex_interface { std::vector vd; try { Point_d const& ph = alpha_complex_->get_point(vh); - for (auto coord = ph.cartesian_begin(); coord < ph.cartesian_end(); coord++) + for (auto coord = ph.cartesian_begin(); coord != ph.cartesian_end(); coord++) vd.push_back(CGAL::to_double(*coord)); } catch (std::out_of_range const&) { // std::out_of_range is thrown in case not found. Other exceptions must be re-thrown @@ -59,8 +60,8 @@ class Alpha_complex_interface { return vd; } - void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square) { - alpha_complex_->create_complex(*simplex_tree, max_alpha_square); + void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool exact_version) { + alpha_complex_->create_complex(*simplex_tree, max_alpha_square, exact_version); simplex_tree->initialize_filtration(); } -- cgit v1.2.3 From 3757fedbf7ad387cdc06870a1db9532bbee4bab9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 5 Dec 2019 17:05:19 +0100 Subject: Add a test that fixes #107 --- src/python/test/test_alpha_complex.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 24f8bf53..ab84daaa 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -1,4 +1,8 @@ from gudhi import AlphaComplex, SimplexTree +import math +import numpy as np +import itertools +import pytest """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. @@ -88,3 +92,34 @@ def test_filtered_alpha(): ] assert simplex_tree.get_star([0]) == [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)] assert simplex_tree.get_cofaces([0], 1) == [([0, 1], 0.25), ([0, 2], 0.25)] + +def alpha_persistence_comparison(exact_version): + #generate periodic signal + time = np.arange(0, 10, 1) + signal = [math.sin(x) for x in time] + delta = math.pi + delayed = [math.sin(x + delta) for x in time] + + #construct embedding + embedding1 = [[signal[i], -signal[i]] for i in range(len(time))] + embedding2 = [[signal[i], delayed[i]] for i in range(len(time))] + + #build alpha complex and simplex tree + alpha_complex1 = AlphaComplex(points=embedding1) + simplex_tree1 = alpha_complex1.create_simplex_tree(exact_version = exact_version) + + alpha_complex2 = AlphaComplex(points=embedding2) + simplex_tree2 = alpha_complex2.create_simplex_tree(exact_version = exact_version) + + diag1 = simplex_tree1.persistence() + diag2 = simplex_tree2.persistence() + + for (first_p, second_p) in itertools.zip_longest(diag1, diag2): + assert first_p[0] == pytest.approx(second_p[0]) + assert first_p[1] == pytest.approx(second_p[1]) + +def test_exact_alpha_version(): + alpha_persistence_comparison(exact_version = True) + +def test_safe_alpha_version(): + alpha_persistence_comparison(exact_version = False) -- cgit v1.2.3 From 6142e146e92801cafe1438bf487f3ecafa502177 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 5 Dec 2019 17:57:19 +0100 Subject: nicer doc presentation --- src/python/gudhi/alpha_complex.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index abac6e7b..bfb9783a 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -107,8 +107,8 @@ cdef class AlphaComplex: there is very little point using anything else since it does not save time. :type max_alpha_square: float - :param exact_version: Exact computation version. Default is false - which means Safe version is used. + :param exact_version: :code:`EXACT` computation version if set. + Default is false which means :code:`SAFE` version is used. :type exact_version: bool :returns: A simplex tree created from the Delaunay Triangulation. :rtype: SimplexTree -- cgit v1.2.3 From 329637d2a0a806955a29faccf38915c3fb7cd2fd Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 10 Dec 2019 10:03:53 +0100 Subject: Remove number_of_vertices method from Alpha_complex as there is no added value to Simplex_tree.num_vertices() --- src/Alpha_complex/include/gudhi/Alpha_complex.h | 8 --- src/Alpha_complex/test/Alpha_complex_unit_test.cpp | 60 +++++++++++++++------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/Alpha_complex/include/gudhi/Alpha_complex.h b/src/Alpha_complex/include/gudhi/Alpha_complex.h index 6f19cb6c..f2a05e95 100644 --- a/src/Alpha_complex/include/gudhi/Alpha_complex.h +++ b/src/Alpha_complex/include/gudhi/Alpha_complex.h @@ -191,14 +191,6 @@ class Alpha_complex { return vertex_handle_to_iterator_.at(vertex)->point(); } - /** \brief number_of_vertices returns the number of vertices (same as the number of points). - * - * @return The number of vertices. - */ - std::size_t number_of_vertices() const { - return vertex_handle_to_iterator_.size(); - } - private: template void init_from_range(const InputPointRange& points) { diff --git a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp index 40b3fe09..27b671dd 100644 --- a/src/Alpha_complex/test/Alpha_complex_unit_test.cpp +++ b/src/Alpha_complex/test/Alpha_complex_unit_test.cpp @@ -53,20 +53,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_OFF_file, TestedKernel, list_of Gudhi::alpha_complex::Alpha_complex alpha_complex_from_file(off_file_name); - std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices() - << std::endl; - BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7); - Gudhi::Simplex_tree<> simplex_tree_60; BOOST_CHECK(alpha_complex_from_file.create_complex(simplex_tree_60, max_alpha_square_value)); std::cout << "simplex_tree_60.dimension()=" << simplex_tree_60.dimension() << std::endl; BOOST_CHECK(simplex_tree_60.dimension() == 2); - std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_file.number_of_vertices() - << std::endl; - BOOST_CHECK(alpha_complex_from_file.number_of_vertices() == 7); - std::cout << "simplex_tree_60.num_vertices()=" << simplex_tree_60.num_vertices() << std::endl; BOOST_CHECK(simplex_tree_60.num_vertices() == 7); @@ -128,10 +120,6 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { Gudhi::Simplex_tree<> simplex_tree; BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); - std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices() - << std::endl; - BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size()); - // Another way to check num_simplices std::cout << "Iterator on alpha complex simplices in the filtration order, with [filtration value]:" << std::endl; int num_simplices = 0; @@ -151,7 +139,7 @@ BOOST_AUTO_TEST_CASE(Alpha_complex_from_points) { std::cout << "simplex_tree.dimension()=" << simplex_tree.dimension() << std::endl; BOOST_CHECK(simplex_tree.dimension() == 3); std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; - BOOST_CHECK(simplex_tree.num_vertices() == 4); + BOOST_CHECK(simplex_tree.num_vertices() == points.size()); for (auto f_simplex : simplex_tree.filtration_simplex_range()) { switch (simplex_tree.dimension(f_simplex)) { @@ -261,10 +249,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, lis Gudhi::Simplex_tree<> simplex_tree; BOOST_CHECK(!alpha_complex_from_points.create_complex(simplex_tree)); - std::cout << "alpha_complex_from_points.number_of_vertices()=" << alpha_complex_from_points.number_of_vertices() - << std::endl; - BOOST_CHECK(alpha_complex_from_points.number_of_vertices() == points.size()); - std::cout << "simplex_tree.num_simplices()=" << simplex_tree.num_simplices() << std::endl; BOOST_CHECK(simplex_tree.num_simplices() == 0); @@ -272,5 +256,45 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_from_empty_points, TestedKernel, lis BOOST_CHECK(simplex_tree.dimension() == -1); std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() << std::endl; - BOOST_CHECK(simplex_tree.num_vertices() == 0); + BOOST_CHECK(simplex_tree.num_vertices() == points.size()); +} + +using Inexact_kernel_2 = CGAL::Epick_d< CGAL::Dimension_tag<2> >; +using Exact_kernel_2 = CGAL::Epeck_d< CGAL::Dimension_tag<2> >; +using list_of_kernel_2_variants = boost::mpl::list; + +BOOST_AUTO_TEST_CASE_TEMPLATE(Alpha_complex_with_duplicated_points, TestedKernel, list_of_kernel_2_variants) { + std::cout << "========== Alpha_complex_with_duplicated_points ==========" << std::endl; + + using Point = typename TestedKernel::Point_d; + using Vector_of_points = std::vector; + + // ---------------------------------------------------------------------------- + // Init of a list of points + // ---------------------------------------------------------------------------- + Vector_of_points points; + points.push_back(Point(1.0, 1.0)); + points.push_back(Point(7.0, 0.0)); + points.push_back(Point(4.0, 6.0)); + points.push_back(Point(9.0, 6.0)); + points.push_back(Point(0.0, 14.0)); + points.push_back(Point(2.0, 19.0)); + points.push_back(Point(9.0, 17.0)); + // duplicated points + points.push_back(Point(1.0, 1.0)); + points.push_back(Point(7.0, 0.0)); + + // ---------------------------------------------------------------------------- + // Init of an alpha complex from the list of points + // ---------------------------------------------------------------------------- + std::cout << "Init" << std::endl; + Gudhi::alpha_complex::Alpha_complex alpha_complex_from_points(points); + + Gudhi::Simplex_tree<> simplex_tree; + std::cout << "create_complex" << std::endl; + BOOST_CHECK(alpha_complex_from_points.create_complex(simplex_tree)); + + std::cout << "simplex_tree.num_vertices()=" << simplex_tree.num_vertices() + << std::endl; + BOOST_CHECK(simplex_tree.num_vertices() < points.size()); } -- cgit v1.2.3 From ad0131187e70657b699eb205de901e50ab36a5d9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 10 Dec 2019 11:44:21 +0100 Subject: Fix #118 for persistence_intervals --- .../include/gudhi/Persistence_intervals.h | 5 +++++ src/Persistence_representations/test/persistence_intervals_test.cpp | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Persistence_representations/include/gudhi/Persistence_intervals.h b/src/Persistence_representations/include/gudhi/Persistence_intervals.h index e2db4572..ea4220ea 100644 --- a/src/Persistence_representations/include/gudhi/Persistence_intervals.h +++ b/src/Persistence_representations/include/gudhi/Persistence_intervals.h @@ -6,6 +6,8 @@ * * Modification(s): * - YYYY/MM Author: Description of the modification + * - 2019/12 Vincent Rouvreau: Fix #118 - Make histogram_of_lengths and cumulative_histogram_of_lengths + * return the exact number_of_bins (was failing on x86) */ #ifndef PERSISTENCE_INTERVALS_H_ @@ -335,6 +337,9 @@ std::vector Persistence_intervals::histogram_of_lengths(size_t number_of getchar(); } } + // we want number of bins equals to number_of_bins (some unexpected results on x86) + result[number_of_bins-1]+=result[number_of_bins]; + result.resize(number_of_bins); if (dbg) { for (size_t i = 0; i != result.size(); ++i) std::cerr << result[i] << std::endl; diff --git a/src/Persistence_representations/test/persistence_intervals_test.cpp b/src/Persistence_representations/test/persistence_intervals_test.cpp index 3b7a2049..a29dcbee 100644 --- a/src/Persistence_representations/test/persistence_intervals_test.cpp +++ b/src/Persistence_representations/test/persistence_intervals_test.cpp @@ -85,8 +85,7 @@ BOOST_AUTO_TEST_CASE(check_histogram_of_lengths) { template_histogram.push_back(6); template_histogram.push_back(1); template_histogram.push_back(7); - template_histogram.push_back(1); - template_histogram.push_back(1); + template_histogram.push_back(2); for (size_t i = 0; i != histogram.size(); ++i) { BOOST_CHECK(histogram[i] == template_histogram[i]); } @@ -105,7 +104,6 @@ BOOST_AUTO_TEST_CASE(check_cumulative_histograms_of_lengths) { template_cumulative_histogram.push_back(35); template_cumulative_histogram.push_back(36); template_cumulative_histogram.push_back(43); - template_cumulative_histogram.push_back(44); template_cumulative_histogram.push_back(45); for (size_t i = 0; i != cumulative_histogram.size(); ++i) { -- cgit v1.2.3 From 291286815e282c9693f17615f8c46a49f87bf887 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 10 Dec 2019 13:33:02 +0100 Subject: Use initializer list instead of push_back to init vectors --- .../test/persistence_intervals_test.cpp | 209 ++++----------------- 1 file changed, 40 insertions(+), 169 deletions(-) diff --git a/src/Persistence_representations/test/persistence_intervals_test.cpp b/src/Persistence_representations/test/persistence_intervals_test.cpp index a29dcbee..02ea8edb 100644 --- a/src/Persistence_representations/test/persistence_intervals_test.cpp +++ b/src/Persistence_representations/test/persistence_intervals_test.cpp @@ -6,6 +6,8 @@ * * Modification(s): * - YYYY/MM Author: Description of the modification + * - 2019/12 Vincent Rouvreau: Fix #118 - Make histogram_of_lengths and cumulative_histogram_of_lengths + * return the exact number_of_bins (was failing on x86) */ #define BOOST_TEST_DYN_LINK @@ -32,17 +34,8 @@ BOOST_AUTO_TEST_CASE(check_min_max_function) { BOOST_AUTO_TEST_CASE(check_length_of_dominant_intervals) { Persistence_intervals p("data/file_with_diagram"); std::vector dominant_ten_intervals_length = p.length_of_dominant_intervals(10); - std::vector dominant_intervals_length; - dominant_intervals_length.push_back(0.862625); - dominant_intervals_length.push_back(0.800893); - dominant_intervals_length.push_back(0.762061); - dominant_intervals_length.push_back(0.756501); - dominant_intervals_length.push_back(0.729367); - dominant_intervals_length.push_back(0.718177); - dominant_intervals_length.push_back(0.708395); - dominant_intervals_length.push_back(0.702844); - dominant_intervals_length.push_back(0.700468); - dominant_intervals_length.push_back(0.622177); + std::vector dominant_intervals_length{0.862625, 0.800893, 0.762061, 0.756501, 0.729367, + 0.718177, 0.708395, 0.702844, 0.700468, 0.622177}; for (size_t i = 0; i != dominant_ten_intervals_length.size(); ++i) { GUDHI_TEST_FLOAT_EQUALITY_CHECK(dominant_ten_intervals_length[i], dominant_intervals_length[i], Gudhi::Persistence_representations::epsi); @@ -52,17 +45,11 @@ BOOST_AUTO_TEST_CASE(check_dominant_intervals) { Persistence_intervals p("data/file_with_diagram"); std::vector > ten_dominant_intervals = p.dominant_intervals(10); - std::vector > templ; - templ.push_back(std::pair(0.114718, 0.977343)); - templ.push_back(std::pair(0.133638, 0.93453)); - templ.push_back(std::pair(0.104599, 0.866659)); - templ.push_back(std::pair(0.149798, 0.906299)); - templ.push_back(std::pair(0.247352, 0.976719)); - templ.push_back(std::pair(0.192675, 0.910852)); - templ.push_back(std::pair(0.191836, 0.900231)); - templ.push_back(std::pair(0.284998, 0.987842)); - templ.push_back(std::pair(0.294069, 0.994537)); - templ.push_back(std::pair(0.267421, 0.889597)); + std::vector > templ{ {0.114718, 0.977343}, {0.133638, 0.93453}, + {0.104599, 0.866659}, {0.149798, 0.906299}, + {0.247352, 0.976719}, {0.192675, 0.910852}, + {0.191836, 0.900231}, {0.284998, 0.987842}, + {0.294069, 0.994537}, {0.267421, 0.889597} }; for (size_t i = 0; i != ten_dominant_intervals.size(); ++i) { GUDHI_TEST_FLOAT_EQUALITY_CHECK(ten_dominant_intervals[i].first, templ[i].first, @@ -75,17 +62,7 @@ BOOST_AUTO_TEST_CASE(check_dominant_intervals) { BOOST_AUTO_TEST_CASE(check_histogram_of_lengths) { Persistence_intervals p("data/file_with_diagram"); std::vector histogram = p.histogram_of_lengths(10); - std::vector template_histogram; - template_histogram.push_back(10); - template_histogram.push_back(5); - template_histogram.push_back(3); - template_histogram.push_back(4); - template_histogram.push_back(4); - template_histogram.push_back(3); - template_histogram.push_back(6); - template_histogram.push_back(1); - template_histogram.push_back(7); - template_histogram.push_back(2); + std::vector template_histogram{10, 5, 3, 4, 4, 3, 6, 1, 7, 2}; for (size_t i = 0; i != histogram.size(); ++i) { BOOST_CHECK(histogram[i] == template_histogram[i]); } @@ -94,17 +71,7 @@ BOOST_AUTO_TEST_CASE(check_histogram_of_lengths) { BOOST_AUTO_TEST_CASE(check_cumulative_histograms_of_lengths) { Persistence_intervals p("data/file_with_diagram"); std::vector cumulative_histogram = p.cumulative_histogram_of_lengths(10); - std::vector template_cumulative_histogram; - template_cumulative_histogram.push_back(10); - template_cumulative_histogram.push_back(15); - template_cumulative_histogram.push_back(18); - template_cumulative_histogram.push_back(22); - template_cumulative_histogram.push_back(26); - template_cumulative_histogram.push_back(29); - template_cumulative_histogram.push_back(35); - template_cumulative_histogram.push_back(36); - template_cumulative_histogram.push_back(43); - template_cumulative_histogram.push_back(45); + std::vector template_cumulative_histogram{10, 15, 18, 22, 26, 29, 35, 36, 43, 45}; for (size_t i = 0; i != cumulative_histogram.size(); ++i) { BOOST_CHECK(cumulative_histogram[i] == template_cumulative_histogram[i]); @@ -114,17 +81,8 @@ BOOST_AUTO_TEST_CASE(check_characteristic_function_of_diagram) { Persistence_intervals p("data/file_with_diagram"); std::pair min_max_ = p.get_x_range(); std::vector char_funct_diag = p.characteristic_function_of_diagram(min_max_.first, min_max_.second); - std::vector template_char_funct_diag; - template_char_funct_diag.push_back(0.370665); - template_char_funct_diag.push_back(0.84058); - template_char_funct_diag.push_back(1.24649); - template_char_funct_diag.push_back(1.3664); - template_char_funct_diag.push_back(1.34032); - template_char_funct_diag.push_back(1.31904); - template_char_funct_diag.push_back(1.14076); - template_char_funct_diag.push_back(0.991259); - template_char_funct_diag.push_back(0.800714); - template_char_funct_diag.push_back(0.0676303); + std::vector template_char_funct_diag{0.370665, 0.84058, 1.24649, 1.3664, 1.34032, + 1.31904, 1.14076, 0.991259, 0.800714, 0.0676303}; for (size_t i = 0; i != char_funct_diag.size(); ++i) { GUDHI_TEST_FLOAT_EQUALITY_CHECK(char_funct_diag[i], template_char_funct_diag[i], @@ -137,18 +95,8 @@ BOOST_AUTO_TEST_CASE(check_cumulative_characteristic_function_of_diagram) { std::pair min_max_ = p.get_x_range(); std::vector cumul_char_funct_diag = p.cumulative_characteristic_function_of_diagram(min_max_.first, min_max_.second); - std::vector template_char_funct_diag_cumul; - - template_char_funct_diag_cumul.push_back(0.370665); - template_char_funct_diag_cumul.push_back(1.21125); - template_char_funct_diag_cumul.push_back(2.45774); - template_char_funct_diag_cumul.push_back(3.82414); - template_char_funct_diag_cumul.push_back(5.16446); - template_char_funct_diag_cumul.push_back(6.4835); - template_char_funct_diag_cumul.push_back(7.62426); - template_char_funct_diag_cumul.push_back(8.61552); - template_char_funct_diag_cumul.push_back(9.41623); - template_char_funct_diag_cumul.push_back(9.48386); + std::vector template_char_funct_diag_cumul{0.370665, 1.21125, 2.45774, 3.82414, 5.16446, + 6.4835, 7.62426, 8.61552, 9.41623, 9.48386}; for (size_t i = 0; i != cumul_char_funct_diag.size(); ++i) { GUDHI_TEST_FLOAT_EQUALITY_CHECK(cumul_char_funct_diag[i], template_char_funct_diag_cumul[i], @@ -158,97 +106,29 @@ BOOST_AUTO_TEST_CASE(check_cumulative_characteristic_function_of_diagram) { BOOST_AUTO_TEST_CASE(check_compute_persistent_betti_numbers) { Persistence_intervals p("data/file_with_diagram"); - std::vector > pbns; - pbns.push_back(std::pair(0.0290362, 1)); - pbns.push_back(std::pair(0.0307676, 2)); - pbns.push_back(std::pair(0.0366312, 3)); - pbns.push_back(std::pair(0.0544614, 4)); - pbns.push_back(std::pair(0.0920033, 5)); - pbns.push_back(std::pair(0.104599, 6)); - pbns.push_back(std::pair(0.114718, 7)); - pbns.push_back(std::pair(0.117379, 8)); - pbns.push_back(std::pair(0.123493, 9)); - pbns.push_back(std::pair(0.133638, 10)); - pbns.push_back(std::pair(0.137798, 9)); - pbns.push_back(std::pair(0.149798, 10)); - pbns.push_back(std::pair(0.155421, 11)); - pbns.push_back(std::pair(0.158443, 12)); - pbns.push_back(std::pair(0.176956, 13)); - pbns.push_back(std::pair(0.183234, 12)); - pbns.push_back(std::pair(0.191069, 13)); - pbns.push_back(std::pair(0.191333, 14)); - pbns.push_back(std::pair(0.191836, 15)); - pbns.push_back(std::pair(0.192675, 16)); - pbns.push_back(std::pair(0.208564, 17)); - pbns.push_back(std::pair(0.218425, 18)); - pbns.push_back(std::pair(0.219902, 17)); - pbns.push_back(std::pair(0.23233, 16)); - pbns.push_back(std::pair(0.234558, 17)); - pbns.push_back(std::pair(0.237166, 16)); - pbns.push_back(std::pair(0.247352, 17)); - pbns.push_back(std::pair(0.267421, 18)); - pbns.push_back(std::pair(0.268093, 19)); - pbns.push_back(std::pair(0.278734, 18)); - pbns.push_back(std::pair(0.284722, 19)); - pbns.push_back(std::pair(0.284998, 20)); - pbns.push_back(std::pair(0.294069, 21)); - pbns.push_back(std::pair(0.306293, 22)); - pbns.push_back(std::pair(0.322361, 21)); - pbns.push_back(std::pair(0.323152, 22)); - pbns.push_back(std::pair(0.371021, 23)); - pbns.push_back(std::pair(0.372395, 24)); - pbns.push_back(std::pair(0.387744, 25)); - pbns.push_back(std::pair(0.435537, 26)); - pbns.push_back(std::pair(0.462911, 25)); - pbns.push_back(std::pair(0.483569, 26)); - pbns.push_back(std::pair(0.489209, 25)); - pbns.push_back(std::pair(0.517115, 24)); - pbns.push_back(std::pair(0.522197, 23)); - pbns.push_back(std::pair(0.532665, 22)); - pbns.push_back(std::pair(0.545262, 23)); - pbns.push_back(std::pair(0.587227, 22)); - pbns.push_back(std::pair(0.593036, 23)); - pbns.push_back(std::pair(0.602647, 24)); - pbns.push_back(std::pair(0.605044, 25)); - pbns.push_back(std::pair(0.621962, 24)); - pbns.push_back(std::pair(0.629449, 23)); - pbns.push_back(std::pair(0.636719, 22)); - pbns.push_back(std::pair(0.64957, 21)); - pbns.push_back(std::pair(0.650781, 22)); - pbns.push_back(std::pair(0.654951, 23)); - pbns.push_back(std::pair(0.683489, 24)); - pbns.push_back(std::pair(0.687172, 23)); - pbns.push_back(std::pair(0.69703, 22)); - pbns.push_back(std::pair(0.701174, 21)); - pbns.push_back(std::pair(0.717623, 22)); - pbns.push_back(std::pair(0.722023, 21)); - pbns.push_back(std::pair(0.722298, 20)); - pbns.push_back(std::pair(0.725347, 19)); - pbns.push_back(std::pair(0.73071, 18)); - pbns.push_back(std::pair(0.758355, 17)); - pbns.push_back(std::pair(0.770913, 18)); - pbns.push_back(std::pair(0.790833, 17)); - pbns.push_back(std::pair(0.821211, 16)); - pbns.push_back(std::pair(0.849305, 17)); - pbns.push_back(std::pair(0.853669, 16)); - pbns.push_back(std::pair(0.866659, 15)); - pbns.push_back(std::pair(0.872896, 16)); - pbns.push_back(std::pair(0.889597, 15)); - pbns.push_back(std::pair(0.900231, 14)); - pbns.push_back(std::pair(0.903847, 13)); - pbns.push_back(std::pair(0.906299, 12)); - pbns.push_back(std::pair(0.910852, 11)); - pbns.push_back(std::pair(0.93453, 10)); - pbns.push_back(std::pair(0.944757, 9)); - pbns.push_back(std::pair(0.947812, 8)); - pbns.push_back(std::pair(0.959154, 7)); - pbns.push_back(std::pair(0.975654, 6)); - pbns.push_back(std::pair(0.976719, 5)); - pbns.push_back(std::pair(0.977343, 4)); - pbns.push_back(std::pair(0.980129, 3)); - pbns.push_back(std::pair(0.987842, 2)); - pbns.push_back(std::pair(0.990127, 1)); - pbns.push_back(std::pair(0.994537, 0)); + std::vector > pbns{ {0.0290362, 1}, {0.0307676, 2}, {0.0366312, 3}, {0.0544614, 4}, + {0.0920033, 5}, {0.104599, 6}, {0.114718, 7}, {0.117379, 8}, + {0.123493, 9}, {0.133638, 10}, {0.137798, 9}, {0.149798, 10}, + {0.155421, 11}, {0.158443, 12}, {0.176956, 13}, {0.183234, 12}, + {0.191069, 13}, {0.191333, 14}, {0.191836, 15}, {0.192675, 16}, + {0.208564, 17}, {0.218425, 18}, {0.219902, 17}, {0.23233, 16}, + {0.234558, 17}, {0.237166, 16}, {0.247352, 17}, {0.267421, 18}, + {0.268093, 19}, {0.278734, 18}, {0.284722, 19}, {0.284998, 20}, + {0.294069, 21}, {0.306293, 22}, {0.322361, 21}, {0.323152, 22}, + {0.371021, 23}, {0.372395, 24}, {0.387744, 25}, {0.435537, 26}, + {0.462911, 25}, {0.483569, 26}, {0.489209, 25}, {0.517115, 24}, + {0.522197, 23}, {0.532665, 22}, {0.545262, 23}, {0.587227, 22}, + {0.593036, 23}, {0.602647, 24}, {0.605044, 25}, {0.621962, 24}, + {0.629449, 23}, {0.636719, 22}, {0.64957, 21}, {0.650781, 22}, + {0.654951, 23}, {0.683489, 24}, {0.687172, 23}, {0.69703, 22}, + {0.701174, 21}, {0.717623, 22}, {0.722023, 21}, {0.722298, 20}, + {0.725347, 19}, {0.73071, 18}, {0.758355, 17}, {0.770913, 18}, + {0.790833, 17}, {0.821211, 16}, {0.849305, 17}, {0.853669, 16}, + {0.866659, 15}, {0.872896, 16}, {0.889597, 15}, {0.900231, 14}, + {0.903847, 13}, {0.906299, 12}, {0.910852, 11}, {0.93453, 10}, + {0.944757, 9}, {0.947812, 8}, {0.959154, 7}, {0.975654, 6}, + {0.976719, 5}, {0.977343, 4}, {0.980129, 3}, {0.987842, 2}, + {0.990127, 1}, {0.994537, 0} }; std::vector > pbns_new = p.compute_persistent_betti_numbers(); for (size_t i = 0; i != pbns.size(); ++i) { @@ -260,17 +140,8 @@ BOOST_AUTO_TEST_CASE(check_compute_persistent_betti_numbers) { BOOST_AUTO_TEST_CASE(check_k_n_n) { Persistence_intervals p("data/file_with_diagram"); std::vector knn = p.k_n_n(5); - std::vector knn_template; - knn_template.push_back(1.04208); - knn_template.push_back(1.00344); - knn_template.push_back(0.979395); - knn_template.push_back(0.890643); - knn_template.push_back(0.874769); - knn_template.push_back(0.845787); - knn_template.push_back(0.819713); - knn_template.push_back(0.803984); - knn_template.push_back(0.799864); - knn_template.push_back(0.786945); + std::vector knn_template{1.04208, 1.00344, 0.979395, 0.890643, 0.874769, + 0.845787, 0.819713, 0.803984, 0.799864, 0.786945}; for (size_t i = 0; i != knn.size(); ++i) { GUDHI_TEST_FLOAT_EQUALITY_CHECK(knn[i], knn_template[i], Gudhi::Persistence_representations::epsi); -- cgit v1.2.3 From 0474f6a62622608b96eac3a553a081e148cbcabc Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 10 Dec 2019 22:51:08 +0100 Subject: Remove FindMPFR mechanism as the job is already done by CGAL --- src/cmake/modules/FindMPFR.cmake | 51 ---------------------- .../modules/GUDHI_third_party_libraries.cmake | 2 - src/python/CMakeLists.txt | 44 ++++++++----------- 3 files changed, 19 insertions(+), 78 deletions(-) delete mode 100644 src/cmake/modules/FindMPFR.cmake diff --git a/src/cmake/modules/FindMPFR.cmake b/src/cmake/modules/FindMPFR.cmake deleted file mode 100644 index 6c963272..00000000 --- a/src/cmake/modules/FindMPFR.cmake +++ /dev/null @@ -1,51 +0,0 @@ -# Try to find the MPFR libraries -# MPFR_FOUND - system has MPFR lib -# MPFR_INCLUDE_DIR - the MPFR include directory -# MPFR_LIBRARIES_DIR - Directory where the MPFR libraries are located -# MPFR_LIBRARIES - the MPFR libraries - -# TODO: support MacOSX - -include(FindPackageHandleStandardArgs) - -if(MPFR_INCLUDE_DIR) - set(MPFR_in_cache TRUE) -else() - set(MPFR_in_cache FALSE) -endif() -if(NOT MPFR_LIBRARIES) - set(MPFR_in_cache FALSE) -endif() - -# Is it already configured? -if (MPFR_in_cache) - set(MPFR_FOUND TRUE) -else() - find_path(MPFR_INCLUDE_DIR - NAMES mpfr.h - HINTS ENV MPFR_INC_DIR - ENV MPFR_DIR - ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include - PATH_SUFFIXES include - DOC "The directory containing the MPFR header files" - ) - - find_library(MPFR_LIBRARIES NAMES mpfr libmpfr-4 libmpfr-1 - HINTS ENV MPFR_LIB_DIR - ENV MPFR_DIR - ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/lib - PATH_SUFFIXES lib - DOC "Path to the MPFR library" - ) - - if ( MPFR_LIBRARIES ) - get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH CACHE ) - endif() - - # Attempt to load a user-defined configuration for MPFR if couldn't be found - if ( NOT MPFR_INCLUDE_DIR OR NOT MPFR_LIBRARIES_DIR ) - include( MPFRConfig OPTIONAL ) - endif() - - find_package_handle_standard_args(MPFR "DEFAULT_MSG" MPFR_LIBRARIES MPFR_INCLUDE_DIR) -endif() diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index d8c7a428..24a34150 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -6,8 +6,6 @@ if(NOT Boost_FOUND) message(FATAL_ERROR "NOTICE: This program requires Boost and will not be compiled.") endif(NOT Boost_FOUND) -find_package(MPFR) - find_package(GMP) if(GMP_FOUND) INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 13a8a909..1704f491 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -230,14 +230,12 @@ endif(CGAL_FOUND) # Test examples if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - if (MPFR_FOUND) - # Bottleneck and Alpha - add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" - -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) - endif(MPFR_FOUND) + # Bottleneck and Alpha + add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" + -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) if(MATPLOTLIB_FOUND AND NUMPY_FOUND) # Tangential add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test @@ -308,23 +306,19 @@ endif(CGAL_FOUND) endif (NOT CGAL_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - if (MPFR_FOUND) - # Alpha - add_test(NAME alpha_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") - - if(MATPLOTLIB_FOUND AND NUMPY_FOUND) - add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) - endif() - - add_gudhi_py_test(test_alpha_complex) - endif(MPFR_FOUND) + # Alpha + add_test(NAME alpha_complex_from_points_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") + if(MATPLOTLIB_FOUND AND NUMPY_FOUND) + add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 0.6) + endif() + add_gudhi_py_test(test_alpha_complex) endif (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) if (NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) -- cgit v1.2.3 From 7b2ac5ccd53ec8988854e5ac2c3c20176e0c24ed Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 16 Dec 2019 10:47:34 +0100 Subject: Fix MPFR when CGAL is not header only --- src/python/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 1704f491..b558d4c4 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -169,6 +169,10 @@ if(PYTHONINTERP_FOUND) add_gudhi_debug_info("MPFR_LIBRARIES = ${MPFR_LIBRARIES}") set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_MPFR', ") add_GUDHI_PYTHON_lib("${MPFR_LIBRARIES}") + # In case CGAL is not header only, all MPFR variables are set except MPFR_LIBRARIES_DIR - Just set it + if(NOT MPFR_LIBRARIES_DIR) + get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH) + endif(NOT MPFR_LIBRARIES_DIR) set(GUDHI_PYTHON_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}'${MPFR_LIBRARIES_DIR}', ") message("** Add mpfr ${MPFR_LIBRARIES}") endif(MPFR_FOUND) -- cgit v1.2.3 From 490a5774601e344bb732de5eab2a8cf6d5a7e81f Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 16 Dec 2019 13:38:58 +0100 Subject: Rollback exact version mechanism --- src/python/gudhi/alpha_complex.pyx | 11 +++-------- src/python/include/Alpha_complex_interface.h | 4 ++-- src/python/test/test_alpha_complex.py | 12 +++--------- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index bfb9783a..24e36bea 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -28,7 +28,7 @@ cdef extern from "Alpha_complex_interface.h" namespace "Gudhi": # 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, bool exact_version) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) # AlphaComplex python interface cdef class AlphaComplex: @@ -99,22 +99,17 @@ cdef class AlphaComplex: cdef vector[double] point = self.thisptr.get_point(vertex) return point - def create_simplex_tree(self, max_alpha_square = float('inf'), - exact_version = False): + 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, and there is very little point using anything else since it does not save time. :type max_alpha_square: float - :param exact_version: :code:`EXACT` computation version if set. - Default is false which means :code:`SAFE` version is used. - :type exact_version: bool :returns: A simplex tree created from the Delaunay Triangulation. :rtype: SimplexTree """ stree = SimplexTree() cdef intptr_t stree_int_ptr=stree.thisptr - self.thisptr.create_simplex_tree(stree_int_ptr, - max_alpha_square, exact_version) + self.thisptr.create_simplex_tree(stree_int_ptr, max_alpha_square) return stree diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index a7621f2b..e9bbadb0 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -60,8 +60,8 @@ class Alpha_complex_interface { return vd; } - void create_simplex_tree(Simplex_tree_interface<>* simplex_tree, double max_alpha_square, bool exact_version) { - alpha_complex_->create_complex(*simplex_tree, max_alpha_square, exact_version); + 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(); } diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index ab84daaa..9b27fff2 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -93,7 +93,7 @@ def test_filtered_alpha(): assert simplex_tree.get_star([0]) == [([0], 0.0), ([0, 1], 0.25), ([0, 2], 0.25)] assert simplex_tree.get_cofaces([0], 1) == [([0, 1], 0.25), ([0, 2], 0.25)] -def alpha_persistence_comparison(exact_version): +def test_safe_alpha_persistence_comparison(): #generate periodic signal time = np.arange(0, 10, 1) signal = [math.sin(x) for x in time] @@ -106,10 +106,10 @@ def alpha_persistence_comparison(exact_version): #build alpha complex and simplex tree alpha_complex1 = AlphaComplex(points=embedding1) - simplex_tree1 = alpha_complex1.create_simplex_tree(exact_version = exact_version) + simplex_tree1 = alpha_complex1.create_simplex_tree() alpha_complex2 = AlphaComplex(points=embedding2) - simplex_tree2 = alpha_complex2.create_simplex_tree(exact_version = exact_version) + simplex_tree2 = alpha_complex2.create_simplex_tree() diag1 = simplex_tree1.persistence() diag2 = simplex_tree2.persistence() @@ -117,9 +117,3 @@ def alpha_persistence_comparison(exact_version): for (first_p, second_p) in itertools.zip_longest(diag1, diag2): assert first_p[0] == pytest.approx(second_p[0]) assert first_p[1] == pytest.approx(second_p[1]) - -def test_exact_alpha_version(): - alpha_persistence_comparison(exact_version = True) - -def test_safe_alpha_version(): - alpha_persistence_comparison(exact_version = False) -- cgit v1.2.3 From b5510c0c362cd2bef79d82fd9809e654aea73957 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 16 Dec 2019 23:10:24 +0100 Subject: Add numpy ndarray to init a cubical and a periodic one --- src/python/doc/cubical_complex_user.rst | 4 +-- src/python/gudhi/cubical_complex.pyx | 27 ++++++++++++++----- src/python/gudhi/periodic_cubical_complex.pyx | 39 ++++++++++++++++++++++----- src/python/test/test_cubical_complex.py | 33 ++++++++++++++++++++--- 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/src/python/doc/cubical_complex_user.rst b/src/python/doc/cubical_complex_user.rst index b13b500e..21806038 100644 --- a/src/python/doc/cubical_complex_user.rst +++ b/src/python/doc/cubical_complex_user.rst @@ -142,8 +142,8 @@ Or it can be defined as follows: .. testcode:: from gudhi import PeriodicCubicalComplex as pcc - periodic_cc = pcc(dimensions=[3,3], - top_dimensional_cells= [0, 0, 0, 0, 1, 0, 0, 0, 0], + from numpy import array as np_array + periodic_cc = pcc(numpy_array = np_array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), periodic_dimensions=[True, False]) result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ repr(periodic_cc.num_simplices()) + ' simplices.' diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 011c407c..2ec0146a 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -5,7 +5,7 @@ from libcpp.string cimport string from libcpp cimport bool import os -from numpy import array as np_array +import numpy as np # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. @@ -47,7 +47,7 @@ cdef class CubicalComplex: # Fake constructor that does nothing but documenting the constructor def __init__(self, dimensions=None, top_dimensional_cells=None, - perseus_file=''): + numpy_array=None, perseus_file=''): """CubicalComplex constructor from dimensions and top_dimensional_cells or from a Perseus-style file name. @@ -58,16 +58,31 @@ cdef class CubicalComplex: Or + :param numpy_array: Filtration values in a d-array. + :type numpy_array: numpy ndarray + + Or + :param perseus_file: A Perseus-style file 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 == ''): + numpy_array=None, perseus_file=''): + if ((dimensions is not None) and (top_dimensional_cells is not None) + and (numpy_array is None) and (perseus_file == '')): 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 != ''): + elif ((dimensions is None) and (top_dimensional_cells is None) + and (numpy_array is not None) and (perseus_file == '')): + if isinstance(numpy_array, np.ndarray): + dimensions = list(numpy_array.shape) + top_dimensional_cells = numpy_array.flatten().tolist() + self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) + else: + print("numpy_array is not an instance of ndarray. It is a " + type(numpy_array)) + elif ((dimensions is None) and (top_dimensional_cells is None) + and (numpy_array is None) and (perseus_file != '')): if os.path.isfile(perseus_file): self.thisptr = new Bitmap_cubical_complex_base_interface(str.encode(perseus_file)) else: @@ -184,4 +199,4 @@ cdef class CubicalComplex: else: print("intervals_in_dim function requires persistence function" " to be launched first.") - return np_array(intervals_result) + return np.array(intervals_result) diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index c89055db..8318b7d3 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -5,7 +5,7 @@ from libcpp.string cimport string from libcpp cimport bool import os -from numpy import array as np_array +import numpy as np # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. @@ -47,7 +47,7 @@ cdef class PeriodicCubicalComplex: # Fake constructor that does nothing but documenting the constructor def __init__(self, dimensions=None, top_dimensional_cells=None, - periodic_dimensions=None, perseus_file=''): + numpy_array=None, periodic_dimensions=None, perseus_file=''): """PeriodicCubicalComplex constructor from dimensions and top_dimensional_cells or from a Perseus-style file name. @@ -60,16 +60,41 @@ cdef class PeriodicCubicalComplex: Or + :param numpy_array: Filtration values in a d-array. + :type numpy_array: numpy ndarray + :param periodic_dimensions: A list of top dimensional cells periodicity value. + :type periodic_dimensions: list of boolean + + Or + :param perseus_file: A Perseus-style file name. :type perseus_file: string """ # The real cython constructor def __cinit__(self, dimensions=None, top_dimensional_cells=None, - periodic_dimensions=None, perseus_file=''): - if (dimensions is not None) and (top_dimensional_cells is not None) and (periodic_dimensions is not None) and (perseus_file == ''): - self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells, periodic_dimensions) - elif (dimensions is None) and (top_dimensional_cells is None) and (periodic_dimensions is None) and (perseus_file != ''): + numpy_array=None, periodic_dimensions=None, + perseus_file=''): + if ((dimensions is not None) and (top_dimensional_cells is not None) + and (numpy_array is None) and (periodic_dimensions is not None) + and (perseus_file == '')): + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, + top_dimensional_cells, + periodic_dimensions) + elif ((dimensions is None) and (top_dimensional_cells is None) + and (numpy_array is not None) and (periodic_dimensions is not None) + and (perseus_file == '')): + if isinstance(numpy_array, np.ndarray): + dimensions = list(numpy_array.shape) + top_dimensional_cells = numpy_array.flatten().tolist() + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, + top_dimensional_cells, + periodic_dimensions) + else: + print("numpy_array is not an instance of ndarray. It is a " + type(numpy_array)) + elif ((dimensions is None) and (top_dimensional_cells is None) + and (numpy_array is None) and (periodic_dimensions is None) + and (perseus_file != '')): if os.path.isfile(perseus_file): self.thisptr = new Periodic_cubical_complex_base_interface(str.encode(perseus_file)) else: @@ -186,4 +211,4 @@ cdef class PeriodicCubicalComplex: else: print("intervals_in_dim function requires persistence function" " to be launched first.") - return np_array(intervals_result) + return np.array(intervals_result) diff --git a/src/python/test/test_cubical_complex.py b/src/python/test/test_cubical_complex.py index 68f54fbe..a37d7821 100755 --- a/src/python/test/test_cubical_complex.py +++ b/src/python/test/test_cubical_complex.py @@ -1,4 +1,5 @@ from gudhi import CubicalComplex +import numpy as np """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. @@ -56,7 +57,7 @@ def test_dimension_or_perseus_file_constructor(): assert cub.__is_persistence_defined() == False -def test_dimension_simple_constructor(): +def simple_constructor(cub): cub = CubicalComplex( dimensions=[3, 3], top_dimensional_cells=[1, 2, 3, 4, 5, 6, 7, 8, 9] ) @@ -67,12 +68,22 @@ def test_dimension_simple_constructor(): assert cub.betti_numbers() == [1, 0, 0] assert cub.persistent_betti_numbers(0, 1000) == [0, 0, 0] - -def test_user_case_simple_constructor(): +def test_simple_constructor_from_top_cells(): cub = CubicalComplex( dimensions=[3, 3], - top_dimensional_cells=[float("inf"), 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0], + top_dimensional_cells=[1, 2, 3, 4, 5, 6, 7, 8, 9], ) + simple_constructor(cub) + +def test_simple_constructor_from_numpy_array(): + cub = CubicalComplex( + numpy_array=np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + ) + simple_constructor(cub) + +def user_case_simple_constructor(cub): assert cub.__is_defined() == True assert cub.__is_persistence_defined() == False assert cub.persistence() == [(1, (0.0, 1.0)), (0, (0.0, float("inf")))] @@ -83,6 +94,20 @@ def test_user_case_simple_constructor(): ) assert other_cub.persistence() == [(1, (0.0, 1.0)), (0, (0.0, float("inf")))] +def test_user_case_simple_constructor_from_top_cells(): + cub = CubicalComplex( + dimensions=[3, 3], + top_dimensional_cells=[float("inf"), 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0], + ) + user_case_simple_constructor(cub) + +def test_user_case_simple_constructor_from_numpy_array(): + cub = CubicalComplex( + numpy_array=np.array([[float("inf"), 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 0.0]]) + ) + user_case_simple_constructor(cub) def test_dimension_file_constructor(): # Create test file -- cgit v1.2.3 From b63be266effe24646823acc59fe397021bb13a3e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 18 Dec 2019 10:44:17 +0100 Subject: Reuse top_dimensional_cells instead of numpy_array argument to create a cubical --- src/python/doc/cubical_complex_user.rst | 2 +- src/python/gudhi/cubical_complex.pyx | 25 ++++++++++--------- src/python/gudhi/periodic_cubical_complex.pyx | 35 +++++++++++++-------------- src/python/test/test_cubical_complex.py | 12 ++++----- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/python/doc/cubical_complex_user.rst b/src/python/doc/cubical_complex_user.rst index 21806038..d56c8789 100644 --- a/src/python/doc/cubical_complex_user.rst +++ b/src/python/doc/cubical_complex_user.rst @@ -143,7 +143,7 @@ Or it can be defined as follows: from gudhi import PeriodicCubicalComplex as pcc from numpy import array as np_array - periodic_cc = pcc(numpy_array = np_array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), + periodic_cc = pcc(top_dimensional_cells = np_array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), periodic_dimensions=[True, False]) result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ repr(periodic_cc.num_simplices()) + ' simplices.' diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 2ec0146a..1aa1164c 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -47,7 +47,7 @@ cdef class CubicalComplex: # Fake constructor that does nothing but documenting the constructor def __init__(self, dimensions=None, top_dimensional_cells=None, - numpy_array=None, perseus_file=''): + perseus_file=''): """CubicalComplex constructor from dimensions and top_dimensional_cells or from a Perseus-style file name. @@ -58,8 +58,9 @@ cdef class CubicalComplex: Or - :param numpy_array: Filtration values in a d-array. - :type numpy_array: numpy ndarray + :param top_dimensional_cells: A multidimensional array of cells + filtration values. + :type top_dimensional_cells: numpy ndarray Or @@ -69,20 +70,20 @@ cdef class CubicalComplex: # The real cython constructor def __cinit__(self, dimensions=None, top_dimensional_cells=None, - numpy_array=None, perseus_file=''): + perseus_file=''): if ((dimensions is not None) and (top_dimensional_cells is not None) - and (numpy_array is None) and (perseus_file == '')): + and (perseus_file == '')): self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) - elif ((dimensions is None) and (top_dimensional_cells is None) - and (numpy_array is not None) and (perseus_file == '')): - if isinstance(numpy_array, np.ndarray): - dimensions = list(numpy_array.shape) - top_dimensional_cells = numpy_array.flatten().tolist() + elif ((dimensions is None) and (top_dimensional_cells is not None) + and (perseus_file == '')): + if isinstance(top_dimensional_cells, np.ndarray): + dimensions = list(top_dimensional_cells.shape) + top_dimensional_cells = top_dimensional_cells.flatten().tolist() self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) else: - print("numpy_array is not an instance of ndarray. It is a " + type(numpy_array)) + print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) elif ((dimensions is None) and (top_dimensional_cells is None) - and (numpy_array is None) and (perseus_file != '')): + and (perseus_file != '')): if os.path.isfile(perseus_file): self.thisptr = new Bitmap_cubical_complex_base_interface(str.encode(perseus_file)) else: diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index 8318b7d3..e623058a 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -47,7 +47,7 @@ cdef class PeriodicCubicalComplex: # Fake constructor that does nothing but documenting the constructor def __init__(self, dimensions=None, top_dimensional_cells=None, - numpy_array=None, periodic_dimensions=None, perseus_file=''): + periodic_dimensions=None, perseus_file=''): """PeriodicCubicalComplex constructor from dimensions and top_dimensional_cells or from a Perseus-style file name. @@ -60,8 +60,9 @@ cdef class PeriodicCubicalComplex: Or - :param numpy_array: Filtration values in a d-array. - :type numpy_array: numpy ndarray + :param top_dimensional_cells: A multidimensional array of cells + filtration values. + :type top_dimensional_cells: numpy ndarray :param periodic_dimensions: A list of top dimensional cells periodicity value. :type periodic_dimensions: list of boolean @@ -73,35 +74,33 @@ cdef class PeriodicCubicalComplex: # The real cython constructor def __cinit__(self, dimensions=None, top_dimensional_cells=None, - numpy_array=None, periodic_dimensions=None, - perseus_file=''): + periodic_dimensions=None, perseus_file=''): if ((dimensions is not None) and (top_dimensional_cells is not None) - and (numpy_array is None) and (periodic_dimensions is not None) - and (perseus_file == '')): + and (periodic_dimensions is not None) and (perseus_file == '')): self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells, periodic_dimensions) - elif ((dimensions is None) and (top_dimensional_cells is None) - and (numpy_array is not None) and (periodic_dimensions is not None) - and (perseus_file == '')): - if isinstance(numpy_array, np.ndarray): - dimensions = list(numpy_array.shape) - top_dimensional_cells = numpy_array.flatten().tolist() + elif ((dimensions is None) and (top_dimensional_cells is not None) + and (periodic_dimensions is not None) and (perseus_file == '')): + if isinstance(top_dimensional_cells, np.ndarray): + dimensions = list(top_dimensional_cells.shape) + top_dimensional_cells = top_dimensional_cells.flatten().tolist() self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells, periodic_dimensions) else: - print("numpy_array is not an instance of ndarray. It is a " + type(numpy_array)) + print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) elif ((dimensions is None) and (top_dimensional_cells is None) - and (numpy_array is None) and (periodic_dimensions is None) - and (perseus_file != '')): + and (periodic_dimensions is None) and (perseus_file != '')): if os.path.isfile(perseus_file): self.thisptr = new Periodic_cubical_complex_base_interface(str.encode(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-style file name.") + print("CubicalComplex can be constructed from dimensions, " + "top_dimensional_cells and periodic_dimensions, or from " + "top_dimensional_cells and periodic_dimensions or from " + "a Perseus-style file name.") def __dealloc__(self): if self.thisptr != NULL: diff --git a/src/python/test/test_cubical_complex.py b/src/python/test/test_cubical_complex.py index a37d7821..6d4e0309 100755 --- a/src/python/test/test_cubical_complex.py +++ b/src/python/test/test_cubical_complex.py @@ -77,9 +77,9 @@ def test_simple_constructor_from_top_cells(): def test_simple_constructor_from_numpy_array(): cub = CubicalComplex( - numpy_array=np.array([[1, 2, 3], - [4, 5, 6], - [7, 8, 9]]) + top_dimensional_cells=np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) ) simple_constructor(cub) @@ -103,9 +103,9 @@ def test_user_case_simple_constructor_from_top_cells(): def test_user_case_simple_constructor_from_numpy_array(): cub = CubicalComplex( - numpy_array=np.array([[float("inf"), 0.0, 0.0], - [0.0, 1.0, 0.0], - [0.0, 0.0, 0.0]]) + top_dimensional_cells=np.array([[float("inf"), 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 0.0]]) ) user_case_simple_constructor(cub) -- cgit v1.2.3 From 32a9c5e4df26e59f5f376e54c05c7bec92012cff Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 18 Dec 2019 10:57:31 +0100 Subject: use ravel instead of flatten (that makes a copy) and no more converting to a list --- src/python/gudhi/cubical_complex.pyx | 4 ++-- src/python/gudhi/periodic_cubical_complex.pyx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 1aa1164c..756a9dab 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -77,8 +77,8 @@ cdef class CubicalComplex: elif ((dimensions is None) and (top_dimensional_cells is not None) and (perseus_file == '')): if isinstance(top_dimensional_cells, np.ndarray): - dimensions = list(top_dimensional_cells.shape) - top_dimensional_cells = top_dimensional_cells.flatten().tolist() + dimensions = top_dimensional_cells.shape + top_dimensional_cells = top_dimensional_cells.ravel(order='C') self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) else: print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index e623058a..c3d64123 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -83,8 +83,8 @@ cdef class PeriodicCubicalComplex: elif ((dimensions is None) and (top_dimensional_cells is not None) and (periodic_dimensions is not None) and (perseus_file == '')): if isinstance(top_dimensional_cells, np.ndarray): - dimensions = list(top_dimensional_cells.shape) - top_dimensional_cells = top_dimensional_cells.flatten().tolist() + dimensions = top_dimensional_cells.shape + top_dimensional_cells = top_dimensional_cells.ravel(order='C') self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells, periodic_dimensions) -- cgit v1.2.3 From ba406558f707f55b638be92d197ae3039595b29a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 20 Dec 2019 16:57:36 +0100 Subject: Fix dimension cell linearization and test connected sublevel sets --- src/python/gudhi/cubical_complex.pyx | 2 +- src/python/gudhi/periodic_cubical_complex.pyx | 2 +- src/python/test/test_cubical_complex.py | 28 ++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 756a9dab..04b22921 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -78,7 +78,7 @@ cdef class CubicalComplex: and (perseus_file == '')): if isinstance(top_dimensional_cells, np.ndarray): dimensions = top_dimensional_cells.shape - top_dimensional_cells = top_dimensional_cells.ravel(order='C') + top_dimensional_cells = top_dimensional_cells.ravel(order='F') self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) else: print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index c3d64123..1d6f1e59 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -84,7 +84,7 @@ cdef class PeriodicCubicalComplex: and (periodic_dimensions is not None) and (perseus_file == '')): if isinstance(top_dimensional_cells, np.ndarray): dimensions = top_dimensional_cells.shape - top_dimensional_cells = top_dimensional_cells.ravel(order='C') + top_dimensional_cells = top_dimensional_cells.ravel(order='F') self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, top_dimensional_cells, periodic_dimensions) diff --git a/src/python/test/test_cubical_complex.py b/src/python/test/test_cubical_complex.py index 6d4e0309..121da12a 100755 --- a/src/python/test/test_cubical_complex.py +++ b/src/python/test/test_cubical_complex.py @@ -1,4 +1,4 @@ -from gudhi import CubicalComplex +from gudhi import CubicalComplex, PeriodicCubicalComplex import numpy as np """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. @@ -121,3 +121,29 @@ def test_dimension_file_constructor(): assert cub.__is_persistence_defined() == True assert cub.betti_numbers() == [1, 0, 0] assert cub.persistent_betti_numbers(0, 1000) == [1, 0, 0] + +def test_connected_sublevel_sets(): + array_cells = np.array([[3, 3], [2, 2], [4, 4]]) + linear_cells = [3, 3, 2, 2, 4, 4] + dimensions = [2, 3] + periodic_dimensions = [False, False] + # with a numpy array version + cub = CubicalComplex(top_dimensional_cells = array_cells) + assert cub.persistence() == [(0, (2.0, float("inf")))] + assert cub.betti_numbers() == [1, 0, 0] + # with vector of dimensions + cub = CubicalComplex(dimensions = dimensions, + top_dimensional_cells = linear_cells) + assert cub.persistence() == [(0, (2.0, float("inf")))] + assert cub.betti_numbers() == [1, 0, 0] + # periodic with a numpy array version + cub = PeriodicCubicalComplex(top_dimensional_cells = array_cells, + periodic_dimensions = periodic_dimensions) + assert cub.persistence() == [(0, (2.0, float("inf")))] + assert cub.betti_numbers() == [1, 0, 0] + # periodic with vector of dimensions + cub = PeriodicCubicalComplex(dimensions = dimensions, + top_dimensional_cells = linear_cells, + periodic_dimensions = periodic_dimensions) + assert cub.persistence() == [(0, (2.0, float("inf")))] + assert cub.betti_numbers() == [1, 0, 0] -- cgit v1.2.3 From 8c30016a3c56522014254dc571ed4fe81f31e02b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 25 Dec 2019 22:18:20 +0100 Subject: Add Hera as a submodule --- .gitmodules | 3 +++ ext/hera | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 ext/hera diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..6e8b3ab1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ext/hera"] + path = ext/hera + url = https://bitbucket.org/grey_narn/hera.git diff --git a/ext/hera b/ext/hera new file mode 160000 index 00000000..5a59cfad --- /dev/null +++ b/ext/hera @@ -0,0 +1 @@ +Subproject commit 5a59cfad45c155f8af89c2c6d82db2848d52a953 -- cgit v1.2.3 From 15f222eecf3b427c59f09ec3bec17983377d96a2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 25 Dec 2019 22:27:52 +0100 Subject: Copy hera headers in user_version --- src/cmake/modules/GUDHI_user_version_target.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake index 4fa74330..2527dee9 100644 --- a/src/cmake/modules/GUDHI_user_version_target.cmake +++ b/src/cmake/modules/GUDHI_user_version_target.cmake @@ -56,6 +56,9 @@ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI) +add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E + copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include ${GUDHI_USER_VERSION_DIR}/hera/wasserstein) + set(GUDHI_DIRECTORIES "doc;example;concept;utilities") set(GUDHI_INCLUDE_DIRECTORIES "include/gudhi") @@ -95,4 +98,4 @@ foreach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST}) endforeach() endforeach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) -endforeach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST}) \ No newline at end of file +endforeach(GUDHI_MODULE ${GUDHI_MODULES_FULL_LIST}) -- cgit v1.2.3 From c2e22942c35e894d5c1ddc429eb32687c61538c8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 10:22:47 +0100 Subject: Basic binding for wasserstein_distance --- src/cmake/modules/GUDHI_user_version_target.cmake | 2 +- src/python/gudhi/hera.cc | 48 +++++++++++++++++++++++ src/python/setup.py.in | 26 +++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/python/gudhi/hera.cc diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake index 2527dee9..9a05386f 100644 --- a/src/cmake/modules/GUDHI_user_version_target.cmake +++ b/src/cmake/modules/GUDHI_user_version_target.cmake @@ -57,7 +57,7 @@ add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/GudhUI ${GUDHI_USER_VERSION_DIR}/GudhUI) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include ${GUDHI_USER_VERSION_DIR}/hera/wasserstein) + copy_directory ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include ${GUDHI_USER_VERSION_DIR}/ext/hera/geom_matching/wasserstein/include) set(GUDHI_DIRECTORIES "doc;example;concept;utilities") diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc new file mode 100644 index 00000000..7cef9425 --- /dev/null +++ b/src/python/gudhi/hera.cc @@ -0,0 +1,48 @@ +#include +#include + +#include + +#include + +#include + +namespace py = pybind11; +typedef py::array_t Dgm; + +namespace hera { +template <> struct DiagramTraits{ + //using Container = void; + using PointType = std::array; + using RealType = double; + + static RealType get_x(const PointType& p) { return std::get<0>(p); } + static RealType get_y(const PointType& p) { return std::get<1>(p); } +}; +} + +double wasserstein_distance( + Dgm d1, + Dgm d2) +{ + py::buffer_info buf1 = d1.request(); + py::buffer_info buf2 = d2.request(); + if(buf1.ndim!=2 || buf1.shape[1]!=2) + throw std::runtime_error("Diagram 1 must be an array of size n x 2"); + if(buf2.ndim!=2 || buf2.shape[1]!=2) + throw std::runtime_error("Diagram 1 must be an array of size n x 2"); + typedef hera::DiagramTraits::PointType Point; + auto p1 = (Point*)buf1.ptr; + auto p2 = (Point*)buf2.ptr; + auto diag1 = boost::make_iterator_range(p1, p1+buf1.shape[0]); + auto diag2 = boost::make_iterator_range(p2, p2+buf2.shape[0]); + + hera::AuctionParams params; + return hera::wasserstein_dist(diag1, diag2, params); +} + +PYBIND11_MODULE(hera, m) { + m.def("wasserstein_distance", &wasserstein_distance, R"pbdoc( + Compute the Wasserstein distance between two diagrams + )pbdoc"); +} diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 3f1d4424..f7ffd146 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -26,6 +26,19 @@ library_dirs=[@GUDHI_PYTHON_LIBRARY_DIRS@] include_dirs = [numpy_get_include(), '@CMAKE_CURRENT_SOURCE_DIR@/gudhi/', @GUDHI_PYTHON_INCLUDE_DIRS@] runtime_library_dirs=[@GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS@] +class get_pybind_include(object): + """Helper class to determine the pybind11 include path + The purpose of this class is to postpone importing pybind11 + until it is actually installed, so that the ``get_include()`` + method can be invoked. """ + + def __init__(self, user=False): + self.user = user + + def __str__(self): + import pybind11 + return pybind11.get_include(self.user) + # Create ext_modules list from module list ext_modules = [] for module in modules: @@ -39,6 +52,15 @@ for module in modules: library_dirs=library_dirs, include_dirs=include_dirs, runtime_library_dirs=runtime_library_dirs,)) +ext_modules.append(Extension( + 'gudhi.hera', + sources = [source_dir + 'hera.cc'], + language = 'c++', + extra_compile_args=extra_compile_args + ['-fvisibility=hidden'], # FIXME + include_dirs = include_dirs + + ['@CMAKE_SOURCE_DIR@/ext/hera/geom_matching/wasserstein/include', + get_pybind_include(False), get_pybind_include(True)] + )) setup( name = 'gudhi', @@ -48,6 +70,6 @@ setup( version='@GUDHI_VERSION@', url='http://gudhi.gforge.inria.fr/', ext_modules = cythonize(ext_modules), - install_requires = ['cython','numpy >= 1.9',], - setup_requires = ['numpy >= 1.9',], + install_requires = ['cython','numpy >= 1.9','pybind11',], + setup_requires = ['numpy >= 1.9','pybind11',], ) -- cgit v1.2.3 From 56cee2efaa26e734c9555b5b0bb9dfbbc4baaed8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 17:33:51 +0100 Subject: Fix compilation --- src/python/CMakeLists.txt | 1 + src/python/setup.py.in | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index b558d4c4..bec38305 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -86,6 +86,7 @@ if(PYTHONINTERP_FOUND) endif(MSVC) if(CMAKE_COMPILER_IS_GNUCXX) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") + set(GUDHI_PYBIND11_EXTRA_COMPILE_ARGS "${GUDHI_PYBIND11_EXTRA_COMPILE_ARGS}'-fvisibility=hidden', ") endif(CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_CXX_COMPILER_ID MATCHES Intel) set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") diff --git a/src/python/setup.py.in b/src/python/setup.py.in index f7ffd146..2d96c57b 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -26,6 +26,7 @@ library_dirs=[@GUDHI_PYTHON_LIBRARY_DIRS@] include_dirs = [numpy_get_include(), '@CMAKE_CURRENT_SOURCE_DIR@/gudhi/', @GUDHI_PYTHON_INCLUDE_DIRS@] runtime_library_dirs=[@GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS@] +# Copied from https://github.com/pybind/python_example/blob/master/setup.py class get_pybind_include(object): """Helper class to determine the pybind11 include path The purpose of this class is to postpone importing pybind11 @@ -52,14 +53,16 @@ for module in modules: library_dirs=library_dirs, include_dirs=include_dirs, runtime_library_dirs=runtime_library_dirs,)) +ext_modules = cythonize(ext_modules) + ext_modules.append(Extension( 'gudhi.hera', sources = [source_dir + 'hera.cc'], language = 'c++', - extra_compile_args=extra_compile_args + ['-fvisibility=hidden'], # FIXME include_dirs = include_dirs + ['@CMAKE_SOURCE_DIR@/ext/hera/geom_matching/wasserstein/include', - get_pybind_include(False), get_pybind_include(True)] + get_pybind_include(False), get_pybind_include(True)], + extra_compile_args=extra_compile_args + [@GUDHI_PYBIND11_EXTRA_COMPILE_ARGS@], )) setup( @@ -69,7 +72,7 @@ setup( author_email='gudhi-contact@lists.gforge.inria.fr', version='@GUDHI_VERSION@', url='http://gudhi.gforge.inria.fr/', - ext_modules = cythonize(ext_modules), + ext_modules = ext_modules, install_requires = ['cython','numpy >= 1.9','pybind11',], setup_requires = ['numpy >= 1.9','pybind11',], ) -- cgit v1.2.3 From 4922f305b7601d9e5d7eb39c73a88ee53bf1ca87 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 18:31:47 +0100 Subject: Update doc --- src/python/doc/wasserstein_distance_user.rst | 14 +++++++++++--- src/python/gudhi/hera.cc | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index a049cfb5..13f6f1af 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -9,12 +9,20 @@ Definition .. include:: wasserstein_distance_sum.inc -This implementation is based on ideas from "Large Scale Computation of Means and Cluster for Persistence Diagrams via Optimal Transport". +Functions +--------- +This implementation is based on ideas from "Large Scale Computation of Means +and Cluster for Persistence Diagrams via Optimal Transport". -Function --------- .. autofunction:: gudhi.wasserstein.wasserstein_distance +This other implementation comes from `Hera +`_ and is based on `"Geometry +Helps to Compare Persistence Diagrams." +`_ by Michael Kerber, Dmitriy +Morozov, and Arnur Nigmetov, at ALENEX 2016. + +.. autofunction:: gudhi.hera.wasserstein_distance Basic example ------------- diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc index 7cef9425..04f5990f 100644 --- a/src/python/gudhi/hera.cc +++ b/src/python/gudhi/hera.cc @@ -42,7 +42,13 @@ double wasserstein_distance( } PYBIND11_MODULE(hera, m) { - m.def("wasserstein_distance", &wasserstein_distance, R"pbdoc( + m.def("wasserstein_distance", &wasserstein_distance, + py::arg("X"), py::arg("Y"), + R"pbdoc( Compute the Wasserstein distance between two diagrams + + Parameters: + X (n x 2 numpy array): First diagram + Y (n x 2 numpy array): Second diagram )pbdoc"); } -- cgit v1.2.3 From 003b33403ab92e25cab2b9e51b36528d5cc6112c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 19:30:04 +0100 Subject: Check for pybind11 --- .appveyor.yml | 2 +- .travis.yml | 2 +- .../modules/GUDHI_third_party_libraries.cmake | 1 + src/python/CMakeLists.txt | 51 ++++++++++++---------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4a76ea0a..3a33ed62 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -48,7 +48,7 @@ install: - pip --version - python -m pip install --upgrade pip - pip install -U setuptools numpy matplotlib scipy Cython pytest - - pip install -U POT + - pip install -U POT pybind11 build_script: - mkdir build diff --git a/.travis.yml b/.travis.yml index d6c82e70..4b4c7068 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,7 +59,7 @@ before_cache: install: - python3 -m pip install --upgrade pip setuptools wheel - python3 -m pip install --user pytest Cython sphinx sphinxcontrib-bibtex sphinx-paramlinks matplotlib numpy scipy scikit-learn - - python3 -m pip install --user POT + - python3 -m pip install --user POT pybind11 script: - rm -rf build diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 24a34150..cb9f9033 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -127,6 +127,7 @@ if( PYTHONINTERP_FOUND ) find_python_module("sphinx") find_python_module("sklearn") find_python_module("ot") + find_python_module("pybind11") endif() if(NOT GUDHI_PYTHON_PATH) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index bec38305..edb1ba02 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -407,32 +407,37 @@ endif(CGAL_FOUND) if(SCIPY_FOUND) if(SKLEARN_FOUND) if(OT_FOUND) - if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") - # User warning - Sphinx is a static pages generator, and configured to work fine with user_version - # Images and biblio warnings because not found on developper version - if (GUDHI_PYTHON_PATH STREQUAL "src/python") - set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss") - endif() - # sphinx target requires gudhi.so, because conf.py reads gudhi version from it - add_custom_target(sphinx - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx - DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" - COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) + if(PYBIND11_FOUND) + if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") + # User warning - Sphinx is a static pages generator, and configured to work fine with user_version + # Images and biblio warnings because not found on developper version + if (GUDHI_PYTHON_PATH STREQUAL "src/python") + set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developper version. Images and biblio will miss") + endif() + # sphinx target requires gudhi.so, because conf.py reads gudhi version from it + add_custom_target(sphinx + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) - add_test(NAME sphinx_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) + add_test(NAME sphinx_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" + ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) - # Set missing or not modules - set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES") - else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) - message("++ Python documentation module will not be compiled because it requires a Eigen3 and CGAL version >= 4.11.0") + # Set missing or not modules + set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES") + else(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + message("++ Python documentation module will not be compiled because it requires a Eigen3 and CGAL version >= 4.11.0") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") + endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + else(PYBIND11_FOUND) + message("++ Python documentation module will not be compiled because pybind11 was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) + endif(PYBIND11_FOUND) else(OT_FOUND) message("++ Python documentation module will not be compiled because POT was not found") set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") -- cgit v1.2.3 From ba35ad0281f89449655a0144284f50e22e870ab4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 19:32:34 +0100 Subject: Install pybind11 in CircleCI --- Dockerfile_for_circleci_image | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index f0c73d76..c9342bf4 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -43,6 +43,7 @@ RUN apt-get install -y make \ python3-pip \ python3-pytest \ python3-tk \ + python3-pybind11 \ libfreetype6-dev \ pkg-config -- cgit v1.2.3 From 7568b34c56e6a6102507df1be0029a0259f2afa7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 20:37:19 +0100 Subject: Checkout submodules in circleci --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e45bc14..51b6c019 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,6 +50,8 @@ jobs: - run: name: Build and test python module. Generates and tests the python documentation command: | + git submodule init + git submodule update mkdir build; cd build; cmake -DUSER_VERSION_DIR=version ..; @@ -74,6 +76,8 @@ jobs: - run: name: Generates the C++ documentation with doxygen command: | + git submodule init + git submodule update mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_TEST=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=OFF -DUSER_VERSION_DIR=version ..; @@ -93,4 +97,4 @@ workflows: - tests - utils - python - - doxygen \ No newline at end of file + - doxygen -- cgit v1.2.3 From 7e9777c568d32a2c3d5c6fd85bbbf882bb121b83 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 26 Dec 2019 20:50:07 +0100 Subject: I am also going to need git to checkout submodules, apparently --- Dockerfile_for_circleci_image | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index c9342bf4..ff4e6018 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -25,6 +25,7 @@ ENV LC_ALL en_US.UTF-8 # Required for Gudhi compilation RUN apt-get install -y make \ + git \ g++ \ cmake \ graphviz \ -- cgit v1.2.3 From b8701d847db37b80a58770e00b91494889df00e8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 27 Dec 2019 00:56:08 +0100 Subject: Expose more options --- src/python/doc/wasserstein_distance_user.rst | 4 ++-- src/python/gudhi/hera.cc | 31 +++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 13f6f1af..6cd7f3a0 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -17,8 +17,8 @@ and Cluster for Persistence Diagrams via Optimal Transport". .. autofunction:: gudhi.wasserstein.wasserstein_distance This other implementation comes from `Hera -`_ and is based on `"Geometry -Helps to Compare Persistence Diagrams." +`_ (BSD-3-Clause) and is +based on `"Geometry Helps to Compare Persistence Diagrams." `_ by Michael Kerber, Dmitriy Morozov, and Arnur Nigmetov, at ALENEX 2016. diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc index 04f5990f..898040fb 100644 --- a/src/python/gudhi/hera.cc +++ b/src/python/gudhi/hera.cc @@ -12,7 +12,6 @@ typedef py::array_t Dgm; namespace hera { template <> struct DiagramTraits{ - //using Container = void; using PointType = std::array; using RealType = double; @@ -22,15 +21,17 @@ template <> struct DiagramTraits{ } double wasserstein_distance( - Dgm d1, - Dgm d2) + Dgm d1, Dgm d2, + double wasserstein_power, double internal_p, + double delta) { py::buffer_info buf1 = d1.request(); py::buffer_info buf2 = d2.request(); - if(buf1.ndim!=2 || buf1.shape[1]!=2) - throw std::runtime_error("Diagram 1 must be an array of size n x 2"); - if(buf2.ndim!=2 || buf2.shape[1]!=2) + // shape (n,2) or (0) for empty + if((buf1.ndim!=2 || buf1.shape[1]!=2) && (buf1.ndim!=1 || buf1.shape[0]!=0)) throw std::runtime_error("Diagram 1 must be an array of size n x 2"); + if((buf2.ndim!=2 || buf2.shape[1]!=2) && (buf2.ndim!=1 || buf2.shape[0]!=0)) + throw std::runtime_error("Diagram 2 must be an array of size n x 2"); typedef hera::DiagramTraits::PointType Point; auto p1 = (Point*)buf1.ptr; auto p2 = (Point*)buf2.ptr; @@ -38,17 +39,33 @@ double wasserstein_distance( auto diag2 = boost::make_iterator_range(p2, p2+buf2.shape[0]); hera::AuctionParams params; + params.wasserstein_power = wasserstein_power; + // hera encodes infinity as -1... + if(std::isinf(internal_p)) internal_p = hera::get_infinity(); + params.internal_p = internal_p; + params.delta = delta; + // The extra parameters are purposedly not exposed for now. return hera::wasserstein_dist(diag1, diag2, params); } PYBIND11_MODULE(hera, m) { m.def("wasserstein_distance", &wasserstein_distance, py::arg("X"), py::arg("Y"), + // Should we name those q, p and d instead? + py::arg("wasserstein_power") = 1, + py::arg("internal_p") = std::numeric_limits::infinity(), + py::arg("delta") = .01, R"pbdoc( - Compute the Wasserstein distance between two diagrams + Compute the Wasserstein distance between two diagrams. Points at infinity are supported. Parameters: X (n x 2 numpy array): First diagram Y (n x 2 numpy array): Second diagram + wasserstein_power (float): Wasserstein degree W_q + internal_p (float): Internal Minkowski norm L^p in R^2 + delta (float): Relative error 1+delta + + Returns: + float: Approximate Wasserstein distance W_q(X,Y) )pbdoc"); } -- cgit v1.2.3 From ec8b343dafdb70acc4a948ef737d83a3cc4d9f7b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 27 Dec 2019 12:43:03 +0100 Subject: Handle submodules in appveyor --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index 3a33ed62..34f42dea 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -39,6 +39,7 @@ init: install: + - git submodule update --init - vcpkg install tbb:x64-windows boost-disjoint-sets:x64-windows boost-serialization:x64-windows boost-date-time:x64-windows boost-system:x64-windows boost-filesystem:x64-windows boost-units:x64-windows boost-thread:x64-windows boost-program-options:x64-windows eigen3:x64-windows mpfr:x64-windows mpir:x64-windows cgal:x64-windows - SET PATH=c:\Tools\vcpkg\installed\x64-windows\bin;%PATH% - SET PATH=%PYTHON%;%PYTHON%\Scripts;%PYTHON%\Library\bin;%PATH% -- cgit v1.2.3 From ef4a688e07e070b190caf267a64fedd607830ee7 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 2 Jan 2020 20:25:04 +0100 Subject: Update Hera --- ext/hera | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/hera b/ext/hera index 5a59cfad..9a899718 160000 --- a/ext/hera +++ b/ext/hera @@ -1 +1 @@ -Subproject commit 5a59cfad45c155f8af89c2c6d82db2848d52a953 +Subproject commit 9a89971855acefe39dce0e2adadf53b88ca8f683 -- cgit v1.2.3 From d316f8ca62a3335d530784a71b4110bc2219c2dd Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 3 Jan 2020 22:02:48 +0100 Subject: Remove implicit this capture in [=] --- src/Nerve_GIC/include/gudhi/GIC.h | 2 +- src/Simplex_tree/include/gudhi/Simplex_tree.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h index b8169c59..a47d6889 100644 --- a/src/Nerve_GIC/include/gudhi/GIC.h +++ b/src/Nerve_GIC/include/gudhi/GIC.h @@ -707,7 +707,7 @@ class Cover_complex { // Sort points according to function values std::vector points(n); for (int i = 0; i < n; i++) points[i] = i; - std::sort(points.begin(), points.end(), [=](const int & p1, const int & p2){return (this->func[p1] < this->func[p2]);}); + std::sort(points.begin(), points.end(), [this](int p1, int p2){return (this->func[p1] < this->func[p2]);}); int id = 0; int pos = 0; diff --git a/src/Simplex_tree/include/gudhi/Simplex_tree.h b/src/Simplex_tree/include/gudhi/Simplex_tree.h index fafdb01c..76608008 100644 --- a/src/Simplex_tree/include/gudhi/Simplex_tree.h +++ b/src/Simplex_tree/include/gudhi/Simplex_tree.h @@ -1378,7 +1378,7 @@ class Simplex_tree { private: bool rec_prune_above_filtration(Siblings* sib, Filtration_value filt) { auto&& list = sib->members(); - auto last = std::remove_if(list.begin(), list.end(), [=](Dit_value_t& simplex) { + auto last = std::remove_if(list.begin(), list.end(), [this,filt](Dit_value_t& simplex) { if (simplex.second.filtration() <= filt) return false; if (has_children(&simplex)) rec_delete(simplex.second.children()); // dimension may need to be lowered -- cgit v1.2.3 From bcc49c54943e20b117a3a83579d94f6c1b0efd04 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 4 Jan 2020 12:50:14 +0100 Subject: Link the doc for subsampling & point file readers, some reorg --- src/python/doc/diagram_readers_ref.rst | 11 ++++++++++ src/python/doc/index.rst | 40 ++++++++++++++++------------------ src/python/doc/point_cloud.rst | 22 +++++++++++++++++++ src/python/doc/point_cloud_sum.inc | 15 +++++++++++++ src/python/doc/reader_utils_ref.rst | 15 ------------- src/python/gudhi/off_reader.pyx | 2 +- src/python/gudhi/reader_utils.pyx | 6 ++--- src/python/gudhi/subsampling.pyx | 12 +++++----- 8 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 src/python/doc/diagram_readers_ref.rst create mode 100644 src/python/doc/point_cloud.rst create mode 100644 src/python/doc/point_cloud_sum.inc delete mode 100644 src/python/doc/reader_utils_ref.rst diff --git a/src/python/doc/diagram_readers_ref.rst b/src/python/doc/diagram_readers_ref.rst new file mode 100644 index 00000000..c79daf9c --- /dev/null +++ b/src/python/doc/diagram_readers_ref.rst @@ -0,0 +1,11 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + +================================ +Diagram readers reference manual +================================ + +.. autofunction:: gudhi.read_persistence_intervals_grouped_by_dimension + +.. autofunction:: gudhi.read_persistence_intervals_in_dimension diff --git a/src/python/doc/index.rst b/src/python/doc/index.rst index c36a578f..9513deb0 100644 --- a/src/python/doc/index.rst +++ b/src/python/doc/index.rst @@ -6,8 +6,8 @@ GUDHI Python modules documentation :alt: Gudhi banner :figclass: align-center -Complexes -********* +Data structures for cell complexes +********************************** Cubical complexes ================= @@ -17,18 +17,26 @@ Cubical complexes Simplicial complexes ==================== +Simplex tree +------------ + +.. include:: simplex_tree_sum.inc + +Filtrations and reconstructions +******************************* + Alpha complex -------------- +============= .. include:: alpha_complex_sum.inc Rips complex ------------- +============ .. include:: rips_complex_sum.inc Witness complex ---------------- +=============== .. include:: witness_complex_sum.inc @@ -37,16 +45,10 @@ Cover complexes .. include:: nerve_gic_complex_sum.inc -Data structures and basic operations -************************************ - -Data structures -=============== - -Simplex tree ------------- +Tangential complex +================== -.. include:: simplex_tree_sum.inc +.. include:: tangential_complex_sum.inc Topological descriptors computation *********************************** @@ -56,14 +58,10 @@ Persistence cohomology .. include:: persistent_cohomology_sum.inc -Manifold reconstruction -*********************** - -Tangential complex -================== - -.. include:: tangential_complex_sum.inc +Point cloud utilities +********************* +.. include:: point_cloud_sum.inc Topological descriptors tools ***************************** diff --git a/src/python/doc/point_cloud.rst b/src/python/doc/point_cloud.rst new file mode 100644 index 00000000..6a74d253 --- /dev/null +++ b/src/python/doc/point_cloud.rst @@ -0,0 +1,22 @@ +:orphan: + +.. To get rid of WARNING: document isn't included in any toctree + +============================ +Point cloud utilities manual +============================ + +File Readers +------------ + +.. autofunction:: gudhi.read_off + +.. autofunction:: gudhi.read_lower_triangular_matrix_from_csv_file + +Subsampling +----------- + +.. automodule:: gudhi.subsampling + :members: + :special-members: + :show-inheritance: diff --git a/src/python/doc/point_cloud_sum.inc b/src/python/doc/point_cloud_sum.inc new file mode 100644 index 00000000..cefcf1c8 --- /dev/null +++ b/src/python/doc/point_cloud_sum.inc @@ -0,0 +1,15 @@ +.. table:: + :widths: 30 50 20 + + +----------------------------------------------------------------+------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ + | :math:`(x_1, x_2, \ldots, x_d)` | Utilities to process point clouds: read from file, subsample, etc. | :Author: Vincent Rouvreau | + | :math:`(y_1, y_2, \ldots, y_d)` | | | + | | | :Introduced in: GUDHI 2.0.0 | + | | | | + | | | :Copyright: MIT (`GPL v3 `_) | + | | Parts of this package require CGAL. | | + | | | :Requires: `Eigen `__ :math:`\geq` 3.1.0 and `CGAL `__ :math:`\geq` 4.11.0 | + | | | | + +----------------------------------------------------------------+------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ + | * :doc:`point_cloud` | + +----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/src/python/doc/reader_utils_ref.rst b/src/python/doc/reader_utils_ref.rst deleted file mode 100644 index f3ecebad..00000000 --- a/src/python/doc/reader_utils_ref.rst +++ /dev/null @@ -1,15 +0,0 @@ -:orphan: - -.. To get rid of WARNING: document isn't included in any toctree - -============================= -Reader utils reference manual -============================= - -.. autofunction:: gudhi.read_off - -.. autofunction:: gudhi.read_lower_triangular_matrix_from_csv_file - -.. autofunction:: gudhi.read_persistence_intervals_grouped_by_dimension - -.. autofunction:: gudhi.read_persistence_intervals_in_dimension diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_reader.pyx index 225e981c..e45356be 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_reader.pyx @@ -26,7 +26,7 @@ def read_off(off_file=''): :type off_file: string :returns: The point set. - :rtype: vector[vector[double]] + :rtype: list(list(float)) """ if off_file: if os.path.isfile(off_file): diff --git a/src/python/gudhi/reader_utils.pyx b/src/python/gudhi/reader_utils.pyx index 6994c4f9..5a756e4b 100644 --- a/src/python/gudhi/reader_utils.pyx +++ b/src/python/gudhi/reader_utils.pyx @@ -34,7 +34,7 @@ def read_lower_triangular_matrix_from_csv_file(csv_file='', separator=';'): :type separator: char :returns: The lower triangular matrix. - :rtype: vector[vector[double]] + :rtype: list(list(float)) """ if csv_file: if path.isfile(csv_file): @@ -45,7 +45,7 @@ def read_lower_triangular_matrix_from_csv_file(csv_file='', separator=';'): def read_persistence_intervals_grouped_by_dimension(persistence_file=''): """Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death - The return value is an `map[dim, vector[pair[birth, death]]]` + The return value is a `dict(dim, list(tuple(birth, death)))` where `dim` is an `int`, `birth` a `double`, and `death` a `double`. Note: the function does not check that birth <= death. @@ -53,7 +53,7 @@ def read_persistence_intervals_grouped_by_dimension(persistence_file=''): :type persistence_file: string :returns: The persistence pairs grouped by dimension. - :rtype: map[int, vector[pair[double, double]]] + :rtype: dict(int, list(tuple(float, float))) """ if persistence_file: if path.isfile(persistence_file): diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index e0cd1348..04f66219 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -33,7 +33,7 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi The iteration starts with the landmark `starting point`. :param points: The input point set. - :type points: vector[vector[double]]. + :type points: list(list(float)). Or @@ -47,7 +47,7 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi index is chosen randomly. :type starting_point: unsigned. :returns: The subsample point set. - :rtype: vector[vector[double]] + :rtype: list(list(float)). """ if off_file: if os.path.isfile(off_file): @@ -74,7 +74,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): """Subsample a point set by picking random vertices. :param points: The input point set. - :type points: vector[vector[double]]. + :type points: list(list(float)). Or @@ -84,7 +84,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): :param nb_points: Number of points of the subsample. :type nb_points: unsigned. :returns: The subsample point set. - :rtype: vector[vector[double]] + :rtype: list(list(float)) """ if off_file: if os.path.isfile(off_file): @@ -103,7 +103,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): between any two points is greater than or equal to min_squared_dist. :param points: The input point set. - :type points: vector[vector[double]]. + :type points: list(list(float)). Or @@ -114,7 +114,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): points. :type min_squared_dist: float. :returns: The subsample point set. - :rtype: vector[vector[double]] + :rtype: list(list(float)) """ if off_file: if os.path.isfile(off_file): -- cgit v1.2.3 From d832d3585bf47c48f28d861469730fc47f4956c8 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 7 Jan 2020 12:24:45 +0100 Subject: Code review: less strict with numpy arrays for cubical ctors. Also accept lists --- src/python/gudhi/cubical_complex.pyx | 14 +++++++------- src/python/gudhi/periodic_cubical_complex.pyx | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 04b22921..63911478 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -60,7 +60,7 @@ cdef class CubicalComplex: :param top_dimensional_cells: A multidimensional array of cells filtration values. - :type top_dimensional_cells: numpy ndarray + :type top_dimensional_cells: numpy ndarray or list of list of double Or @@ -76,12 +76,12 @@ cdef class CubicalComplex: self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) elif ((dimensions is None) and (top_dimensional_cells is not None) and (perseus_file == '')): - if isinstance(top_dimensional_cells, np.ndarray): - dimensions = top_dimensional_cells.shape - top_dimensional_cells = top_dimensional_cells.ravel(order='F') - self.thisptr = new Bitmap_cubical_complex_base_interface(dimensions, top_dimensional_cells) - else: - print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) + top_dimensional_cells = np.array(top_dimensional_cells, + copy = False, + order = 'F') + dimensions = top_dimensional_cells.shape + top_dimensional_cells = top_dimensional_cells.ravel(order='F') + 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 != '')): if os.path.isfile(perseus_file): diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index 1d6f1e59..3c0f529b 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -62,7 +62,7 @@ cdef class PeriodicCubicalComplex: :param top_dimensional_cells: A multidimensional array of cells filtration values. - :type top_dimensional_cells: numpy ndarray + :type top_dimensional_cells: numpy ndarray or list of list of double :param periodic_dimensions: A list of top dimensional cells periodicity value. :type periodic_dimensions: list of boolean @@ -82,14 +82,14 @@ cdef class PeriodicCubicalComplex: periodic_dimensions) elif ((dimensions is None) and (top_dimensional_cells is not None) and (periodic_dimensions is not None) and (perseus_file == '')): - if isinstance(top_dimensional_cells, np.ndarray): - dimensions = top_dimensional_cells.shape - top_dimensional_cells = top_dimensional_cells.ravel(order='F') - self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, - top_dimensional_cells, - periodic_dimensions) - else: - print("top_dimensional_cells is not an instance of ndarray. It is a " + type(top_dimensional_cells)) + top_dimensional_cells = np.array(top_dimensional_cells, + copy = False, + order = 'F') + dimensions = top_dimensional_cells.shape + top_dimensional_cells = top_dimensional_cells.ravel(order='F') + self.thisptr = new Periodic_cubical_complex_base_interface(dimensions, + top_dimensional_cells, + periodic_dimensions) elif ((dimensions is None) and (top_dimensional_cells is None) and (periodic_dimensions is None) and (perseus_file != '')): if os.path.isfile(perseus_file): -- cgit v1.2.3 From 82b556c554a60e3b05942ba53300463dc00b8538 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 7 Jan 2020 12:27:19 +0100 Subject: Code review: use list in examples instead of numpy arrays --- src/python/doc/cubical_complex_user.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/python/doc/cubical_complex_user.rst b/src/python/doc/cubical_complex_user.rst index d56c8789..6fdcd9df 100644 --- a/src/python/doc/cubical_complex_user.rst +++ b/src/python/doc/cubical_complex_user.rst @@ -142,9 +142,7 @@ Or it can be defined as follows: .. testcode:: from gudhi import PeriodicCubicalComplex as pcc - from numpy import array as np_array - periodic_cc = pcc(top_dimensional_cells = np_array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]), - periodic_dimensions=[True, False]) + periodic_cc = pcc(top_dimensional_cells = [[0, 0, 0], [0, 1, 0], [0, 0, 0]] result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ repr(periodic_cc.num_simplices()) + ' simplices.' print(result_str) -- cgit v1.2.3 From 44484a8f9242e45ead34cb49226df015c4b6c19a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 7 Jan 2020 12:27:43 +0100 Subject: Code review: use list in examples instead of numpy arrays --- src/python/doc/cubical_complex_user.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/doc/cubical_complex_user.rst b/src/python/doc/cubical_complex_user.rst index 6fdcd9df..56cf0170 100644 --- a/src/python/doc/cubical_complex_user.rst +++ b/src/python/doc/cubical_complex_user.rst @@ -142,7 +142,8 @@ Or it can be defined as follows: .. testcode:: from gudhi import PeriodicCubicalComplex as pcc - periodic_cc = pcc(top_dimensional_cells = [[0, 0, 0], [0, 1, 0], [0, 0, 0]] + periodic_cc = pcc(top_dimensional_cells = [[0, 0, 0], [0, 1, 0], [0, 0, 0]], + periodic_dimensions=[True, False]) result_str = 'Periodic cubical complex is of dimension ' + repr(periodic_cc.dimension()) + ' - ' + \ repr(periodic_cc.num_simplices()) + ' simplices.' print(result_str) -- cgit v1.2.3 From 6a7a7b6d6d81946dd903f68f525389ab2fd51f71 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 7 Jan 2020 13:31:18 +0100 Subject: Doc review: anything convertible to a numpy ndarray --- src/python/gudhi/cubical_complex.pyx | 2 +- src/python/gudhi/periodic_cubical_complex.pyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 63911478..b7047d4f 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -60,7 +60,7 @@ cdef class CubicalComplex: :param top_dimensional_cells: A multidimensional array of cells filtration values. - :type top_dimensional_cells: numpy ndarray or list of list of double + :type top_dimensional_cells: anything convertible to a numpy ndarray Or diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index 3c0f529b..eb96ab5f 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -62,7 +62,7 @@ cdef class PeriodicCubicalComplex: :param top_dimensional_cells: A multidimensional array of cells filtration values. - :type top_dimensional_cells: numpy ndarray or list of list of double + :type top_dimensional_cells: anything convertible to a numpy ndarray :param periodic_dimensions: A list of top dimensional cells periodicity value. :type periodic_dimensions: list of boolean -- cgit v1.2.3 From 98b4aa0026a7208230d396bc9fb28c7a3b72be6d Mon Sep 17 00:00:00 2001 From: tlacombe Date: Tue, 7 Jan 2020 18:06:13 +0100 Subject: changing variable name from (p, q) to (q, internal_p). Must also be done in tests files and doc --- src/python/gudhi/wasserstein.py | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index d8a3104c..2acf93d6 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -23,26 +23,26 @@ def _proj_on_diag(X): return np.array([Z , Z]).T -def _build_dist_matrix(X, Y, p=2., q=2.): +def _build_dist_matrix(X, Y, q=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (points of the) first diagram. :param Y: (m x 2) numpy.array encoding the second diagram. - :param q: Ground metric (i.e. norm l_q). - :param p: exponent for the Wasserstein metric. + :param internal_p: Ground metric (i.e. norm l_q). + :param q: exponent for the Wasserstein metric. :returns: (n+1) x (m+1) np.array encoding the cost matrix C. For 1 <= i <= n, 1 <= j <= m, C[i,j] encodes the distance between X[i] and Y[j], while C[i, m+1] (resp. C[n+1, j]) encodes the distance (to the p) between X[i] (resp Y[j]) and its orthogonal proj onto the diagonal. note also that C[n+1, m+1] = 0 (it costs nothing to move from the diagonal to the diagonal). ''' Xdiag = _proj_on_diag(X) Ydiag = _proj_on_diag(Y) - if np.isinf(q): - C = sc.cdist(X,Y, metric='chebyshev')**p - Cxd = np.linalg.norm(X - Xdiag, ord=q, axis=1)**p - Cdy = np.linalg.norm(Y - Ydiag, ord=q, axis=1)**p + if np.isinf(internal_p): + C = sc.cdist(X,Y, metric='chebyshev')**q + Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q + Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**q else: - C = sc.cdist(X,Y, metric='minkowski', p=q)**p - Cxd = np.linalg.norm(X - Xdiag, ord=q, axis=1)**p - Cdy = np.linalg.norm(Y - Ydiag, ord=q, axis=1)**p + C = sc.cdist(X,Y, metric='minkowski', p=internal_p)**q + Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q + Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**q Cf = np.hstack((C, Cxd[:,None])) Cdy = np.append(Cdy, 0) @@ -51,24 +51,24 @@ def _build_dist_matrix(X, Y, p=2., q=2.): return Cf -def _perstot(X, p, q): +def _perstot(X, q, internal_p): ''' :param X: (n x 2) numpy.array (points of a given diagram). - :param q: Ground metric on the (upper-half) plane (i.e. norm l_q in R^2); Default value is 2 (Euclidean norm). - :param p: exponent for Wasserstein; Default value is 2. + :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (Euclidean norm). + :param q: exponent for Wasserstein; Default value is 2. :returns: float, the total persistence of the diagram (that is, its distance to the empty diagram). ''' Xdiag = _proj_on_diag(X) - return (np.sum(np.linalg.norm(X - Xdiag, ord=q, axis=1)**p))**(1./p) + return (np.sum(np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q))**(1./q) -def wasserstein_distance(X, Y, p=2., q=2.): +def wasserstein_distance(X, Y, q=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (finite points of the) first diagram. Must not contain essential points (i.e. with infinite coordinate). :param Y: (m x 2) numpy.array encoding the second diagram. - :param q: Ground metric on the (upper-half) plane (i.e. norm l_q in R^2); Default value is 2 (euclidean norm). - :param p: exponent for Wasserstein; Default value is 2. - :returns: the p-Wasserstein distance (1 <= p < infinity) with respect to the q-norm as ground metric. + :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (euclidean norm). + :param q: exponent for Wasserstein; Default value is 2. + :returns: the q-Wasserstein distance (1 <= q < infinity) with respect to the internal_p-norm as ground metric. :rtype: float ''' n = len(X) @@ -79,20 +79,20 @@ def wasserstein_distance(X, Y, p=2., q=2.): if Y.size == 0: return 0. else: - return _perstot(Y, p, q) + return _perstot(Y, q, internal_p) elif Y.size == 0: - return _perstot(X, p, q) + return _perstot(X, q, internal_p) - M = _build_dist_matrix(X, Y, p=p, q=q) + M = _build_dist_matrix(X, Y, q=q, internal_p=internal_p) a = np.full(n+1, 1. / (n + m) ) # weight vector of the input diagram. Uniform here. a[-1] = a[-1] * m # normalized so that we have a probability measure, required by POT b = np.full(m+1, 1. / (n + m) ) # weight vector of the input diagram. Uniform here. b[-1] = b[-1] * n # so that we have a probability measure, required by POT # Comptuation of the otcost using the ot.emd2 library. - # Note: it is the squared Wasserstein distance. + # Note: it is the Wasserstein distance to the power q. # The default numItermax=100000 is not sufficient for some examples with 5000 points, what is a good value? ot_cost = (n+m) * ot.emd2(a, b, M, numItermax=2000000) - return ot_cost ** (1./p) + return ot_cost ** (1./q) -- cgit v1.2.3 From f3dc8e802d2a6226532f92a252f96ddbd7b6a411 Mon Sep 17 00:00:00 2001 From: tlacombe Date: Wed, 8 Jan 2020 09:41:31 +0100 Subject: changing variable name in test files --- src/python/test/test_wasserstein_distance.py | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index a6bf9901..40112c1b 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -23,26 +23,26 @@ def test_basic_wasserstein(): diag4 = np.array([[0, 3], [4, 8]]) emptydiag = np.array([[]]) - assert wasserstein_distance(emptydiag, emptydiag, q=2., p=1.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, q=np.inf, p=1.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, q=np.inf, p=2.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, q=2., p=2.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., q=1.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, q=1.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, q=2.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., q=2.) == 0. - assert wasserstein_distance(diag3, emptydiag, q=np.inf, p=1.) == 2. - assert wasserstein_distance(diag3, emptydiag, q=1., p=1.) == 4. + assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, q=1.) == 2. + assert wasserstein_distance(diag3, emptydiag, internal_p=1., q=1.) == 4. - assert wasserstein_distance(diag4, emptydiag, q=1., p=2.) == 5. # thank you Pythagorician triplets - assert wasserstein_distance(diag4, emptydiag, q=np.inf, p=2.) == 2.5 - assert wasserstein_distance(diag4, emptydiag, q=2., p=2.) == 3.5355339059327378 + assert wasserstein_distance(diag4, emptydiag, internal_p=1., q=2.) == 5. # thank you Pythagorician triplets + assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, q=2.) == 2.5 + assert wasserstein_distance(diag4, emptydiag, internal_p=2., q=2.) == 3.5355339059327378 - assert wasserstein_distance(diag1, diag2, q=2., p=1.) == 1.4453593023967701 - assert wasserstein_distance(diag1, diag2, q=2.35, p=1.74) == 0.9772734057168739 + assert wasserstein_distance(diag1, diag2, internal_p=2., q=1.) == 1.4453593023967701 + assert wasserstein_distance(diag1, diag2, internal_p=2.35, q=1.74) == 0.9772734057168739 - assert wasserstein_distance(diag1, emptydiag, q=2.35, p=1.7863) == 3.141592214572228 + assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, q=1.7863) == 3.141592214572228 - assert wasserstein_distance(diag3, diag4, q=1., p=1.) == 3. - assert wasserstein_distance(diag3, diag4, q=np.inf, p=1.) == 3. # no diag matching here - assert wasserstein_distance(diag3, diag4, q=np.inf, p=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, q=1., p=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, q=4.5, p=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=1., q=1.) == 3. + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, q=1.) == 3. # no diag matching here + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, q=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=1., q=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=4.5, q=2.) == np.sqrt(5) -- cgit v1.2.3 From 4bcdd64974900302f420fb08435275cc8faa794a Mon Sep 17 00:00:00 2001 From: tlacombe Date: Wed, 8 Jan 2020 09:44:36 +0100 Subject: update variable name in doc --- src/python/doc/wasserstein_distance_sum.inc | 6 +++--- src/python/doc/wasserstein_distance_user.rst | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/python/doc/wasserstein_distance_sum.inc b/src/python/doc/wasserstein_distance_sum.inc index ffd4d312..a97f428d 100644 --- a/src/python/doc/wasserstein_distance_sum.inc +++ b/src/python/doc/wasserstein_distance_sum.inc @@ -2,12 +2,12 @@ :widths: 30 50 20 +-----------------------------------------------------------------+----------------------------------------------------------------------+------------------------------------------------------------------+ - | .. figure:: | The p-Wasserstein distance measures the similarity between two | :Author: Theo Lacombe | + | .. figure:: | The q-Wasserstein distance measures the similarity between two | :Author: Theo Lacombe | | ../../doc/Bottleneck_distance/perturb_pd.png | persistence diagrams. It's the minimum value c that can be achieved | | | :figclass: align-center | by a perfect matching between the points of the two diagrams (+ all | :Introduced in: GUDHI 3.1.0 | | | diagonal points), where the value of a matching is defined as the | | - | Wasserstein distance is the p-th root of the sum of the | p-th root of the sum of all edge lengths to the power p. Edge lengths| :Copyright: MIT | - | edge lengths to the power p. | are measured in norm q, for :math:`1 \leq q \leq \infty`. | | + | Wasserstein distance is the q-th root of the sum of the | q-th root of the sum of all edge lengths to the power q. Edge lengths| :Copyright: MIT | + | edge lengths to the power q. | are measured in norm p, for :math:`1 \leq p \leq \infty`. | | | | | :Requires: Python Optimal Transport (POT) :math:`\geq` 0.5.1 | +-----------------------------------------------------------------+----------------------------------------------------------------------+------------------------------------------------------------------+ | * :doc:`wasserstein_distance_user` | | diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index a049cfb5..8862a5ce 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -30,7 +30,7 @@ Note that persistence diagrams must be submitted as (n x 2) numpy arrays and mus diag1 = np.array([[2.7, 3.7],[9.6, 14.],[34.2, 34.974]]) diag2 = np.array([[2.8, 4.45],[9.5, 14.1]]) - message = "Wasserstein distance value = " + '%.2f' % gudhi.wasserstein.wasserstein_distance(diag1, diag2, q=2., p=1.) + message = "Wasserstein distance value = " + '%.2f' % gudhi.wasserstein.wasserstein_distance(diag1, diag2, internal_p=2., q=1.) print(message) The output is: -- cgit v1.2.3 From 18c98020adea4a7d0c53fe4e76c92bab23e7ad76 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 9 Jan 2020 18:03:39 +0100 Subject: Spell out types as in PEP 484 but don't actually use annotations. A quick try with sphinx-autodoc-typehints failed, I didn't investigate much, it can wait. --- src/python/gudhi/off_reader.pyx | 2 +- src/python/gudhi/reader_utils.pyx | 6 +++--- src/python/gudhi/subsampling.pyx | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_reader.pyx index e45356be..3a31eba6 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_reader.pyx @@ -26,7 +26,7 @@ def read_off(off_file=''): :type off_file: string :returns: The point set. - :rtype: list(list(float)) + :rtype: List[List[float]] """ if off_file: if os.path.isfile(off_file): diff --git a/src/python/gudhi/reader_utils.pyx b/src/python/gudhi/reader_utils.pyx index 5a756e4b..9ced6bca 100644 --- a/src/python/gudhi/reader_utils.pyx +++ b/src/python/gudhi/reader_utils.pyx @@ -34,7 +34,7 @@ def read_lower_triangular_matrix_from_csv_file(csv_file='', separator=';'): :type separator: char :returns: The lower triangular matrix. - :rtype: list(list(float)) + :rtype: List[List[float]] """ if csv_file: if path.isfile(csv_file): @@ -46,14 +46,14 @@ def read_persistence_intervals_grouped_by_dimension(persistence_file=''): """Reads a file containing persistence intervals. Each line might contain 2, 3 or 4 values: [[field] dimension] birth death The return value is a `dict(dim, list(tuple(birth, death)))` - where `dim` is an `int`, `birth` a `double`, and `death` a `double`. + where `dim` is an `int`, `birth` a `float`, and `death` a `float`. Note: the function does not check that birth <= death. :param persistence_file: A persistence file style name. :type persistence_file: string :returns: The persistence pairs grouped by dimension. - :rtype: dict(int, list(tuple(float, float))) + :rtype: Dict[int, List[Tuple[float, float]]] """ if persistence_file: if path.isfile(persistence_file): diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index 04f66219..f50f4b0c 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -33,7 +33,7 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi The iteration starts with the landmark `starting point`. :param points: The input point set. - :type points: list(list(float)). + :type points: Iterable[Iterable[float]]. Or @@ -47,7 +47,7 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi index is chosen randomly. :type starting_point: unsigned. :returns: The subsample point set. - :rtype: list(list(float)). + :rtype: List[List[float]]. """ if off_file: if os.path.isfile(off_file): @@ -74,7 +74,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): """Subsample a point set by picking random vertices. :param points: The input point set. - :type points: list(list(float)). + :type points: Iterable[Iterable[float]]. Or @@ -84,7 +84,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): :param nb_points: Number of points of the subsample. :type nb_points: unsigned. :returns: The subsample point set. - :rtype: list(list(float)) + :rtype: List[List[float]] """ if off_file: if os.path.isfile(off_file): @@ -103,7 +103,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): between any two points is greater than or equal to min_squared_dist. :param points: The input point set. - :type points: list(list(float)). + :type points: Iterable[Iterable[float]]. Or @@ -114,7 +114,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): points. :type min_squared_dist: float. :returns: The subsample point set. - :rtype: list(list(float)) + :rtype: List[List[float]] """ if off_file: if os.path.isfile(off_file): -- cgit v1.2.3 From 2f7f4d84df64172c1af8b8741112c6dd9c883944 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 9 Jan 2020 18:22:24 +0100 Subject: Move point utilities in the index they we between computing diagrams and using diagrams, it looked strange --- src/python/doc/index.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/python/doc/index.rst b/src/python/doc/index.rst index 9513deb0..3387a64f 100644 --- a/src/python/doc/index.rst +++ b/src/python/doc/index.rst @@ -58,11 +58,6 @@ Persistence cohomology .. include:: persistent_cohomology_sum.inc -Point cloud utilities -********************* - -.. include:: point_cloud_sum.inc - Topological descriptors tools ***************************** @@ -86,6 +81,11 @@ Persistence graphical tools .. include:: persistence_graphical_tools_sum.inc +Point cloud utilities +********************* + +.. include:: point_cloud_sum.inc + Bibliography ************ -- cgit v1.2.3 From 051c9760a214a11e8e4af14ae6221e34bb876350 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 9 Jan 2020 20:56:48 +0100 Subject: align text --- src/python/doc/point_cloud_sum.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/doc/point_cloud_sum.inc b/src/python/doc/point_cloud_sum.inc index cefcf1c8..85d52de7 100644 --- a/src/python/doc/point_cloud_sum.inc +++ b/src/python/doc/point_cloud_sum.inc @@ -2,8 +2,8 @@ :widths: 30 50 20 +----------------------------------------------------------------+------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ - | :math:`(x_1, x_2, \ldots, x_d)` | Utilities to process point clouds: read from file, subsample, etc. | :Author: Vincent Rouvreau | - | :math:`(y_1, y_2, \ldots, y_d)` | | | + | | :math:`(x_1, x_2, \ldots, x_d)` | Utilities to process point clouds: read from file, subsample, etc. | :Author: Vincent Rouvreau | + | | :math:`(y_1, y_2, \ldots, y_d)` | | | | | | :Introduced in: GUDHI 2.0.0 | | | | | | | | :Copyright: MIT (`GPL v3 `_) | -- cgit v1.2.3 From 6d30726d9279a2ccaacdae6244fd50a6fd34528c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 10 Jan 2020 10:59:32 +0100 Subject: Fix #105: Add alpha value on the picture, clarify simplices removal from the Delaunay complex, use max_alpha_square=32 in the Python example --- src/Alpha_complex/doc/Intro_alpha_complex.h | 14 +++++++------- .../doc/alpha_complex_representation.ipe | 6 +++--- .../doc/alpha_complex_representation.png | Bin 14606 -> 19568 bytes src/common/doc/main_page.md | 4 ++-- src/python/doc/alpha_complex_sum.inc | 6 +++--- src/python/doc/alpha_complex_user.rst | 19 +++++++++---------- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/Alpha_complex/doc/Intro_alpha_complex.h b/src/Alpha_complex/doc/Intro_alpha_complex.h index 3c32a1e6..a8b1a106 100644 --- a/src/Alpha_complex/doc/Intro_alpha_complex.h +++ b/src/Alpha_complex/doc/Intro_alpha_complex.h @@ -31,8 +31,8 @@ namespace alpha_complex { * 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. + * All simplices that have a filtration value \f$ > \alpha^2 \f$ are removed from the Delaunay complex + * when creating the simplicial complex if it is specified. * * \image html "alpha_complex_representation.png" "Alpha-complex representation" * @@ -46,8 +46,8 @@ namespace alpha_complex { * \cite cgal:s-gkd-19b from CGAL as template parameter. * * \remark - * - When the simplicial complex is constructed with an infinite value of alpha, the complex is a Delaunay - * complex. + * - When an \f$\alpha\f$-complex is constructed with an infinite value of \f$ \alpha^2 \f$, the complex is a Delaunay + * complex (with special filtration values). * - For people only interested in the topology of the \ref alpha_complex (for instance persistence), * \ref alpha_complex is equivalent to the \ref cech_complex and much smaller if you do not bound the radii. * \ref cech_complex can still make sense in higher dimension precisely because you can bound the radii. @@ -135,13 +135,13 @@ namespace alpha_complex { * * \subsubsection nondecreasing 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). + * As the squared radii computed by CGAL are an approximation, it might happen that these \f$ \alpha^2 \f$ values do + * not quite define a proper filtration (i.e. non-decreasing with respect to inclusion). * We fix that up by calling `SimplicialComplexForAlpha::make_filtration_non_decreasing()`. * * \subsubsection pruneabove Prune above given filtration value * - * The simplex tree is pruned from the given maximum alpha squared value (cf. + * The simplex tree is pruned from the given maximum \f$ \alpha^2 \f$ value (cf. * `SimplicialComplexForAlpha::prune_above_filtration()`). * In the following example, the value is given by the user as argument of the program. * diff --git a/src/Alpha_complex/doc/alpha_complex_representation.ipe b/src/Alpha_complex/doc/alpha_complex_representation.ipe index e8096b93..40ff1d0f 100644 --- a/src/Alpha_complex/doc/alpha_complex_representation.ipe +++ b/src/Alpha_complex/doc/alpha_complex_representation.ipe @@ -1,7 +1,7 @@ - - + + @@ -305,7 +305,7 @@ h 108.275 743.531 m 166.45 743.531 l -$\alpha$ +\alpha = \sqrt{32.0} diff --git a/src/Alpha_complex/doc/alpha_complex_representation.png b/src/Alpha_complex/doc/alpha_complex_representation.png index 7b81cd69..5ebb1e75 100644 Binary files a/src/Alpha_complex/doc/alpha_complex_representation.png and b/src/Alpha_complex/doc/alpha_complex_representation.png differ diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index e8d11fdf..0b4bfb7a 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -43,8 +43,8 @@ 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.
+ All simplices that have a filtration value \f$ > \alpha^2 \f$ are removed from the Delaunay complex + when creating the simplicial complex if it is specified.
For performances reasons, it is advised to use \ref cgal ≥ 5.0.0. diff --git a/src/python/doc/alpha_complex_sum.inc b/src/python/doc/alpha_complex_sum.inc index c5ba9dc7..a1184663 100644 --- a/src/python/doc/alpha_complex_sum.inc +++ b/src/python/doc/alpha_complex_sum.inc @@ -9,9 +9,9 @@ | | circumradius of the simplex if the circumsphere is empty (the simplex | :Copyright: MIT (`GPL v3 `_) | | | is then said to be Gabriel), and as the minimum of the filtration | | | | values of the codimension 1 cofaces that make it not Gabriel | :Requires: `Eigen `__ :math:`\geq` 3.1.0 and `CGAL `__ :math:`\geq` 4.11.0 | - | | otherwise. All simplices that have a filtration value strictly | | - | | greater than a given alpha squared value are not inserted into the | | - | | complex. | | + | | otherwise. All simplices that have a filtration value | | + | | :math:`> \alpha^2` are removed from the Delaunay complex | | + | | when creating the simplicial complex if it is specified. | | | | | | | | This package requires having CGAL version 4.7 or higher (4.8.1 is | | | | advised for better performance). | | diff --git a/src/python/doc/alpha_complex_user.rst b/src/python/doc/alpha_complex_user.rst index b7e69e12..60319e84 100644 --- a/src/python/doc/alpha_complex_user.rst +++ b/src/python/doc/alpha_complex_user.rst @@ -16,7 +16,8 @@ Definition Remarks ^^^^^^^ -When an :math:`\alpha`-complex is constructed with an infinite value of :math:`\alpha`, the complex is a Delaunay complex (with special filtration values). +When an :math:`\alpha`-complex is constructed with an infinite value of :math:`\alpha^2`, +the complex is a Delaunay complex (with special filtration values). Example from points ------------------- @@ -137,19 +138,20 @@ sets the filtration value (0 in case of a vertex - propagation will have no effe 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). +As the squared radii computed by CGAL are an approximation, it might happen that these +:math:`\alpha^2` values do not quite define a proper filtration (i.e. non-decreasing with +respect to inclusion). We fix that up by calling :func:`~gudhi.SimplexTree.make_filtration_non_decreasing` (cf. `C++ version `_). Prune above given filtration value ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The simplex tree is pruned from the given maximum alpha squared value (cf. +The simplex tree is pruned from the given maximum :math:`\alpha^2` value (cf. :func:`~gudhi.SimplexTree.prune_above_filtration`). Note that this does not provide any kind of speed-up, since we always first build the full filtered complex, so it is recommended not to use :paramref:`~gudhi.AlphaComplex.create_simplex_tree.max_alpha_square`. -In the following example, a threshold of 59 is used. +In the following example, a threshold of :math:`\alpha^2 = 32.0` is used. Example from OFF file @@ -166,7 +168,7 @@ Then, it is asked to display information about the alpha complex: import gudhi alpha_complex = gudhi.AlphaComplex(off_file=gudhi.__root_source_dir__ + \ '/data/points/alphacomplexdoc.off') - simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=59.0) + simplex_tree = alpha_complex.create_simplex_tree(max_alpha_square=32.0) result_str = 'Alpha complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ repr(simplex_tree.num_simplices()) + ' simplices - ' + \ repr(simplex_tree.num_vertices()) + ' vertices.' @@ -179,7 +181,7 @@ the program output is: .. testoutput:: - Alpha complex is of dimension 2 - 23 simplices - 7 vertices. + Alpha complex is of dimension 2 - 20 simplices - 7 vertices. [0] -> 0.00 [1] -> 0.00 [2] -> 0.00 @@ -200,9 +202,6 @@ the program output is: [4, 6] -> 22.74 [4, 5, 6] -> 22.74 [3, 6] -> 30.25 - [2, 6] -> 36.50 - [2, 3, 6] -> 36.50 - [2, 4, 6] -> 37.24 CGAL citations ============== -- cgit v1.2.3 From 609d4a5307cb8faef5f5002be9f51eee7bf3916e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 10 Jan 2020 11:20:07 +0100 Subject: Bug fix: a href tag was badly closed --- src/common/doc/installation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index d70a2efa..ce2c5448 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -33,7 +33,7 @@ make \endverbatim * \subsection testsuites Test suites * To test your build, run the following command in a terminal: * \verbatim make test \endverbatim - * `make test` is using Ctest<\a> (CMake test driver + * `make test` is using Ctest (CMake test driver * program). If some of the tests are failing, please send us the result of the following command: * \verbatim ctest --output-on-failure \endverbatim * -- cgit v1.2.3 From 8f5cb043bf78b8f008b67e292668543a899e6795 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 10 Jan 2020 19:43:04 +0100 Subject: Reorder import and docstrings. Modify test_representations --- src/python/gudhi/__init__.py.in | 8 +++----- src/python/gudhi/alpha_complex.pyx | 18 +++++++++--------- src/python/gudhi/bottleneck.pyx | 10 +++++----- src/python/gudhi/cubical_complex.pyx | 18 +++++++++--------- src/python/gudhi/euclidean_strong_witness_complex.pyx | 16 ++++++++-------- src/python/gudhi/euclidean_witness_complex.pyx | 16 ++++++++-------- src/python/gudhi/nerve_gic.pyx | 18 +++++++++--------- src/python/gudhi/off_reader.pyx | 10 +++++----- src/python/gudhi/periodic_cubical_complex.pyx | 18 +++++++++--------- src/python/gudhi/persistence_graphical_tools.py | 14 +++++++------- src/python/gudhi/reader_utils.pyx | 18 +++++++++--------- src/python/gudhi/rips_complex.pyx | 18 +++++++++--------- src/python/gudhi/simplex_tree.pxd | 19 +++++++++---------- src/python/gudhi/simplex_tree.pyx | 8 ++++---- src/python/gudhi/strong_witness_complex.pyx | 16 ++++++++-------- src/python/gudhi/subsampling.pyx | 12 ++++++------ src/python/gudhi/tangential_complex.pyx | 18 +++++++++--------- src/python/gudhi/wasserstein.py | 14 +++++++------- src/python/gudhi/witness_complex.pyx | 16 ++++++++-------- src/python/setup.py.in | 8 ++++---- src/python/test/test_alpha_complex.py | 12 ++++++------ src/python/test/test_bottleneck_distance.py | 4 ++-- src/python/test/test_cover_complex.py | 4 ++-- src/python/test/test_cubical_complex.py | 6 +++--- src/python/test/test_euclidean_witness_complex.py | 4 ++-- src/python/test/test_reader_utils.py | 6 +++--- src/python/test/test_representations.py | 15 ++++++++------- src/python/test/test_rips_complex.py | 6 +++--- src/python/test/test_simplex_tree.py | 4 ++-- src/python/test/test_subsampling.py | 4 ++-- src/python/test/test_tangential_complex.py | 4 ++-- src/python/test/test_wasserstein_distance.py | 6 +++--- src/python/test/test_witness_complex.py | 4 ++-- 33 files changed, 185 insertions(+), 187 deletions(-) diff --git a/src/python/gudhi/__init__.py.in b/src/python/gudhi/__init__.py.in index 0c462b02..79e12fbc 100644 --- a/src/python/gudhi/__init__.py.in +++ b/src/python/gudhi/__init__.py.in @@ -1,5 +1,3 @@ -from importlib import import_module - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -9,6 +7,9 @@ from importlib import import_module # Modification(s): # - YYYY/MM Author: Description of the modification +from importlib import import_module +from sys import exc_info + __author__ = "GUDHI Editorial Board" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "https://gudhi.inria.fr/licensing/" @@ -17,9 +18,6 @@ __version__ = "@GUDHI_VERSION@" __root_source_dir__ = "@CMAKE_SOURCE_DIR@" __debug_info__ = @GUDHI_PYTHON_DEBUG_INFO@ -from sys import exc_info -from importlib import import_module - __all__ = [@GUDHI_PYTHON_MODULES@ @GUDHI_PYTHON_MODULES_EXTRA@] __available_modules = '' diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index 24e36bea..db11416c 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -1,3 +1,12 @@ +# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. +# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. +# Author(s): Vincent Rouvreau +# +# Copyright (C) 2016 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair @@ -9,15 +18,6 @@ import os from gudhi.simplex_tree cimport * from gudhi.simplex_tree import SimplexTree -# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. -# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. -# Author(s): Vincent Rouvreau -# -# Copyright (C) 2016 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/bottleneck.pyx b/src/python/gudhi/bottleneck.pyx index c2361024..af011e88 100644 --- a/src/python/gudhi/bottleneck.pyx +++ b/src/python/gudhi/bottleneck.pyx @@ -1,8 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -import os - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -12,6 +7,11 @@ import os # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +import os + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index b7047d4f..92ff6411 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -1,12 +1,3 @@ -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 - -import numpy as np - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -16,6 +7,15 @@ import numpy as np # Modification(s): # - YYYY/MM Author: Description of the modification +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 + +import numpy as np + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/euclidean_strong_witness_complex.pyx b/src/python/gudhi/euclidean_strong_witness_complex.pyx index e3f451f0..9889f92c 100644 --- a/src/python/gudhi/euclidean_strong_witness_complex.pyx +++ b/src/python/gudhi/euclidean_strong_witness_complex.pyx @@ -1,11 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -from libc.stdint cimport intptr_t - -from gudhi.simplex_tree cimport * -from gudhi.simplex_tree import SimplexTree - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -15,6 +7,14 @@ from gudhi.simplex_tree import SimplexTree # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libc.stdint cimport intptr_t + +from gudhi.simplex_tree cimport * +from gudhi.simplex_tree import SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/euclidean_witness_complex.pyx b/src/python/gudhi/euclidean_witness_complex.pyx index 84a8ea1a..e3ce0e82 100644 --- a/src/python/gudhi/euclidean_witness_complex.pyx +++ b/src/python/gudhi/euclidean_witness_complex.pyx @@ -1,11 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -from libc.stdint cimport intptr_t - -from gudhi.simplex_tree cimport * -from gudhi.simplex_tree import SimplexTree - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -15,6 +7,14 @@ from gudhi.simplex_tree import SimplexTree # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libc.stdint cimport intptr_t + +from gudhi.simplex_tree cimport * +from gudhi.simplex_tree import SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/nerve_gic.pyx b/src/python/gudhi/nerve_gic.pyx index acb78564..68c06432 100644 --- a/src/python/gudhi/nerve_gic.pyx +++ b/src/python/gudhi/nerve_gic.pyx @@ -1,3 +1,12 @@ +# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. +# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. +# Author(s): Vincent Rouvreau +# +# Copyright (C) 2018 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair @@ -9,15 +18,6 @@ from libc.stdint cimport intptr_t from gudhi.simplex_tree cimport * from gudhi.simplex_tree import SimplexTree -# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. -# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. -# Author(s): Vincent Rouvreau -# -# Copyright (C) 2018 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2018 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_reader.pyx index 225e981c..54a275e2 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_reader.pyx @@ -1,8 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.string cimport string -import os - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -12,6 +7,11 @@ import os # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +import os + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index eb96ab5f..b5dece10 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -1,12 +1,3 @@ -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 - -import numpy as np - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -16,6 +7,15 @@ import numpy as np # Modification(s): # - YYYY/MM Author: Description of the modification +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 + +import numpy as np + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/persistence_graphical_tools.py b/src/python/gudhi/persistence_graphical_tools.py index 7d232c85..246280de 100644 --- a/src/python/gudhi/persistence_graphical_tools.py +++ b/src/python/gudhi/persistence_graphical_tools.py @@ -1,10 +1,3 @@ -from os import path -from math import isfinite -import numpy as np - -from gudhi.reader_utils import read_persistence_intervals_in_dimension -from gudhi.reader_utils import read_persistence_intervals_grouped_by_dimension - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau, Bertrand Michel @@ -14,6 +7,13 @@ from gudhi.reader_utils import read_persistence_intervals_grouped_by_dimension # Modification(s): # - YYYY/MM Author: Description of the modification +from os import path +from math import isfinite +import numpy as np + +from gudhi.reader_utils import read_persistence_intervals_in_dimension +from gudhi.reader_utils import read_persistence_intervals_grouped_by_dimension + __author__ = "Vincent Rouvreau, Bertrand Michel" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/reader_utils.pyx b/src/python/gudhi/reader_utils.pyx index 6994c4f9..345c92f8 100644 --- a/src/python/gudhi/reader_utils.pyx +++ b/src/python/gudhi/reader_utils.pyx @@ -1,12 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.string cimport string -from libcpp.map cimport map -from libcpp.pair cimport pair - -from os import path -from numpy import array as np_array - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -16,6 +7,15 @@ from numpy import array as np_array # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp.map cimport map +from libcpp.pair cimport pair + +from os import path +from numpy import array as np_array + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2017 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/rips_complex.pyx b/src/python/gudhi/rips_complex.pyx index cbbbab0d..722cdcdc 100644 --- a/src/python/gudhi/rips_complex.pyx +++ b/src/python/gudhi/rips_complex.pyx @@ -1,3 +1,12 @@ +# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. +# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. +# Author(s): Vincent Rouvreau +# +# Copyright (C) 2016 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair @@ -8,15 +17,6 @@ from libc.stdint cimport intptr_t from gudhi.simplex_tree cimport * from gudhi.simplex_tree import SimplexTree -# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. -# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. -# Author(s): Vincent Rouvreau -# -# Copyright (C) 2016 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 5f86cfe2..1066d44b 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -1,19 +1,18 @@ +# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. +# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. +# Author(s): Vincent Rouvreau +# +# Copyright (C) 2016 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair from libcpp cimport bool from libcpp.string cimport string -""" This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. - See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. - Author(s): Vincent Rouvreau - - Copyright (C) 2016 Inria - - Modification(s): - - YYYY/MM Author: Description of the modification -""" - __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 4a3cd9bc..85d25492 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -1,7 +1,3 @@ -from libc.stdint cimport intptr_t -from numpy import array as np_array -cimport simplex_tree - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -11,6 +7,10 @@ cimport simplex_tree # Modification(s): # - YYYY/MM Author: Description of the modification +from libc.stdint cimport intptr_t +from numpy import array as np_array +cimport simplex_tree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/strong_witness_complex.pyx b/src/python/gudhi/strong_witness_complex.pyx index 66d49b49..2c33c3f2 100644 --- a/src/python/gudhi/strong_witness_complex.pyx +++ b/src/python/gudhi/strong_witness_complex.pyx @@ -1,11 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -from libc.stdint cimport intptr_t - -from gudhi.simplex_tree cimport * -from gudhi.simplex_tree import SimplexTree - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -15,6 +7,14 @@ from gudhi.simplex_tree import SimplexTree # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libc.stdint cimport intptr_t + +from gudhi.simplex_tree cimport * +from gudhi.simplex_tree import SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index e0cd1348..b1812087 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -1,9 +1,3 @@ -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 - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -13,6 +7,12 @@ import os # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp cimport bool +import os + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/tangential_complex.pyx b/src/python/gudhi/tangential_complex.pyx index f4c8b079..0083033c 100644 --- a/src/python/gudhi/tangential_complex.pyx +++ b/src/python/gudhi/tangential_complex.pyx @@ -1,3 +1,12 @@ +# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. +# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. +# Author(s): Vincent Rouvreau +# +# Copyright (C) 2016 Inria +# +# Modification(s): +# - YYYY/MM Author: Description of the modification + from cython cimport numeric from libcpp.vector cimport vector from libcpp.utility cimport pair @@ -9,15 +18,6 @@ import os from gudhi.simplex_tree cimport * from gudhi.simplex_tree import SimplexTree -# This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. -# See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. -# Author(s): Vincent Rouvreau -# -# Copyright (C) 2016 Inria -# -# Modification(s): -# - YYYY/MM Author: Description of the modification - __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "GPL v3" diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index d8a3104c..1906eeb1 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -1,10 +1,3 @@ -import numpy as np -import scipy.spatial.distance as sc -try: - import ot -except ImportError: - print("POT (Python Optimal Transport) package is not installed. Try to run $ conda install -c conda-forge pot ; or $ pip install POT") - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Theo Lacombe @@ -14,6 +7,13 @@ except ImportError: # Modification(s): # - YYYY/MM Author: Description of the modification +import numpy as np +import scipy.spatial.distance as sc +try: + import ot +except ImportError: + print("POT (Python Optimal Transport) package is not installed. Try to run $ conda install -c conda-forge pot ; or $ pip install POT") + def _proj_on_diag(X): ''' :param X: (n x 2) array encoding the points of a persistent diagram. diff --git a/src/python/gudhi/witness_complex.pyx b/src/python/gudhi/witness_complex.pyx index 153fc615..b032a5a1 100644 --- a/src/python/gudhi/witness_complex.pyx +++ b/src/python/gudhi/witness_complex.pyx @@ -1,11 +1,3 @@ -from cython cimport numeric -from libcpp.vector cimport vector -from libcpp.utility cimport pair -from libc.stdint cimport intptr_t - -from gudhi.simplex_tree cimport * -from gudhi.simplex_tree import SimplexTree - # This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. # See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. # Author(s): Vincent Rouvreau @@ -15,6 +7,14 @@ from gudhi.simplex_tree import SimplexTree # Modification(s): # - YYYY/MM Author: Description of the modification +from cython cimport numeric +from libcpp.vector cimport vector +from libcpp.utility cimport pair +from libc.stdint cimport intptr_t + +from gudhi.simplex_tree cimport * +from gudhi.simplex_tree import SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 3f1d4424..24d05025 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -1,7 +1,3 @@ -from setuptools import setup, Extension -from Cython.Build import cythonize -from numpy import get_include as numpy_get_include - """This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -12,6 +8,10 @@ from numpy import get_include as numpy_get_include - YYYY/MM Author: Description of the modification """ +from setuptools import setup, Extension +from Cython.Build import cythonize +from numpy import get_include as numpy_get_include + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 9b27fff2..712a50b6 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -1,9 +1,3 @@ -from gudhi import AlphaComplex, SimplexTree -import math -import numpy as np -import itertools -import pytest - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -14,6 +8,12 @@ import pytest - YYYY/MM Author: Description of the modification """ +from gudhi import AlphaComplex, SimplexTree +import math +import numpy as np +import itertools +import pytest + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_bottleneck_distance.py b/src/python/test/test_bottleneck_distance.py index f5f019b9..70b2abad 100755 --- a/src/python/test/test_bottleneck_distance.py +++ b/src/python/test/test_bottleneck_distance.py @@ -1,5 +1,3 @@ -import gudhi - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ import gudhi - YYYY/MM Author: Description of the modification """ +import gudhi + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_cover_complex.py b/src/python/test/test_cover_complex.py index 8cd12272..32bc5a26 100755 --- a/src/python/test/test_cover_complex.py +++ b/src/python/test/test_cover_complex.py @@ -1,5 +1,3 @@ -from gudhi import CoverComplex - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ from gudhi import CoverComplex - YYYY/MM Author: Description of the modification """ +from gudhi import CoverComplex + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2018 Inria" __license__ = "MIT" diff --git a/src/python/test/test_cubical_complex.py b/src/python/test/test_cubical_complex.py index 121da12a..8c1b2600 100755 --- a/src/python/test/test_cubical_complex.py +++ b/src/python/test/test_cubical_complex.py @@ -1,6 +1,3 @@ -from gudhi import CubicalComplex, PeriodicCubicalComplex -import numpy as np - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -11,6 +8,9 @@ import numpy as np - YYYY/MM Author: Description of the modification """ +from gudhi import CubicalComplex, PeriodicCubicalComplex +import numpy as np + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_euclidean_witness_complex.py b/src/python/test/test_euclidean_witness_complex.py index f5eae5fa..c18d2484 100755 --- a/src/python/test/test_euclidean_witness_complex.py +++ b/src/python/test/test_euclidean_witness_complex.py @@ -1,5 +1,3 @@ -import gudhi - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ import gudhi - YYYY/MM Author: Description of the modification """ +import gudhi + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_reader_utils.py b/src/python/test/test_reader_utils.py index 4c7b32c2..90da6651 100755 --- a/src/python/test/test_reader_utils.py +++ b/src/python/test/test_reader_utils.py @@ -1,6 +1,3 @@ -import gudhi -import numpy as np - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -11,6 +8,9 @@ import numpy as np - YYYY/MM Author: Description of the modification """ +import gudhi +import numpy as np + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2017 Inria" __license__ = "MIT" diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 4ff65f98..dba7f952 100755 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -1,11 +1,12 @@ import os import sys import matplotlib.pyplot as plt -# Disable graphics for testing purposes -plt.show = lambda:None -here = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(here + "/../example") -import diagram_vectorizations_distances_kernels -# pytest is unhappy if there are 0 tests -def test_nothing(): + +def test_representations_examples(): + # Disable graphics for testing purposes + plt.show = lambda:None + here = os.path.dirname(os.path.realpath(__file__)) + sys.path.append(here + "/../example") + import diagram_vectorizations_distances_kernels + return None diff --git a/src/python/test/test_rips_complex.py b/src/python/test/test_rips_complex.py index d55ae22f..b02a68e1 100755 --- a/src/python/test/test_rips_complex.py +++ b/src/python/test/test_rips_complex.py @@ -1,6 +1,3 @@ -from gudhi import RipsComplex -from math import sqrt - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -11,6 +8,9 @@ from math import sqrt - YYYY/MM Author: Description of the modification """ +from gudhi import RipsComplex +from math import sqrt + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_simplex_tree.py b/src/python/test/test_simplex_tree.py index 8d8971c1..1822c43b 100755 --- a/src/python/test/test_simplex_tree.py +++ b/src/python/test/test_simplex_tree.py @@ -1,5 +1,3 @@ -from gudhi import SimplexTree - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ from gudhi import SimplexTree - YYYY/MM Author: Description of the modification """ +from gudhi import SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_subsampling.py b/src/python/test/test_subsampling.py index c816e203..fe0985fa 100755 --- a/src/python/test/test_subsampling.py +++ b/src/python/test/test_subsampling.py @@ -1,5 +1,3 @@ -import gudhi - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ import gudhi - YYYY/MM Author: Description of the modification """ +import gudhi + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_tangential_complex.py b/src/python/test/test_tangential_complex.py index 0f828d8e..e650e99c 100755 --- a/src/python/test/test_tangential_complex.py +++ b/src/python/test/test_tangential_complex.py @@ -1,5 +1,3 @@ -from gudhi import TangentialComplex, SimplexTree - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ from gudhi import TangentialComplex, SimplexTree - YYYY/MM Author: Description of the modification """ +from gudhi import TangentialComplex, SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index a6bf9901..bb59b3c2 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -1,6 +1,3 @@ -from gudhi.wasserstein import wasserstein_distance -import numpy as np - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Theo Lacombe @@ -11,6 +8,9 @@ import numpy as np - YYYY/MM Author: Description of the modification """ +from gudhi.wasserstein import wasserstein_distance +import numpy as np + __author__ = "Theo Lacombe" __copyright__ = "Copyright (C) 2019 Inria" __license__ = "MIT" diff --git a/src/python/test/test_witness_complex.py b/src/python/test/test_witness_complex.py index 36ced635..7baf18c9 100755 --- a/src/python/test/test_witness_complex.py +++ b/src/python/test/test_witness_complex.py @@ -1,5 +1,3 @@ -from gudhi import WitnessComplex, StrongWitnessComplex, SimplexTree - """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. Author(s): Vincent Rouvreau @@ -10,6 +8,8 @@ from gudhi import WitnessComplex, StrongWitnessComplex, SimplexTree - YYYY/MM Author: Description of the modification """ +from gudhi import WitnessComplex, StrongWitnessComplex, SimplexTree + __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" __license__ = "MIT" -- cgit v1.2.3 From b6e1d3025e27eed08eb8a1c5f95a80d6c6a9ce15 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 13 Jan 2020 09:55:01 +0100 Subject: Fix #194 : Rename read_off as it only read points from OFF file --- src/python/doc/persistence_graphical_tools_user.rst | 2 +- src/python/doc/reader_utils_ref.rst | 2 +- src/python/doc/rips_complex_user.rst | 3 ++- src/python/doc/witness_complex_user.rst | 2 +- src/python/example/alpha_rips_persistence_bottleneck_distance.py | 2 +- ...strong_witness_complex_diagram_persistence_from_off_file_example.py | 2 +- ...lidean_witness_complex_diagram_persistence_from_off_file_example.py | 2 +- src/python/example/plot_rips_complex.py | 2 +- .../example/rips_complex_diagram_persistence_from_off_file_example.py | 2 +- src/python/gudhi/off_reader.pyx | 2 +- 10 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/python/doc/persistence_graphical_tools_user.rst b/src/python/doc/persistence_graphical_tools_user.rst index f41a926b..80002db6 100644 --- a/src/python/doc/persistence_graphical_tools_user.rst +++ b/src/python/doc/persistence_graphical_tools_user.rst @@ -24,7 +24,7 @@ This function can display the persistence result as a barcode: import gudhi off_file = gudhi.__root_source_dir__ + '/data/points/tore3D_300.off' - point_cloud = gudhi.read_off(off_file=off_file) + point_cloud = gudhi.read_points_from_off_file(off_file=off_file) rips_complex = gudhi.RipsComplex(points=point_cloud, max_edge_length=0.7) simplex_tree = rips_complex.create_simplex_tree(max_dimension=3) diff --git a/src/python/doc/reader_utils_ref.rst b/src/python/doc/reader_utils_ref.rst index f3ecebad..b8977a5a 100644 --- a/src/python/doc/reader_utils_ref.rst +++ b/src/python/doc/reader_utils_ref.rst @@ -6,7 +6,7 @@ Reader utils reference manual ============================= -.. autofunction:: gudhi.read_off +.. autofunction:: gudhi.read_points_from_off_file .. autofunction:: gudhi.read_lower_triangular_matrix_from_csv_file diff --git a/src/python/doc/rips_complex_user.rst b/src/python/doc/rips_complex_user.rst index a8659542..a27573e8 100644 --- a/src/python/doc/rips_complex_user.rst +++ b/src/python/doc/rips_complex_user.rst @@ -136,7 +136,8 @@ Finally, it is asked to display information about the Rips complex. .. testcode:: import gudhi - point_cloud = gudhi.read_off(off_file=gudhi.__root_source_dir__ + '/data/points/alphacomplexdoc.off') + off_file = gudhi.__root_source_dir__ + '/data/points/alphacomplexdoc.off' + point_cloud = gudhi.read_points_from_off_file(off_file = off_file) rips_complex = gudhi.RipsComplex(points=point_cloud, max_edge_length=12.0) simplex_tree = rips_complex.create_simplex_tree(max_dimension=1) result_str = 'Rips complex is of dimension ' + repr(simplex_tree.dimension()) + ' - ' + \ diff --git a/src/python/doc/witness_complex_user.rst b/src/python/doc/witness_complex_user.rst index 45ba5b3b..7087fa98 100644 --- a/src/python/doc/witness_complex_user.rst +++ b/src/python/doc/witness_complex_user.rst @@ -101,7 +101,7 @@ Let's start with a simple example, which reads an off point file and computes a print("#####################################################################") print("EuclideanWitnessComplex creation from points read in a OFF file") - witnesses = gudhi.read_off(off_file=args.file) + witnesses = gudhi.read_points_from_off_file(off_file=args.file) landmarks = gudhi.pick_n_random_points(points=witnesses, nb_points=args.number_of_landmarks) message = "EuclideanWitnessComplex with max_edge_length=" + repr(args.max_alpha_square) + \ diff --git a/src/python/example/alpha_rips_persistence_bottleneck_distance.py b/src/python/example/alpha_rips_persistence_bottleneck_distance.py index 086307ee..d5c33ec8 100755 --- a/src/python/example/alpha_rips_persistence_bottleneck_distance.py +++ b/src/python/example/alpha_rips_persistence_bottleneck_distance.py @@ -35,7 +35,7 @@ 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"): - point_cloud = gudhi.read_off(off_file=args.file) + point_cloud = gudhi.read_points_from_off_file(off_file=args.file) print("#####################################################################") print("RipsComplex creation from points read in a OFF file") diff --git a/src/python/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py b/src/python/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py index 0eedd140..4903667e 100755 --- a/src/python/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py @@ -47,7 +47,7 @@ with open(args.file, "r") as f: print("#####################################################################") print("EuclideanStrongWitnessComplex creation from points read in a OFF file") - witnesses = gudhi.read_off(off_file=args.file) + witnesses = gudhi.read_points_from_off_file(off_file=args.file) landmarks = gudhi.pick_n_random_points( points=witnesses, nb_points=args.number_of_landmarks ) diff --git a/src/python/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py b/src/python/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py index 1fe55737..339a8577 100755 --- a/src/python/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py @@ -46,7 +46,7 @@ with open(args.file, "r") as f: print("#####################################################################") print("EuclideanWitnessComplex creation from points read in a OFF file") - witnesses = gudhi.read_off(off_file=args.file) + witnesses = gudhi.read_points_from_off_file(off_file=args.file) landmarks = gudhi.pick_n_random_points( points=witnesses, nb_points=args.number_of_landmarks ) diff --git a/src/python/example/plot_rips_complex.py b/src/python/example/plot_rips_complex.py index 1c878db1..214a3c0a 100755 --- a/src/python/example/plot_rips_complex.py +++ b/src/python/example/plot_rips_complex.py @@ -2,7 +2,7 @@ import numpy as np import gudhi -points = np.array(gudhi.read_off('../../data/points/Kl.off')) +points = np.array(gudhi.read_points_from_off_file('../../data/points/Kl.off')) rc = gudhi.RipsComplex(points=points, max_edge_length=.2) st = rc.create_simplex_tree(max_dimension=2) # We are only going to plot the triangles diff --git a/src/python/example/rips_complex_diagram_persistence_from_off_file_example.py b/src/python/example/rips_complex_diagram_persistence_from_off_file_example.py index b9074cf9..c757aca7 100755 --- a/src/python/example/rips_complex_diagram_persistence_from_off_file_example.py +++ b/src/python/example/rips_complex_diagram_persistence_from_off_file_example.py @@ -48,7 +48,7 @@ with open(args.file, "r") as f: message = "RipsComplex with max_edge_length=" + repr(args.max_edge_length) print(message) - point_cloud = gudhi.read_off(off_file=args.file) + point_cloud = gudhi.read_points_from_off_file(off_file=args.file) rips_complex = gudhi.RipsComplex( points=point_cloud, max_edge_length=args.max_edge_length ) diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_reader.pyx index 225e981c..ee369976 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_reader.pyx @@ -19,7 +19,7 @@ __license__ = "MIT" cdef extern from "Off_reader_interface.h" namespace "Gudhi": vector[vector[double]] read_points_from_OFF_file(string off_file) -def read_off(off_file=''): +def read_points_from_off_file(off_file=''): """Read points from OFF file. :param off_file: An OFF file style name. -- cgit v1.2.3 From 79bf59738ff9ee18824ae874b60138a6b26fd336 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 13 Jan 2020 13:05:22 +0100 Subject: Add scikit-learn as a third party library as it is required by persistence representations --- src/python/doc/installation.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 50a697c7..40f3f44b 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -257,6 +257,13 @@ The :doc:`Wasserstein distance ` module requires `POT `_, a library that provides several solvers for optimization problems related to Optimal Transport. +Scikit-learn +============ + +The :doc:`persistence representations ` module require +`scikit-learn `_, a Python-based ecosystem of +open-source software for machine learning. + SciPy ===== -- cgit v1.2.3 From e807654f30363ec92c0d24b702bfd081ec8aae5a Mon Sep 17 00:00:00 2001 From: tlacombe Date: Mon, 13 Jan 2020 15:13:35 +0100 Subject: update variable names, going for order and internal_p --- src/python/doc/wasserstein_distance_user.rst | 2 +- src/python/gudhi/wasserstein.py | 34 ++++++++++++++-------------- src/python/test/test_wasserstein_distance.py | 34 ++++++++++++++-------------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 8862a5ce..32999a0c 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -30,7 +30,7 @@ Note that persistence diagrams must be submitted as (n x 2) numpy arrays and mus diag1 = np.array([[2.7, 3.7],[9.6, 14.],[34.2, 34.974]]) diag2 = np.array([[2.8, 4.45],[9.5, 14.1]]) - message = "Wasserstein distance value = " + '%.2f' % gudhi.wasserstein.wasserstein_distance(diag1, diag2, internal_p=2., q=1.) + message = "Wasserstein distance value = " + '%.2f' % gudhi.wasserstein.wasserstein_distance(diag1, diag2, order=1., internal_p=2.) print(message) The output is: diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index 2acf93d6..aef54f64 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -23,12 +23,12 @@ def _proj_on_diag(X): return np.array([Z , Z]).T -def _build_dist_matrix(X, Y, q=2., internal_p=2.): +def _build_dist_matrix(X, Y, order=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (points of the) first diagram. :param Y: (m x 2) numpy.array encoding the second diagram. :param internal_p: Ground metric (i.e. norm l_q). - :param q: exponent for the Wasserstein metric. + :param order: exponent for the Wasserstein metric. :returns: (n+1) x (m+1) np.array encoding the cost matrix C. For 1 <= i <= n, 1 <= j <= m, C[i,j] encodes the distance between X[i] and Y[j], while C[i, m+1] (resp. C[n+1, j]) encodes the distance (to the p) between X[i] (resp Y[j]) and its orthogonal proj onto the diagonal. note also that C[n+1, m+1] = 0 (it costs nothing to move from the diagonal to the diagonal). @@ -36,13 +36,13 @@ def _build_dist_matrix(X, Y, q=2., internal_p=2.): Xdiag = _proj_on_diag(X) Ydiag = _proj_on_diag(Y) if np.isinf(internal_p): - C = sc.cdist(X,Y, metric='chebyshev')**q - Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q - Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**q + C = sc.cdist(X,Y, metric='chebyshev')**order + Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**order + Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**order else: - C = sc.cdist(X,Y, metric='minkowski', p=internal_p)**q - Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q - Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**q + C = sc.cdist(X,Y, metric='minkowski', p=internal_p)**order + Cxd = np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**order + Cdy = np.linalg.norm(Y - Ydiag, ord=internal_p, axis=1)**order Cf = np.hstack((C, Cxd[:,None])) Cdy = np.append(Cdy, 0) @@ -51,23 +51,23 @@ def _build_dist_matrix(X, Y, q=2., internal_p=2.): return Cf -def _perstot(X, q, internal_p): +def _perstot(X, order, internal_p): ''' :param X: (n x 2) numpy.array (points of a given diagram). :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (Euclidean norm). - :param q: exponent for Wasserstein; Default value is 2. + :param order: exponent for Wasserstein; Default value is 2. :returns: float, the total persistence of the diagram (that is, its distance to the empty diagram). ''' Xdiag = _proj_on_diag(X) - return (np.sum(np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**q))**(1./q) + return (np.sum(np.linalg.norm(X - Xdiag, ord=internal_p, axis=1)**order))**(1./order) -def wasserstein_distance(X, Y, q=2., internal_p=2.): +def wasserstein_distance(X, Y, order=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (finite points of the) first diagram. Must not contain essential points (i.e. with infinite coordinate). :param Y: (m x 2) numpy.array encoding the second diagram. :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (euclidean norm). - :param q: exponent for Wasserstein; Default value is 2. + :param order: exponent for Wasserstein; Default value is 2. :returns: the q-Wasserstein distance (1 <= q < infinity) with respect to the internal_p-norm as ground metric. :rtype: float ''' @@ -79,11 +79,11 @@ def wasserstein_distance(X, Y, q=2., internal_p=2.): if Y.size == 0: return 0. else: - return _perstot(Y, q, internal_p) + return _perstot(Y, order, internal_p) elif Y.size == 0: - return _perstot(X, q, internal_p) + return _perstot(X, order, internal_p) - M = _build_dist_matrix(X, Y, q=q, internal_p=internal_p) + M = _build_dist_matrix(X, Y, order=order, internal_p=internal_p) a = np.full(n+1, 1. / (n + m) ) # weight vector of the input diagram. Uniform here. a[-1] = a[-1] * m # normalized so that we have a probability measure, required by POT b = np.full(m+1, 1. / (n + m) ) # weight vector of the input diagram. Uniform here. @@ -94,5 +94,5 @@ def wasserstein_distance(X, Y, q=2., internal_p=2.): # The default numItermax=100000 is not sufficient for some examples with 5000 points, what is a good value? ot_cost = (n+m) * ot.emd2(a, b, M, numItermax=2000000) - return ot_cost ** (1./q) + return ot_cost ** (1./order) diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 40112c1b..602e4bf1 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -23,26 +23,26 @@ def test_basic_wasserstein(): diag4 = np.array([[0, 3], [4, 8]]) emptydiag = np.array([[]]) - assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., q=1.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, q=1.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, q=2.) == 0. - assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., q=2.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=1.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=1.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=2.) == 0. + assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=2.) == 0. - assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, q=1.) == 2. - assert wasserstein_distance(diag3, emptydiag, internal_p=1., q=1.) == 4. + assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.) == 2. + assert wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.) == 4. - assert wasserstein_distance(diag4, emptydiag, internal_p=1., q=2.) == 5. # thank you Pythagorician triplets - assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, q=2.) == 2.5 - assert wasserstein_distance(diag4, emptydiag, internal_p=2., q=2.) == 3.5355339059327378 + assert wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.) == 5. # thank you Pythagorician triplets + assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.) == 2.5 + assert wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.) == 3.5355339059327378 - assert wasserstein_distance(diag1, diag2, internal_p=2., q=1.) == 1.4453593023967701 - assert wasserstein_distance(diag1, diag2, internal_p=2.35, q=1.74) == 0.9772734057168739 + assert wasserstein_distance(diag1, diag2, internal_p=2., order=1.) == 1.4453593023967701 + assert wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74) == 0.9772734057168739 - assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, q=1.7863) == 3.141592214572228 + assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863) == 3.141592214572228 - assert wasserstein_distance(diag3, diag4, internal_p=1., q=1.) == 3. - assert wasserstein_distance(diag3, diag4, internal_p=np.inf, q=1.) == 3. # no diag matching here - assert wasserstein_distance(diag3, diag4, internal_p=np.inf, q=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, internal_p=1., q=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, internal_p=4.5, q=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=1., order=1.) == 3. + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.) == 3. # no diag matching here + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=1., order=2.) == np.sqrt(5) + assert wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.) == np.sqrt(5) -- cgit v1.2.3 From cabafa3852c2d325b83593d34f16dfbc2d9eaefb Mon Sep 17 00:00:00 2001 From: tlacombe Date: Mon, 13 Jan 2020 17:30:38 +0100 Subject: fix typo in doc wasserstein_distance with new variables naming conventions. --- src/python/gudhi/wasserstein.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index aef54f64..b6495c80 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -55,7 +55,7 @@ def _perstot(X, order, internal_p): ''' :param X: (n x 2) numpy.array (points of a given diagram). :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (Euclidean norm). - :param order: exponent for Wasserstein; Default value is 2. + :param order: exponent for Wasserstein. Default value is 2. :returns: float, the total persistence of the diagram (that is, its distance to the empty diagram). ''' Xdiag = _proj_on_diag(X) @@ -68,7 +68,7 @@ def wasserstein_distance(X, Y, order=2., internal_p=2.): :param Y: (m x 2) numpy.array encoding the second diagram. :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (euclidean norm). :param order: exponent for Wasserstein; Default value is 2. - :returns: the q-Wasserstein distance (1 <= q < infinity) with respect to the internal_p-norm as ground metric. + :returns: the Wasserstein distance of order q (1 <= q < infinity) between persistence diagrams with respect to the internal_p-norm as ground metric. :rtype: float ''' n = len(X) -- cgit v1.2.3 From 9bbbc84ab7208ccd69934445202538e34439b304 Mon Sep 17 00:00:00 2001 From: Théo Lacombe Date: Mon, 13 Jan 2020 17:39:02 +0100 Subject: Update src/python/gudhi/wasserstein.py Co-Authored-By: Marc Glisse --- src/python/gudhi/wasserstein.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index b6495c80..3eb7faef 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -27,7 +27,7 @@ def _build_dist_matrix(X, Y, order=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (points of the) first diagram. :param Y: (m x 2) numpy.array encoding the second diagram. - :param internal_p: Ground metric (i.e. norm l_q). + :param internal_p: Ground metric (i.e. norm l_p). :param order: exponent for the Wasserstein metric. :returns: (n+1) x (m+1) np.array encoding the cost matrix C. For 1 <= i <= n, 1 <= j <= m, C[i,j] encodes the distance between X[i] and Y[j], while C[i, m+1] (resp. C[n+1, j]) encodes the distance (to the p) between X[i] (resp Y[j]) and its orthogonal proj onto the diagonal. @@ -95,4 +95,3 @@ def wasserstein_distance(X, Y, order=2., internal_p=2.): ot_cost = (n+m) * ot.emd2(a, b, M, numItermax=2000000) return ot_cost ** (1./order) - -- cgit v1.2.3 From 8848099734d1825c59e2bae5612883808d080d85 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 14 Jan 2020 16:16:24 +0100 Subject: Unlink Python2 for Python3 to be available through brew installation --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d6c82e70..60d32ef8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,10 +36,13 @@ cache: - $HOME/.cache/pip - $HOME/Library/Caches/Homebrew +before_install: + - brew update && brew unlink python@2 && brew upgrade python + addons: homebrew: - update: true packages: + - python3 - cmake - graphviz - doxygen @@ -49,7 +52,6 @@ addons: - mpfr - tbb - cgal - - python3 before_cache: - rm -f $HOME/.cache/pip/log/debug.log -- cgit v1.2.3 From 95c34035645e788d98a3fa6b059ad48024596906 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 15 Jan 2020 10:20:22 +0100 Subject: In python2 itertools zip_longest is named izip_longest --- src/python/test/test_alpha_complex.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 712a50b6..0d9e9e45 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -11,8 +11,13 @@ from gudhi import AlphaComplex, SimplexTree import math import numpy as np -import itertools import pytest +try: + # python3 + from itertools import zip_longest +except ImportError: + # python2 + from itertools import izip_longest as zip_longest __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -114,6 +119,6 @@ def test_safe_alpha_persistence_comparison(): diag1 = simplex_tree1.persistence() diag2 = simplex_tree2.persistence() - for (first_p, second_p) in itertools.zip_longest(diag1, diag2): + for (first_p, second_p) in zip_longest(diag1, diag2): assert first_p[0] == pytest.approx(second_p[0]) assert first_p[1] == pytest.approx(second_p[1]) -- cgit v1.2.3 From e1255fe356f1ff97533b33caa6179737a64c4898 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 15 Jan 2020 10:22:21 +0100 Subject: Fix #96 : set language_level. It does not work when using compiler_directives of cythonize. --- src/python/setup.py.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 24d05025..9c2124f4 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -11,6 +11,7 @@ from setuptools import setup, Extension from Cython.Build import cythonize from numpy import get_include as numpy_get_include +import sys __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -38,7 +39,8 @@ for module in modules: libraries=libraries, library_dirs=library_dirs, include_dirs=include_dirs, - runtime_library_dirs=runtime_library_dirs,)) + runtime_library_dirs=runtime_library_dirs, + cython_directives = {'language_level': str(sys.version_info[0])},)) setup( name = 'gudhi', -- cgit v1.2.3 From d747facccbe835be1384e569cf3d6e4c335c0364 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 15 Jan 2020 10:23:58 +0100 Subject: In python2, does not work. is ok for Python 2 and 3 --- src/python/gudhi/alpha_complex.pyx | 2 +- src/python/gudhi/cubical_complex.pyx | 2 +- src/python/gudhi/nerve_gic.pyx | 12 ++++++------ src/python/gudhi/off_reader.pyx | 2 +- src/python/gudhi/periodic_cubical_complex.pyx | 2 +- src/python/gudhi/reader_utils.pyx | 8 ++++---- src/python/gudhi/simplex_tree.pyx | 2 +- src/python/gudhi/subsampling.pyx | 8 ++++---- src/python/gudhi/tangential_complex.pyx | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index db11416c..f3ca3dd5 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -69,7 +69,7 @@ cdef class AlphaComplex: def __cinit__(self, points = None, off_file = ''): if off_file: if os.path.isfile(off_file): - self.thisptr = new Alpha_complex_interface(str.encode(off_file), True) + self.thisptr = new Alpha_complex_interface(off_file.encode('utf-8'), True) else: print("file " + off_file + " not found.") else: diff --git a/src/python/gudhi/cubical_complex.pyx b/src/python/gudhi/cubical_complex.pyx index 92ff6411..cbeda014 100644 --- a/src/python/gudhi/cubical_complex.pyx +++ b/src/python/gudhi/cubical_complex.pyx @@ -85,7 +85,7 @@ cdef class CubicalComplex: elif ((dimensions is None) and (top_dimensional_cells is None) and (perseus_file != '')): if os.path.isfile(perseus_file): - self.thisptr = new Bitmap_cubical_complex_base_interface(str.encode(perseus_file)) + self.thisptr = new Bitmap_cubical_complex_base_interface(perseus_file.encode('utf-8')) else: print("file " + perseus_file + " not found.") else: diff --git a/src/python/gudhi/nerve_gic.pyx b/src/python/gudhi/nerve_gic.pyx index 68c06432..382e71c5 100644 --- a/src/python/gudhi/nerve_gic.pyx +++ b/src/python/gudhi/nerve_gic.pyx @@ -180,7 +180,7 @@ cdef class CoverComplex: :returns: Read file status. """ if os.path.isfile(off_file): - return self.thisptr.read_point_cloud(str.encode(off_file)) + return self.thisptr.read_point_cloud(off_file.encode('utf-8')) else: print("file " + off_file + " not found.") return False @@ -212,7 +212,7 @@ cdef class CoverComplex: :type color_file_name: string """ if os.path.isfile(color_file_name): - self.thisptr.set_color_from_file(str.encode(color_file_name)) + self.thisptr.set_color_from_file(color_file_name.encode('utf-8')) else: print("file " + color_file_name + " not found.") @@ -233,7 +233,7 @@ cdef class CoverComplex: :type cover_file_name: string """ if os.path.isfile(cover_file_name): - self.thisptr.set_cover_from_file(str.encode(cover_file_name)) + self.thisptr.set_cover_from_file(cover_file_name.encode('utf-8')) else: print("file " + cover_file_name + " not found.") @@ -266,7 +266,7 @@ cdef class CoverComplex: :type func_file_name: string """ if os.path.isfile(func_file_name): - self.thisptr.set_function_from_file(str.encode(func_file_name)) + self.thisptr.set_function_from_file(func_file_name.encode('utf-8')) else: print("file " + func_file_name + " not found.") @@ -307,7 +307,7 @@ cdef class CoverComplex: :type graph_file_name: string """ if os.path.isfile(graph_file_name): - self.thisptr.set_graph_from_file(str.encode(graph_file_name)) + self.thisptr.set_graph_from_file(graph_file_name.encode('utf-8')) else: print("file " + graph_file_name + " not found.") @@ -368,7 +368,7 @@ cdef class CoverComplex: :param type: either "GIC" or "Nerve". :type type: string """ - self.thisptr.set_type(str.encode(type)) + self.thisptr.set_type(type.encode('utf-8')) def set_verbose(self, verbose): """Specifies whether the program should display information or not. diff --git a/src/python/gudhi/off_reader.pyx b/src/python/gudhi/off_reader.pyx index 58f05db8..a0d5bf25 100644 --- a/src/python/gudhi/off_reader.pyx +++ b/src/python/gudhi/off_reader.pyx @@ -30,7 +30,7 @@ def read_points_from_off_file(off_file=''): """ if off_file: if os.path.isfile(off_file): - return read_points_from_OFF_file(str.encode(off_file)) + return read_points_from_OFF_file(off_file.encode('utf-8')) else: print("file " + off_file + " not found.") return [] diff --git a/src/python/gudhi/periodic_cubical_complex.pyx b/src/python/gudhi/periodic_cubical_complex.pyx index b5dece10..37f76201 100644 --- a/src/python/gudhi/periodic_cubical_complex.pyx +++ b/src/python/gudhi/periodic_cubical_complex.pyx @@ -93,7 +93,7 @@ cdef class PeriodicCubicalComplex: elif ((dimensions is None) and (top_dimensional_cells is None) and (periodic_dimensions is None) and (perseus_file != '')): if os.path.isfile(perseus_file): - self.thisptr = new Periodic_cubical_complex_base_interface(str.encode(perseus_file)) + self.thisptr = new Periodic_cubical_complex_base_interface(perseus_file.encode('utf-8')) else: print("file " + perseus_file + " not found.") else: diff --git a/src/python/gudhi/reader_utils.pyx b/src/python/gudhi/reader_utils.pyx index 345c92f8..d6033b86 100644 --- a/src/python/gudhi/reader_utils.pyx +++ b/src/python/gudhi/reader_utils.pyx @@ -38,7 +38,7 @@ def read_lower_triangular_matrix_from_csv_file(csv_file='', separator=';'): """ if csv_file: if path.isfile(csv_file): - return read_matrix_from_csv_file(str.encode(csv_file), ord(separator[0])) + return read_matrix_from_csv_file(csv_file.encode('utf-8'), ord(separator[0])) print("file " + csv_file + " not set or not found.") return [] @@ -57,7 +57,7 @@ def read_persistence_intervals_grouped_by_dimension(persistence_file=''): """ if persistence_file: if path.isfile(persistence_file): - return read_pers_intervals_grouped_by_dimension(str.encode(persistence_file)) + return read_pers_intervals_grouped_by_dimension(persistence_file.encode('utf-8')) print("file " + persistence_file + " not set or not found.") return [] @@ -80,7 +80,7 @@ def read_persistence_intervals_in_dimension(persistence_file='', only_this_dim=- """ if persistence_file: if path.isfile(persistence_file): - return np_array(read_pers_intervals_in_dimension(str.encode( - persistence_file), only_this_dim)) + return np_array(read_pers_intervals_in_dimension(persistence_file.encode( + 'utf-8'), only_this_dim)) print("file " + persistence_file + " not set or not found.") return [] diff --git a/src/python/gudhi/simplex_tree.pyx b/src/python/gudhi/simplex_tree.pyx index 85d25492..b18627c4 100644 --- a/src/python/gudhi/simplex_tree.pyx +++ b/src/python/gudhi/simplex_tree.pyx @@ -508,7 +508,7 @@ cdef class SimplexTree: """ if self.pcohptr != NULL: if persistence_file != '': - self.pcohptr.write_output_diagram(str.encode(persistence_file)) + self.pcohptr.write_output_diagram(persistence_file.encode('utf-8')) else: print("persistence_file must be specified") else: diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index b1812087..c501d16b 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -52,10 +52,10 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi if off_file: if os.path.isfile(off_file): if starting_point == '': - return subsampling_n_farthest_points_from_file(str.encode(off_file), + return subsampling_n_farthest_points_from_file(off_file.encode('utf-8'), nb_points) else: - return subsampling_n_farthest_points_from_file(str.encode(off_file), + return subsampling_n_farthest_points_from_file(off_file.encode('utf-8'), nb_points, starting_point) else: @@ -88,7 +88,7 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): """ if off_file: if os.path.isfile(off_file): - return subsampling_n_random_points_from_file(str.encode(off_file), + return subsampling_n_random_points_from_file(off_file.encode('utf-8'), nb_points) else: print("file " + off_file + " not found.") @@ -118,7 +118,7 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): """ if off_file: if os.path.isfile(off_file): - return subsampling_sparsify_points_from_file(str.encode(off_file), + return subsampling_sparsify_points_from_file(off_file.encode('utf-8'), min_squared_dist) else: print("file " + off_file + " not found.") diff --git a/src/python/gudhi/tangential_complex.pyx b/src/python/gudhi/tangential_complex.pyx index 0083033c..6391488c 100644 --- a/src/python/gudhi/tangential_complex.pyx +++ b/src/python/gudhi/tangential_complex.pyx @@ -66,7 +66,7 @@ cdef class TangentialComplex: def __cinit__(self, intrisic_dim, points=None, off_file=''): if off_file: if os.path.isfile(off_file): - self.thisptr = new Tangential_complex_interface(intrisic_dim, str.encode(off_file), True) + self.thisptr = new Tangential_complex_interface(intrisic_dim, off_file.encode('utf-8'), True) else: print("file " + off_file + " not found.") else: -- cgit v1.2.3 From 9fbd7f8fd558a6045ff7f6508bb668ff8e689eba Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 16 Jan 2020 14:53:49 +0100 Subject: Version 3.1.0 to be released --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index eb2a0666..ed19ecfb 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,5 +1,5 @@ set (GUDHI_MAJOR_VERSION 3) -set (GUDHI_MINOR_VERSION 0) +set (GUDHI_MINOR_VERSION 1) set (GUDHI_PATCH_VERSION 0) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) -- cgit v1.2.3 From cabc43b34723efa7640313348b844eabe9971e38 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 16 Jan 2020 14:54:17 +0100 Subject: Version 3.1.0.rc1 to be released --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index ed19ecfb..8300b75e 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,6 +1,6 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 1) -set (GUDHI_PATCH_VERSION 0) +set (GUDHI_PATCH_VERSION 0.rc1) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") -- cgit v1.2.3 From 28388680567b885fe0a3a8c2364175b8879108fd Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 17 Jan 2020 07:45:56 +0100 Subject: Rename conventions.txt --- Conventions.txt | 1 - code_conventions.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 Conventions.txt create mode 100644 code_conventions.md diff --git a/Conventions.txt b/Conventions.txt deleted file mode 100644 index e4ae7925..00000000 --- a/Conventions.txt +++ /dev/null @@ -1 +0,0 @@ -Please refer to the Wiki: https://gforge.inria.fr/plugins/mediawiki/wiki/gudhi/index.php/Conventions \ No newline at end of file diff --git a/code_conventions.md b/code_conventions.md new file mode 100644 index 00000000..e4ae7925 --- /dev/null +++ b/code_conventions.md @@ -0,0 +1 @@ +Please refer to the Wiki: https://gforge.inria.fr/plugins/mediawiki/wiki/gudhi/index.php/Conventions \ No newline at end of file -- cgit v1.2.3 From 3c535f32b56ff5ef6656bac71f56749fa44fcf23 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 17 Jan 2020 07:48:47 +0100 Subject: Add code conventions in markdown format --- code_conventions.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/code_conventions.md b/code_conventions.md index e4ae7925..5882f78e 100644 --- a/code_conventions.md +++ b/code_conventions.md @@ -1 +1,26 @@ -Please refer to the Wiki: https://gforge.inria.fr/plugins/mediawiki/wiki/gudhi/index.php/Conventions \ No newline at end of file +# Naming conventions + +## C++ + +### In the code: +* The classes and functions of a package should be in a sub-namespace of the `Gudhi` namespace. The sub-namespace names are in lowercase and use underscore separators. E.g. `Gudhi::package_name::` +* Concepts are named with camel case starting with uppercase. E.g. `PersistentHomology` for the concept of Persitence homology. +* Classes start with an uppercase letter and use underscore separators. E.g. `Skeleton_blocker_contractor`. +* Member functions and free functions are in lowercase and use underscore separators. E.g. `int num_vertices()`. +* Constants and macros are in uppercase. +* Macros should begin with the prefix `GUDHI_`. + +### File names: +* All headers are named *.h and all sources are named *.cpp. +* If a single class or function is provided in a file, its name (with the same letter case) should be used for the file name. +* If a file does not contain a single class, its name should not begin with a capital letter. +* Test files should be called `test_[what_is_tested].cpp`. E.g. `test_sparsify_point_set.cpp` +* Example files should be called `example_[what_it_is].cpp`. E.g. `example_sparsify_point_set.cpp` + +### In CMakeLists.txt files: +* The name of the "project" should be in this form: `Package_[tests|examples|…]`. E.g. `project(Simplex_tree_examples)`. +* The name if each "target" (first parameter of add_executable) should be in this form: `Package_{name of the cpp file without extension}`. E.g `add_executable(Subsampling_test_sparsify_point_set test_sparsify_point_set.cpp)`. + +## Python + +In progress... \ No newline at end of file -- cgit v1.2.3 From 2583f7a332cf4d18102f23ab86ac32ba03c33075 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 17 Jan 2020 07:56:42 +0100 Subject: A base file for next release announcements --- next_release.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 next_release.md diff --git a/next_release.md b/next_release.md new file mode 100644 index 00000000..2bbb2aee --- /dev/null +++ b/next_release.md @@ -0,0 +1,35 @@ +We are pleased to announce the release 3.1.0 of the GUDHI library. + +As a major new feature, the GUDHI library now offers 2 new Python modules: Persistence representations and Wasserstein distance. + +We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.1.0.rc1.tar.gz). + +Below is a list of changes made since Gudhi 3.0.0: + +- [Persistence representations](https://gudhi.inria.fr/python/3.1.0.rc1/representations.html) (new Python module) + - Vectorizations, distances and kernels that work on persistence diagrams, compatible with scikit-learn. This module was originally available at https://github.com/MathieuCarriere/sklearn-tda and named sklearn_tda. + +- [Wasserstein distance](https://gudhi.inria.fr/python/3.1.0.rc1/wasserstein_distance_user.html) (new Python module) + - The q-Wasserstein distance measures the similarity between two persistence diagrams. + +- [Alpha complex](https://gudhi.inria.fr/doc/3.1.0.rc1/group__alpha__complex.html) (new C++ interface) + - Thanks to [CGAL 5.0 Epeck_d](https://doc.cgal.org/latest/Kernel_d/structCGAL_1_1Epeck__d.html) kernel, an exact computation version of Alpha complex dD is available and the default one (even in Python). + +- [Persistence graphical tools](https://gudhi.inria.fr/python/3.1.0.rc1/persistence_graphical_tools_user.html) (new Python interface) + - Axes as a parameter allows the user to subplot graphics. + - Use matplotlib default palette (can be user defined). + +- Miscellaneous + - Python `read_off` function has been renamed `read_points_from_off_file` as it only read points from OFF files. + - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.1.0+). + + +All modules are distributed under the terms of the MIT license. + +We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. + +We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. + +Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. + +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.0.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.0.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). \ No newline at end of file -- cgit v1.2.3 From 3c77e0fdf51f59c91e0b36a4f8ba32da85e27a5d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 17 Jan 2020 08:04:26 +0100 Subject: release review. Add some precisions on MIT --- next_release.md | 1 + 1 file changed, 1 insertion(+) diff --git a/next_release.md b/next_release.md index 2bbb2aee..6d749886 100644 --- a/next_release.md +++ b/next_release.md @@ -25,6 +25,7 @@ Below is a list of changes made since Gudhi 3.0.0: All modules are distributed under the terms of the MIT license. +There are still GPL dependencies for many modules, and so for an end-user it doesn't necessarily change much. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details about this change. We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. -- cgit v1.2.3 From f8a5efa165241b9e27f06431e4919322b359ddb2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 17 Jan 2020 09:13:37 +0100 Subject: No need to copy code conventions in user version --- src/cmake/modules/GUDHI_user_version_target.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmake/modules/GUDHI_user_version_target.cmake b/src/cmake/modules/GUDHI_user_version_target.cmake index 4fa74330..0b361a0f 100644 --- a/src/cmake/modules/GUDHI_user_version_target.cmake +++ b/src/cmake/modules/GUDHI_user_version_target.cmake @@ -32,8 +32,6 @@ file(COPY "${CMAKE_SOURCE_DIR}/biblio/bibliography.bib" DESTINATION "${CMAKE_CUR add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/biblio ${GUDHI_USER_VERSION_DIR}/biblio) -add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E - copy ${CMAKE_SOURCE_DIR}/Conventions.txt ${GUDHI_USER_VERSION_DIR}/Conventions.txt) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/README.md ${GUDHI_USER_VERSION_DIR}/README.md) add_custom_command(TARGET user_version PRE_BUILD COMMAND ${CMAKE_COMMAND} -E -- cgit v1.2.3 From f5e49792f809b198908a67e674672a676c0877ec Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 18 Jan 2020 22:56:22 +0100 Subject: Separate optional arguments from common arguments I copy-pasted what is done in RipsComplex. Before that, sphinx was grouping nb_points with off_file, as if it couldn't be used with points. --- src/python/gudhi/subsampling.pyx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/python/gudhi/subsampling.pyx b/src/python/gudhi/subsampling.pyx index 4c84cb03..f77c6f75 100644 --- a/src/python/gudhi/subsampling.pyx +++ b/src/python/gudhi/subsampling.pyx @@ -40,6 +40,8 @@ def choose_n_farthest_points(points=None, off_file='', nb_points=0, starting_poi :param off_file: An OFF file style name. :type off_file: string + And in both cases + :param nb_points: Number of points of the subsample. :type nb_points: unsigned. :param starting_point: The iteration starts with the landmark `starting \ @@ -81,6 +83,8 @@ def pick_n_random_points(points=None, off_file='', nb_points=0): :param off_file: An OFF file style name. :type off_file: string + And in both cases + :param nb_points: Number of points of the subsample. :type nb_points: unsigned. :returns: The subsample point set. @@ -110,6 +114,8 @@ def sparsify_point_set(points=None, off_file='', min_squared_dist=0.0): :param off_file: An OFF file style name. :type off_file: string + And in both cases + :param min_squared_dist: Minimum squared distance separating the output \ points. :type min_squared_dist: float. -- cgit v1.2.3 From cc126a733a994571f8fc8b6004a8c8c6c2c81718 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 18 Jan 2020 23:28:52 +0100 Subject: The license is not new anymore --- next_release.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/next_release.md b/next_release.md index 6d749886..08b736b1 100644 --- a/next_release.md +++ b/next_release.md @@ -20,12 +20,12 @@ Below is a list of changes made since Gudhi 3.0.0: - Use matplotlib default palette (can be user defined). - Miscellaneous - - Python `read_off` function has been renamed `read_points_from_off_file` as it only read points from OFF files. + - Python `read_off` function has been renamed `read_points_from_off_file` as it only reads points from OFF files. - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.1.0+). All modules are distributed under the terms of the MIT license. -There are still GPL dependencies for many modules, and so for an end-user it doesn't necessarily change much. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details about this change. +However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details. We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. @@ -33,4 +33,4 @@ We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) fo Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. -For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.0.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.0.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). \ No newline at end of file +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.0.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.0.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). -- cgit v1.2.3 From b36d27e63a6e60e3b84346aa3b3a95014b30068e Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 21 Nov 2019 23:49:07 +0100 Subject: Sprinkle some "except +" in cython files --- src/python/gudhi/alpha_complex.pyx | 11 +++++------ src/python/gudhi/euclidean_strong_witness_complex.pyx | 4 ++-- src/python/gudhi/euclidean_witness_complex.pyx | 4 ++-- src/python/gudhi/rips_complex.pyx | 2 +- src/python/gudhi/simplex_tree.pxd | 2 +- src/python/gudhi/strong_witness_complex.pyx | 4 ++-- src/python/gudhi/witness_complex.pyx | 4 ++-- src/python/include/Alpha_complex_interface.h | 10 +++------- 8 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/python/gudhi/alpha_complex.pyx b/src/python/gudhi/alpha_complex.pyx index f3ca3dd5..fff3e920 100644 --- a/src/python/gudhi/alpha_complex.pyx +++ b/src/python/gudhi/alpha_complex.pyx @@ -24,11 +24,11 @@ __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) + Alpha_complex_interface(vector[vector[double]] points) except + # 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) + Alpha_complex_interface(string off_file, bool from_file) except + + vector[double] get_point(int vertex) except + + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) except + # AlphaComplex python interface cdef class AlphaComplex: @@ -96,8 +96,7 @@ cdef class AlphaComplex: :rtype: list of float :returns: the point. """ - cdef vector[double] point = self.thisptr.get_point(vertex) - return point + return self.thisptr.get_point(vertex) def create_simplex_tree(self, max_alpha_square = float('inf')): """ diff --git a/src/python/gudhi/euclidean_strong_witness_complex.pyx b/src/python/gudhi/euclidean_strong_witness_complex.pyx index 9889f92c..aca6084e 100644 --- a/src/python/gudhi/euclidean_strong_witness_complex.pyx +++ b/src/python/gudhi/euclidean_strong_witness_complex.pyx @@ -22,9 +22,9 @@ __license__ = "GPL v3" cdef extern from "Euclidean_strong_witness_complex_interface.h" namespace "Gudhi": cdef cppclass Euclidean_strong_witness_complex_interface "Gudhi::witness_complex::Euclidean_strong_witness_complex_interface": Euclidean_strong_witness_complex_interface(vector[vector[double]] landmarks, vector[vector[double]] witnesses) - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) except + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, - unsigned limit_dimension) + unsigned limit_dimension) except + vector[double] get_point(unsigned vertex) # EuclideanStrongWitnessComplex python interface diff --git a/src/python/gudhi/euclidean_witness_complex.pyx b/src/python/gudhi/euclidean_witness_complex.pyx index e3ce0e82..fb0c2201 100644 --- a/src/python/gudhi/euclidean_witness_complex.pyx +++ b/src/python/gudhi/euclidean_witness_complex.pyx @@ -22,9 +22,9 @@ __license__ = "GPL v3" cdef extern from "Euclidean_witness_complex_interface.h" namespace "Gudhi": cdef cppclass Euclidean_witness_complex_interface "Gudhi::witness_complex::Euclidean_witness_complex_interface": Euclidean_witness_complex_interface(vector[vector[double]] landmarks, vector[vector[double]] witnesses) - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) except + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, - unsigned limit_dimension) + unsigned limit_dimension) except + vector[double] get_point(unsigned vertex) # EuclideanWitnessComplex python interface diff --git a/src/python/gudhi/rips_complex.pyx b/src/python/gudhi/rips_complex.pyx index 722cdcdc..deb8057a 100644 --- a/src/python/gudhi/rips_complex.pyx +++ b/src/python/gudhi/rips_complex.pyx @@ -28,7 +28,7 @@ cdef extern from "Rips_complex_interface.h" namespace "Gudhi": void init_matrix(vector[vector[double]] values, double threshold) void init_points_sparse(vector[vector[double]] values, double threshold, double sparse) void init_matrix_sparse(vector[vector[double]] values, double threshold, double sparse) - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, int dim_max) except + # RipsComplex python interface cdef class RipsComplex: diff --git a/src/python/gudhi/simplex_tree.pxd b/src/python/gudhi/simplex_tree.pxd index 1066d44b..96d14079 100644 --- a/src/python/gudhi/simplex_tree.pxd +++ b/src/python/gudhi/simplex_tree.pxd @@ -39,7 +39,7 @@ cdef extern from "Simplex_tree_interface.h" namespace "Gudhi": vector[pair[vector[int], double]] get_star(vector[int] simplex) vector[pair[vector[int], double]] get_cofaces(vector[int] simplex, int dimension) - void expansion(int max_dim) + void expansion(int max_dim) except + void remove_maximal_simplex(vector[int] simplex) bool prune_above_filtration(double filtration) bool make_filtration_non_decreasing() diff --git a/src/python/gudhi/strong_witness_complex.pyx b/src/python/gudhi/strong_witness_complex.pyx index 2c33c3f2..9f89d3ae 100644 --- a/src/python/gudhi/strong_witness_complex.pyx +++ b/src/python/gudhi/strong_witness_complex.pyx @@ -22,9 +22,9 @@ __license__ = "MIT" cdef extern from "Strong_witness_complex_interface.h" namespace "Gudhi": cdef cppclass Strong_witness_complex_interface "Gudhi::witness_complex::Strong_witness_complex_interface": Strong_witness_complex_interface(vector[vector[pair[size_t, double]]] nearest_landmark_table) - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) except + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, - unsigned limit_dimension) + unsigned limit_dimension) except + # StrongWitnessComplex python interface cdef class StrongWitnessComplex: diff --git a/src/python/gudhi/witness_complex.pyx b/src/python/gudhi/witness_complex.pyx index b032a5a1..e589d006 100644 --- a/src/python/gudhi/witness_complex.pyx +++ b/src/python/gudhi/witness_complex.pyx @@ -22,9 +22,9 @@ __license__ = "MIT" 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[pair[size_t, double]]] nearest_landmark_table) - void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square) except + void create_simplex_tree(Simplex_tree_interface_full_featured* simplex_tree, double max_alpha_square, - unsigned limit_dimension) + unsigned limit_dimension) except + # WitnessComplex python interface cdef class WitnessComplex: diff --git a/src/python/include/Alpha_complex_interface.h b/src/python/include/Alpha_complex_interface.h index e9bbadb0..8614eee3 100644 --- a/src/python/include/Alpha_complex_interface.h +++ b/src/python/include/Alpha_complex_interface.h @@ -50,13 +50,9 @@ class Alpha_complex_interface { std::vector get_point(int vh) { std::vector vd; - try { - Point_d const& ph = alpha_complex_->get_point(vh); - for (auto coord = ph.cartesian_begin(); coord != ph.cartesian_end(); coord++) - vd.push_back(CGAL::to_double(*coord)); - } catch (std::out_of_range const&) { - // std::out_of_range is thrown in case not found. Other exceptions must be re-thrown - } + Point_d const& ph = alpha_complex_->get_point(vh); + for (auto coord = ph.cartesian_begin(); coord != ph.cartesian_end(); coord++) + vd.push_back(CGAL::to_double(*coord)); return vd; } -- cgit v1.2.3 From d9bdb64a5bc016c5bc34f95f29773050e90aa7ed Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 22 Nov 2019 00:14:08 +0100 Subject: Adapt tests It is still failing by default, until I touch alpha_complex.pyx and rebuild it, after which it works ?! --- .../example/alpha_complex_from_points_example.py | 7 +++++- src/python/test/test_alpha_complex.py | 28 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/python/example/alpha_complex_from_points_example.py b/src/python/example/alpha_complex_from_points_example.py index a746998c..844d7a82 100755 --- a/src/python/example/alpha_complex_from_points_example.py +++ b/src/python/example/alpha_complex_from_points_example.py @@ -52,4 +52,9 @@ print("star([0])=", simplex_tree.get_star([0])) print("coface([0], 1)=", simplex_tree.get_cofaces([0], 1)) print("point[0]=", alpha_complex.get_point(0)) -print("point[5]=", alpha_complex.get_point(5)) +try: + print("point[5]=", alpha_complex.get_point(5)) +except IndexError: + pass +else: + assert False diff --git a/src/python/test/test_alpha_complex.py b/src/python/test/test_alpha_complex.py index 0d9e9e45..3761fe16 100755 --- a/src/python/test/test_alpha_complex.py +++ b/src/python/test/test_alpha_complex.py @@ -65,8 +65,18 @@ def test_infinite_alpha(): 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) == [] + try: + alpha_complex.get_point(4) == [] + except IndexError: + pass + else: + assert False + try: + alpha_complex.get_point(125) == [] + except IndexError: + pass + else: + assert False def test_filtered_alpha(): @@ -82,8 +92,18 @@ def test_filtered_alpha(): 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) == [] + try: + filtered_alpha.get_point(4) == [] + except IndexError: + pass + else: + assert False + try: + filtered_alpha.get_point(125) == [] + except IndexError: + pass + else: + assert False assert simplex_tree.get_filtration() == [ ([0], 0.0), -- cgit v1.2.3 From 784f9b5fdac6ff8c50b31479c1ae26f3efb823b2 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 20 Jan 2020 13:38:30 +0100 Subject: Release GUDHI 3.1.0 --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index 8300b75e..ed19ecfb 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,6 +1,6 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 1) -set (GUDHI_PATCH_VERSION 0.rc1) +set (GUDHI_PATCH_VERSION 0) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") -- cgit v1.2.3 From a7f3167ffb465bd6d1e3b9e40bc6f1c35daf87fc Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 16:43:37 +0100 Subject: Simplify the pybind11 code --- src/python/doc/wasserstein_distance_user.rst | 5 +++-- src/python/gudhi/hera.cc | 19 +++++-------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 6cd7f3a0..355ad247 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -11,8 +11,9 @@ Definition Functions --------- -This implementation is based on ideas from "Large Scale Computation of Means -and Cluster for Persistence Diagrams via Optimal Transport". +This implementation uses the Python Optimal Transport library and is based on +ideas from "Large Scale Computation of Means and Cluster for Persistence +Diagrams via Optimal Transport". .. autofunction:: gudhi.wasserstein.wasserstein_distance diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc index 898040fb..61f0da10 100644 --- a/src/python/gudhi/hera.cc +++ b/src/python/gudhi/hera.cc @@ -10,16 +10,6 @@ namespace py = pybind11; typedef py::array_t Dgm; -namespace hera { -template <> struct DiagramTraits{ - using PointType = std::array; - using RealType = double; - - static RealType get_x(const PointType& p) { return std::get<0>(p); } - static RealType get_y(const PointType& p) { return std::get<1>(p); } -}; -} - double wasserstein_distance( Dgm d1, Dgm d2, double wasserstein_power, double internal_p, @@ -32,7 +22,7 @@ double wasserstein_distance( throw std::runtime_error("Diagram 1 must be an array of size n x 2"); if((buf2.ndim!=2 || buf2.shape[1]!=2) && (buf2.ndim!=1 || buf2.shape[0]!=0)) throw std::runtime_error("Diagram 2 must be an array of size n x 2"); - typedef hera::DiagramTraits::PointType Point; + typedef std::array Point; auto p1 = (Point*)buf1.ptr; auto p2 = (Point*)buf2.ptr; auto diag1 = boost::make_iterator_range(p1, p1+buf1.shape[0]); @@ -52,16 +42,17 @@ PYBIND11_MODULE(hera, m) { m.def("wasserstein_distance", &wasserstein_distance, py::arg("X"), py::arg("Y"), // Should we name those q, p and d instead? - py::arg("wasserstein_power") = 1, + py::arg("order") = 1, py::arg("internal_p") = std::numeric_limits::infinity(), py::arg("delta") = .01, R"pbdoc( - Compute the Wasserstein distance between two diagrams. Points at infinity are supported. + Compute the Wasserstein distance between two diagrams. + Points at infinity are supported. Parameters: X (n x 2 numpy array): First diagram Y (n x 2 numpy array): Second diagram - wasserstein_power (float): Wasserstein degree W_q + order (float): Wasserstein exponent W_q internal_p (float): Internal Minkowski norm L^p in R^2 delta (float): Relative error 1+delta -- cgit v1.2.3 From 1783c047302414bbcd6ff4f7c73dcc5a6501fd81 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 17:51:28 +0100 Subject: Share tests for wasserstein_distance --- src/python/test/test_wasserstein_distance.py | 59 ++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 43dda77e..46a7079f 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -8,41 +8,66 @@ - YYYY/MM Author: Description of the modification """ -from gudhi.wasserstein import wasserstein_distance +from gudhi.wasserstein import wasserstein_distance as pot +from gudhi.hera import wasserstein_distance as hera import numpy as np __author__ = "Theo Lacombe" __copyright__ = "Copyright (C) 2019 Inria" __license__ = "MIT" - -def test_basic_wasserstein(): +def _basic_wasserstein(wasserstein_distance, delta, test_infinity=True): diag1 = np.array([[2.7, 3.7], [9.6, 14.0], [34.2, 34.974]]) diag2 = np.array([[2.8, 4.45], [9.5, 14.1]]) diag3 = np.array([[0, 2], [4, 6]]) diag4 = np.array([[0, 3], [4, 8]]) - emptydiag = np.array([[]]) + emptydiag = np.array([]) + + # We just need to handle positive numbers here + def approx(a, b): + f = 1 + delta + return a <= b*f and b <= a*f assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=1.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=1.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=2.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=2.) == 0. - assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.) == 2. - assert wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.) == 4. + assert approx(wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.), 2.) + assert approx(wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.), 4.) + + assert approx(wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.), 5.) # thank you Pythagorician triplets + assert approx(wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.), 2.5) + assert approx(wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.), 3.5355339059327378) + + assert approx(wasserstein_distance(diag1, diag2, internal_p=2., order=1.) , 1.4453593023967701) + assert approx(wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74), 0.9772734057168739) + + assert approx(wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863), 3.141592214572228) + + assert approx(wasserstein_distance(diag3, diag4, internal_p=1., order=1.), 3.) + assert approx(wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.), 3.) # no diag matching here + assert approx(wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.), np.sqrt(5)) + assert approx(wasserstein_distance(diag3, diag4, internal_p=1., order=2.), np.sqrt(5)) + assert approx(wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.), np.sqrt(5)) + + if(not test_infinity): + return - assert wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.) == 5. # thank you Pythagorician triplets - assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.) == 2.5 - assert wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.) == 3.5355339059327378 + diag5 = np.array([[0, 3], [4, np.inf]]) + diag6 = np.array([[7, 8], [4, 6], [3, np.inf]]) - assert wasserstein_distance(diag1, diag2, internal_p=2., order=1.) == 1.4453593023967701 - assert wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74) == 0.9772734057168739 + assert wasserstein_distance(diag4, diag5) == np.inf + assert approx(wasserstein_distance(diag5, diag6, order=1, internal_p=np.inf), 4.) - assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863) == 3.141592214572228 +def hera_wrap(delta): + def fun(*kargs,**kwargs): + return hera(*kargs,**kwargs,delta=delta) + return fun - assert wasserstein_distance(diag3, diag4, internal_p=1., order=1.) == 3. - assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.) == 3. # no diag matching here - assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, internal_p=1., order=2.) == np.sqrt(5) - assert wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.) == np.sqrt(5) +def test_wasserstein_distance_pot(): + _basic_wasserstein(pot, 1e-15, False) +def test_wasserstein_distance_hera(): + _basic_wasserstein(hera_wrap(1e-12), 1e-12) + _basic_wasserstein(hera_wrap(.1), .1) -- cgit v1.2.3 From a02397ba04d707dc79736ce2f598ebb74459bf90 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 18:20:45 +0100 Subject: Mention submodules in README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 167a38b3..f7e3d70c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,15 @@ The GUDHI library is a generic open source C++ library, with a Python interface, for Topological Data Analysis (TDA) and Higher Dimensional Geometry Understanding. The library offers state-of-the-art data structures and algorithms to construct simplicial complexes and compute persistent homology. +# Source code + +We recommend that users get official releases from [the GUDHI website](https://gudhi.inria.fr/). + +For potential contributors, to fully checkout GUDHI, after cloning the git repository, you may also need to checkout its submodules using +```sh +git submodule update --init +``` + # Compilation and installation To install GUDHI, you can follow the [C++ compilation procedure](https://gudhi.inria.fr/doc/latest/installation.html), the [Python compilation procedure](https://gudhi.inria.fr/python/latest/installation.html), use our [conda-forge package](https://gudhi.inria.fr/conda/), or [go with Docker](https://gudhi.inria.fr/dockerfile/). -- cgit v1.2.3 From 4c8e4549818bb033b148632abba4eae9ae9407c3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 19:17:14 +0100 Subject: Add pybind11 to Dockerfile_gudhi_installation --- Dockerfile_gudhi_installation | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation index 9fe20730..76b2628b 100644 --- a/Dockerfile_gudhi_installation +++ b/Dockerfile_gudhi_installation @@ -42,6 +42,7 @@ RUN apt-get install -y make \ python3-pip \ python3-pytest \ python3-tk \ + python3-pybind11 \ libfreetype6-dev \ pkg-config \ curl @@ -62,4 +63,4 @@ RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudh && make all test install \ && cmake -DWITH_GUDHI_PYTHON=ON . \ && cd python \ -&& python3 setup.py install \ No newline at end of file +&& python3 setup.py install -- cgit v1.2.3 From 6ee77c3da821256459406e87024077c48419a493 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 20:03:56 +0100 Subject: Shuffle the modules on the main page --- src/common/doc/main_page.md | 253 +++++++++++++++++++++----------------------- 1 file changed, 123 insertions(+), 130 deletions(-) diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index 0b4bfb7a..768c5794 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -4,8 +4,8 @@ \image html "Gudhi_banner.png"



-## Complexes {#Complexes} -### Cubical complex +## Data structures for cell complexes {#Complexes} +### Cubical complexes @@ -29,246 +29,269 @@
-### Simplicial complex - -#### Alpha complex +### Simplicial complexes +#### Simplex tree
- \image html "alpha_complex_representation.png" + \image html "Simplex_tree_representation.png" - Alpha complex 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 \f$ > \alpha^2 \f$ are removed from the Delaunay complex - when creating the simplicial complex if it is specified.
- For performances reasons, it is advised to use \ref cgal ≥ 5.0.0. + The simplex tree is an efficient and flexible + data structure for representing general (filtered) simplicial complexes. The data structure + is described in \cite boissonnatmariasimplextreealgorithmica .
- Author: Vincent Rouvreau
- Introduced in: GUDHI 1.3.0
- Copyright: MIT [(GPL v3)](../../licensing/)
- Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0 + Author: Clément Maria
+ Introduced in: GUDHI 1.0.0
+ Copyright: MIT
- User manual: \ref alpha_complex + User manual: \ref simplex_tree
-#### Čech complex +#### Skeleton blocker - +
- \image html "cech_complex_representation.png" + \image html "ds_representation.png" - The Čech complex is a simplicial complex constructed from a proximity graph. - The set of all simplices is filtered by the radius of their minimal enclosing ball. + The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* + representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the + 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. + This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but + operations that are particularly efficient are operations that do not require simplex enumeration such as edge + iteration, link computation or simplex contraction. - Author: Vincent Rouvreau
- Introduced in: GUDHI 2.2.0
- Copyright: MIT [(GPL v3)](../../licensing/)
- Includes: [Miniball](https://people.inf.ethz.ch/gaertner/subdir/software/miniball.html)
+ Author: David Salinas
+ Introduced in: GUDHI 1.1.0
+ Copyright: MIT
- User manual: \ref cech_complex + User manual: \ref skbl
-#### Rips complex +#### Toplex Map
- \image html "rips_complex_representation.png" + \image html "map.png" - Rips complex is a simplicial complex constructed from a one skeleton graph.
- The filtration value of each edge is computed from a user-given distance function and is inserted until a - user-given threshold value.
- This complex can be built from a point cloud and a distance function, or from a distance matrix. + The Toplex map data structure is composed firstly of a raw storage of toplices (the maximal simplices) + and secondly of a map which associate any vertex to a set of pointers toward all toplices + containing this vertex.
- Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse
- Introduced in: GUDHI 2.0.0
+ Author: François Godi
+ Introduced in: GUDHI 2.1.0
Copyright: MIT
- User manual: \ref rips_complex + User manual: \ref toplex_map
-#### Witness complex +#### Basic operation: contraction
- \image html "Witness_complex_representation.png" + \image html "sphere_contraction_representation.png" - Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$. - The data structure is described in \cite boissonnatmariasimplextreealgorithmica . + The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge + simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most + used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, + the size of this data-structure is even much lower than the total number of simplices. - Author: Siargey Kachanovich
- Introduced in: GUDHI 1.3.0
- Copyright: MIT ([GPL v3](../../licensing/) for Euclidean version)
- Euclidean version requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0 + Author: David Salinas
+ Introduced in: GUDHI 1.1.0
+ Copyright: MIT [(LGPL v3)](../../licensing/)
+ Requires: \ref cgal ≥ 4.11.0
- User manual: \ref witness_complex + User manual: \ref contr
-### Cover Complexes +## Filtrations and reconstructions +### Alpha complex +
- \image html "gicvisu.jpg" + \image html "alpha_complex_representation.png" - Nerves and Graph Induced Complexes are cover complexes, i.e. simplicial complexes that provably contain - topological information about the input data. They can be computed with a cover of the - data, that comes i.e. from the preimage of a family of intervals covering the image - of a scalar-valued function defined on the data.
+ Alpha complex 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 \f$ > \alpha^2 \f$ are removed from the Delaunay complex + when creating the simplicial complex if it is specified.
+ For performances reasons, it is advised to use \ref cgal ≥ 5.0.0.
- Author: Mathieu Carrière
- Introduced in: GUDHI 2.1.0
+ Author: Vincent Rouvreau
+ Introduced in: GUDHI 1.3.0
Copyright: MIT [(GPL v3)](../../licensing/)
- Requires: \ref cgal ≥ 4.11.0 + Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0
- User manual: \ref cover_complex + User manual: \ref alpha_complex
-## Data structures and basic operations {#DataStructuresAndBasicOperations} +### Čech complex + + + + + + + + + + +
+ \image html "cech_complex_representation.png" + + The Čech complex is a simplicial complex constructed from a proximity graph. + The set of all simplices is filtered by the radius of their minimal enclosing ball. + + Author: Vincent Rouvreau
+ Introduced in: GUDHI 2.2.0
+ Copyright: MIT [(GPL v3)](../../licensing/)
+ Includes: [Miniball](https://people.inf.ethz.ch/gaertner/subdir/software/miniball.html)
+
+ User manual: \ref cech_complex +
-### Data structures +### Rips complex -#### Simplex tree
- \image html "Simplex_tree_representation.png" + \image html "rips_complex_representation.png" - The simplex tree is an efficient and flexible - data structure for representing general (filtered) simplicial complexes. The data structure - is described in \cite boissonnatmariasimplextreealgorithmica . + Rips complex is a simplicial complex constructed from a one skeleton graph.
+ The filtration value of each edge is computed from a user-given distance function and is inserted until a + user-given threshold value.
+ This complex can be built from a point cloud and a distance function, or from a distance matrix.
- Author: Clément Maria
- Introduced in: GUDHI 1.0.0
+ Author: Clément Maria, Pawel Dlotko, Vincent Rouvreau, Marc Glisse
+ Introduced in: GUDHI 2.0.0
Copyright: MIT
- User manual: \ref simplex_tree + User manual: \ref rips_complex
-#### Skeleton blocker +### Witness complex
- \image html "ds_representation.png" + \image html "Witness_complex_representation.png" - The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* - representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the - 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. - This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but - operations that are particularly efficient are operations that do not require simplex enumeration such as edge - iteration, link computation or simplex contraction. + Witness complex \f$ Wit(W,L) \f$ is a simplicial complex defined on two sets of points in \f$\mathbb{R}^D\f$. + The data structure is described in \cite boissonnatmariasimplextreealgorithmica . - Author: David Salinas
- Introduced in: GUDHI 1.1.0
- Copyright: MIT
+ Author: Siargey Kachanovich
+ Introduced in: GUDHI 1.3.0
+ Copyright: MIT ([GPL v3](../../licensing/) for Euclidean version)
+ Euclidean version requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0
- User manual: \ref skbl + User manual: \ref witness_complex
-#### Toplex Map - +### Cover Complexes
- \image html "map.png" + \image html "gicvisu.jpg" - The Toplex map data structure is composed firstly of a raw storage of toplices (the maximal simplices) - and secondly of a map which associate any vertex to a set of pointers toward all toplices - containing this vertex. + Nerves and Graph Induced Complexes are cover complexes, i.e. simplicial complexes that provably contain + topological information about the input data. They can be computed with a cover of the + data, that comes i.e. from the preimage of a family of intervals covering the image + of a scalar-valued function defined on the data.
- Author: François Godi
+ Author: Mathieu Carrière
Introduced in: GUDHI 2.1.0
- Copyright: MIT
+ Copyright: MIT [(GPL v3)](../../licensing/)
+ Requires: \ref cgal ≥ 4.11.0
- User manual: \ref toplex_map + User manual: \ref cover_complex
-### Basic operations - -#### Contraction +### Tangential complex
- \image html "sphere_contraction_representation.png" + \image html "tc_examples.png" - The purpose of this package is to offer a user-friendly interface for edge contraction simplification of huge - simplicial complexes. It uses the \ref skbl data-structure whose size remains small during simplification of most - used geometrical complexes of topological data analysis such as the Rips or the Delaunay complexes. In practice, - the size of this data-structure is even much lower than the total number of simplices. + A Tangential Delaunay complex is a simplicial complex + designed to reconstruct a \f$ k \f$-dimensional manifold embedded in \f$ d \f$-dimensional Euclidean space. + The input is a point sample coming from an unknown manifold. + The running time depends only linearly on the extrinsic dimension \f$ d \f$ + and exponentially on the intrinsic dimension \f$ k \f$. - Author: David Salinas
- Introduced in: GUDHI 1.1.0
- Copyright: MIT [(LGPL v3)](../../licensing/)
- Requires: \ref cgal ≥ 4.11.0 + Author: Clément Jamin
+ Introduced in: GUDHI 2.0.0
+ Copyright: MIT [(GPL v3)](../../licensing/)
+ Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0
- User manual: \ref contr + User manual: \ref tangential_complex
@@ -305,36 +328,6 @@ -## Manifold reconstruction {#ManifoldReconstruction} - -### Tangential complex - - - - - - - - - - -
- \image html "tc_examples.png" - - A Tangential Delaunay complex is a simplicial complex - designed to reconstruct a \f$ k \f$-dimensional manifold embedded in \f$ d \f$-dimensional Euclidean space. - The input is a point sample coming from an unknown manifold. - The running time depends only linearly on the extrinsic dimension \f$ d \f$ - and exponentially on the intrinsic dimension \f$ k \f$. - - Author: Clément Jamin
- Introduced in: GUDHI 2.0.0
- Copyright: MIT [(GPL v3)](../../licensing/)
- Requires: \ref eigen ≥ 3.1.0 and \ref cgal ≥ 4.11.0 -
- User manual: \ref tangential_complex -
- ## Topological descriptors tools {#TopologicalDescriptorsTools} ### Bottleneck distance -- cgit v1.2.3 From 82b4a1e765adc6ec9d37b1bfb09ce443f642cb08 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 20:11:28 +0100 Subject: Missing entry in TOC --- src/common/doc/main_page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index 768c5794..90afb05d 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -135,7 +135,7 @@ -## Filtrations and reconstructions +## Filtrations and reconstructions {#FiltrationsReconstructions} ### Alpha complex -- cgit v1.2.3 From 8c85fa3f6dcb47346f3070adc46d44c9afca2f2c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 20:26:18 +0100 Subject: Reorder skbl and toplexmap so that skbl is next to contractions --- src/common/doc/main_page.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index 90afb05d..23dd3fde 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -55,55 +55,55 @@
-#### Skeleton blocker +#### Toplex Map
- \image html "ds_representation.png" + \image html "map.png" - The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* - representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the - 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. - This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but - operations that are particularly efficient are operations that do not require simplex enumeration such as edge - iteration, link computation or simplex contraction. + The Toplex map data structure is composed firstly of a raw storage of toplices (the maximal simplices) + and secondly of a map which associate any vertex to a set of pointers toward all toplices + containing this vertex. - Author: David Salinas
- Introduced in: GUDHI 1.1.0
+ Author: François Godi
+ Introduced in: GUDHI 2.1.0
Copyright: MIT
- User manual: \ref skbl + User manual: \ref toplex_map
-#### Toplex Map +#### Skeleton blocker
- \image html "map.png" + \image html "ds_representation.png" - The Toplex map data structure is composed firstly of a raw storage of toplices (the maximal simplices) - and secondly of a map which associate any vertex to a set of pointers toward all toplices - containing this vertex. + The Skeleton-Blocker data-structure proposes a light encoding for simplicial complexes by storing only an *implicit* + representation of its simplices \cite socg_blockers_2011,\cite blockers2012. Intuitively, it just stores the + 1-skeleton of a simplicial complex with a graph and the set of its "missing faces" that is very small in practice. + This data-structure handles all simplicial complexes operations such as simplex enumeration or simplex removal but + operations that are particularly efficient are operations that do not require simplex enumeration such as edge + iteration, link computation or simplex contraction. - Author: François Godi
- Introduced in: GUDHI 2.1.0
+ Author: David Salinas
+ Introduced in: GUDHI 1.1.0
Copyright: MIT
- User manual: \ref toplex_map + User manual: \ref skbl
-- cgit v1.2.3 From dc3d21f55d3e0de311f56b2706629483f50b0258 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 20:36:58 +0100 Subject: Link kd-tree and subsampling from the main doc --- src/common/doc/main_page.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index 23dd3fde..72bf1cef 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -383,3 +383,26 @@ + +## Point cloud utilities {#PointCloudUtils} + + + + + + + + + + +
+ \f$(x_1,\ldots\x_d)\f$ + + This contains various tools to handle point clouds: spatial searching, subsampling, etc. + + Author: Clément Jamin
+ Introduced in: GUDHI 1.3.0
+ Copyright: MIT [(GPL v3)](../../licensing/)
+
+ Manuals: \ref spatial_searching, \ref subsampling +
-- cgit v1.2.3 From 43b6452cf36e92595e4fd05bdeca6c5eeaf95e86 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 20 Jan 2020 20:55:33 +0100 Subject: Typo --- src/common/doc/main_page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/doc/main_page.md b/src/common/doc/main_page.md index 72bf1cef..6ea10b88 100644 --- a/src/common/doc/main_page.md +++ b/src/common/doc/main_page.md @@ -389,7 +389,7 @@
- \f$(x_1,\ldots\x_d)\f$ + \f$(x_1,\ldots,x_d)\f$ This contains various tools to handle point clouds: spatial searching, subsampling, etc. -- cgit v1.2.3 From 5572f6a59390d389535925b8c68de429bc32861b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 27 Jan 2020 09:42:35 +0100 Subject: Reset for next release --- next_release.md | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/next_release.md b/next_release.md index 08b736b1..b85afdf5 100644 --- a/next_release.md +++ b/next_release.md @@ -1,27 +1,19 @@ -We are pleased to announce the release 3.1.0 of the GUDHI library. +We are pleased to announce the release 3.X.X of the GUDHI library. As a major new feature, the GUDHI library now offers 2 new Python modules: Persistence representations and Wasserstein distance. -We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.1.0.rc1.tar.gz). +We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz). -Below is a list of changes made since Gudhi 3.0.0: +Below is a list of changes made since Gudhi 3.1.0: -- [Persistence representations](https://gudhi.inria.fr/python/3.1.0.rc1/representations.html) (new Python module) - - Vectorizations, distances and kernels that work on persistence diagrams, compatible with scikit-learn. This module was originally available at https://github.com/MathieuCarriere/sklearn-tda and named sklearn_tda. +- [Module](link) + - ... -- [Wasserstein distance](https://gudhi.inria.fr/python/3.1.0.rc1/wasserstein_distance_user.html) (new Python module) - - The q-Wasserstein distance measures the similarity between two persistence diagrams. - -- [Alpha complex](https://gudhi.inria.fr/doc/3.1.0.rc1/group__alpha__complex.html) (new C++ interface) - - Thanks to [CGAL 5.0 Epeck_d](https://doc.cgal.org/latest/Kernel_d/structCGAL_1_1Epeck__d.html) kernel, an exact computation version of Alpha complex dD is available and the default one (even in Python). - -- [Persistence graphical tools](https://gudhi.inria.fr/python/3.1.0.rc1/persistence_graphical_tools_user.html) (new Python interface) - - Axes as a parameter allows the user to subplot graphics. - - Use matplotlib default palette (can be user defined). +- [Module](link) + - ... - Miscellaneous - - Python `read_off` function has been renamed `read_points_from_off_file` as it only reads points from OFF files. - - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.1.0+). + - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.X.X+). All modules are distributed under the terms of the MIT license. -- cgit v1.2.3 From 1e061ddfe473aceb8727fc5ca160193bf9d9a4fc Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 27 Jan 2020 09:44:13 +0100 Subject: Reset for next release --- next_release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next_release.md b/next_release.md index b85afdf5..26d4fca5 100644 --- a/next_release.md +++ b/next_release.md @@ -1,6 +1,6 @@ We are pleased to announce the release 3.X.X of the GUDHI library. -As a major new feature, the GUDHI library now offers 2 new Python modules: Persistence representations and Wasserstein distance. +As a major new feature, the GUDHI library now offers ... We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz). -- cgit v1.2.3 From 48952ee2ad76e2f4e5ada7f038ff88dee496272a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 30 Jan 2020 11:58:52 +0100 Subject: Allow use of preinstalled Hera --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 3 +++ src/python/setup.py.in | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index cb9f9033..359d1c12 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -35,6 +35,9 @@ if(CGAL_FOUND) include( ${CGAL_USE_FILE} ) endif() +# For those who dislike bundled dependencies, this indicates where to find a preinstalled Hera. +set(HERA_WASSERSTEIN_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/ext/hera/geom_matching/wasserstein/include CACHE PATH "Directory where one can find Hera's wasserstein.h") + option(WITH_GUDHI_USE_TBB "Build with Intel TBB parallelization" ON) # Find TBB package for parallel sort - not mandatory, just optional. diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 08c46ced..851188bd 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -63,7 +63,7 @@ ext_modules.append(Extension( sources = [source_dir + 'hera.cc'], language = 'c++', include_dirs = include_dirs + - ['@CMAKE_SOURCE_DIR@/ext/hera/geom_matching/wasserstein/include', + ['@HERA_WASSERSTEIN_INCLUDE_DIR@', get_pybind_include(False), get_pybind_include(True)], extra_compile_args=extra_compile_args + [@GUDHI_PYBIND11_EXTRA_COMPILE_ARGS@], )) -- cgit v1.2.3 From 09cf8752c50f25acac0eb1a6369624399431b2ca Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 30 Jan 2020 12:14:20 +0100 Subject: Document dependency on pybind11 --- src/python/doc/installation.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 40f3f44b..f8456799 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -257,6 +257,14 @@ The :doc:`Wasserstein distance ` module requires `POT `_, a library that provides several solvers for optimization problems related to Optimal Transport. +Pybind11 +======== + +The :doc:`Wasserstein distance ` module requires +`pybind11 `_, a library that provides +interoperability between C++ and Python, for its interface to `Hera +`_. + Scikit-learn ============ -- cgit v1.2.3 From 0cbf41493cee2b9bd598557b97df9b1211da2b9d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 30 Jan 2020 18:04:20 +0100 Subject: Use mutex from stl instead of tbb one that is deprecated --- src/Nerve_GIC/include/gudhi/GIC.h | 8 ++++---- src/Tangential_complex/include/gudhi/Tangential_complex.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h index a47d6889..2a6d4788 100644 --- a/src/Nerve_GIC/include/gudhi/GIC.h +++ b/src/Nerve_GIC/include/gudhi/GIC.h @@ -14,7 +14,7 @@ #ifdef GUDHI_USE_TBB #include -#include +#include #endif #include @@ -459,7 +459,7 @@ class Cover_complex { // This cannot be parallelized if thread_local is not defined // thread_local is not defined for XCode < v.8 #if defined(GUDHI_USE_TBB) && defined(GUDHI_CAN_USE_CXX11_THREAD_LOCAL) - tbb::mutex deltamutex; + std::mutex deltamutex; tbb::parallel_for(0, N, [&](int i){ std::vector samples(m); SampleWithoutReplacement(n, m, samples); @@ -765,7 +765,7 @@ class Cover_complex { #ifdef GUDHI_USE_TBB if (verbose) std::cout << "Computing connected components (parallelized)..." << std::endl; - tbb::mutex covermutex, idmutex; + std::mutex covermutex, idmutex; tbb::parallel_for(0, res, [&](int i){ // Compute connected components Graph G = one_skeleton.create_subgraph(); @@ -895,7 +895,7 @@ class Cover_complex { // Compute the geodesic distances to subsamples with Dijkstra #ifdef GUDHI_USE_TBB if (verbose) std::cout << "Computing geodesic distances (parallelized)..." << std::endl; - tbb::mutex coverMutex; tbb::mutex mindistMutex; + std::mutex coverMutex; std::mutex mindistMutex; tbb::parallel_for(0, m, [&](int i){ int seed = voronoi_subsamples[i]; std::vector dmap(n); diff --git a/src/Tangential_complex/include/gudhi/Tangential_complex.h b/src/Tangential_complex/include/gudhi/Tangential_complex.h index f058fa9f..f007bdd5 100644 --- a/src/Tangential_complex/include/gudhi/Tangential_complex.h +++ b/src/Tangential_complex/include/gudhi/Tangential_complex.h @@ -60,7 +60,7 @@ #ifdef GUDHI_USE_TBB #include #include -#include +#include #endif // #define GUDHI_TC_EXPORT_NORMALS // Only for 3D surfaces (k=2, d=3) @@ -147,7 +147,7 @@ class Tangential_complex { typedef typename Tr_traits::Vector_d Tr_vector; #if defined(GUDHI_USE_TBB) - typedef tbb::mutex Mutex_for_perturb; + typedef std::mutex Mutex_for_perturb; typedef Vector Translation_for_perturb; typedef std::vector > Weights; #else -- cgit v1.2.3 From 59116c450bf912a4b446b02e55278f3ec55a90ee Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 3 Feb 2020 18:48:36 +0100 Subject: Contradictory requirements for CGAL --- src/python/doc/alpha_complex_sum.inc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/python/doc/alpha_complex_sum.inc b/src/python/doc/alpha_complex_sum.inc index a1184663..b5af0d27 100644 --- a/src/python/doc/alpha_complex_sum.inc +++ b/src/python/doc/alpha_complex_sum.inc @@ -5,16 +5,13 @@ | .. figure:: | Alpha complex is a simplicial complex constructed from the finite | :Author: Vincent Rouvreau | | ../../doc/Alpha_complex/alpha_complex_representation.png | cells of a Delaunay Triangulation. | | | :alt: Alpha complex representation | | :Introduced in: GUDHI 2.0.0 | - | :figclass: align-center | The filtration value of each simplex is computed as the square of the | | - | | circumradius of the simplex if the circumsphere is empty (the simplex | :Copyright: MIT (`GPL v3 `_) | - | | is then said to be Gabriel), and as the minimum of the filtration | | - | | values of the codimension 1 cofaces that make it not Gabriel | :Requires: `Eigen `__ :math:`\geq` 3.1.0 and `CGAL `__ :math:`\geq` 4.11.0 | - | | otherwise. All simplices that have a filtration value | | - | | :math:`> \alpha^2` are removed from the Delaunay complex | | - | | when creating the simplicial complex if it is specified. | | + | :figclass: align-center | The filtration value of each simplex is computed as the **square** of | | + | | the circumradius of the simplex if the circumsphere is empty (the | :Copyright: MIT (`GPL v3 `_) | + | | simplex is then said to be Gabriel), and as the minimum of the | | + | | filtration values of the codimension 1 cofaces that make it not | :Requires: `Eigen `__ :math:`\geq` 3.1.0 and `CGAL `__ :math:`\geq` 4.11.0 | + | | Gabriel otherwise. | | | | | | - | | This package requires having CGAL version 4.7 or higher (4.8.1 is | | - | | advised for better performance). | | + | | For performances reasons, it is advised to use CGAL ≥ 5.0.0. | | +----------------------------------------------------------------+------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+ | * :doc:`alpha_complex_user` | * :doc:`alpha_complex_ref` | +----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -- cgit v1.2.3 From 53f90be09bcfafd8edda763ba1532c519847929a Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 4 Feb 2020 16:59:49 +0100 Subject: Dockerfile_gudhi_installation for gudhi 3.1.0 version --- Dockerfile_gudhi_installation | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation index 9fe20730..d5d86338 100644 --- a/Dockerfile_gudhi_installation +++ b/Dockerfile_gudhi_installation @@ -50,14 +50,16 @@ RUN pip3 install \ numpy \ matplotlib \ scipy \ - Cython + Cython \ + POT \ + scikit-learn # apt clean up RUN apt autoremove && rm -rf /var/lib/apt/lists/* -RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.0.0/gudhi.3.0.0.tar.gz" \ -&& tar xf gudhi.3.0.0.tar.gz \ -&& cd gudhi.3.0.0 \ +RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.1.0/gudhi.3.1.0.tar.gz" \ +&& tar xf gudhi.3.1.0.tar.gz \ +&& cd gudhi.3.1.0 \ && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_PYTHON=OFF -DPython_ADDITIONAL_VERSIONS=3 .. \ && make all test install \ && cmake -DWITH_GUDHI_PYTHON=ON . \ -- cgit v1.2.3 From 08596f907e5b4fb99a5c9d51799f54f1b0535071 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 4 Feb 2020 18:05:42 +0100 Subject: Fix #186 - Link with TBB for all simplex tree user --- src/Simplex_tree/example/CMakeLists.txt | 3 +++ src/Witness_complex/example/CMakeLists.txt | 10 +++++++++- src/common/doc/installation.h | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Simplex_tree/example/CMakeLists.txt b/src/Simplex_tree/example/CMakeLists.txt index f99b164c..8a8cac58 100644 --- a/src/Simplex_tree/example/CMakeLists.txt +++ b/src/Simplex_tree/example/CMakeLists.txt @@ -16,6 +16,9 @@ endif() add_test(NAME Simplex_tree_example_simple_simplex_tree COMMAND $) add_executable ( Simplex_tree_example_mini_simplex_tree mini_simplex_tree.cpp ) +if (TBB_FOUND) + target_link_libraries(Simplex_tree_example_mini_simplex_tree ${TBB_LIBRARIES}) +endif() add_test(NAME Simplex_tree_example_mini_simplex_tree COMMAND $) # An example with Simplex-tree using CGAL alpha_shapes_3 diff --git a/src/Witness_complex/example/CMakeLists.txt b/src/Witness_complex/example/CMakeLists.txt index 5860f3a3..2659798e 100644 --- a/src/Witness_complex/example/CMakeLists.txt +++ b/src/Witness_complex/example/CMakeLists.txt @@ -12,10 +12,18 @@ install(TARGETS Witness_complex_example_nearest_landmark_table DESTINATION bin) # CGAL and Eigen3 are required for Euclidean version of Witness if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0) add_executable( Witness_complex_example_off example_witness_complex_off.cpp ) + if (TBB_FOUND) + target_link_libraries(Witness_complex_example_off ${TBB_LIBRARIES}) + endif() add_executable ( Witness_complex_example_sphere example_witness_complex_sphere.cpp ) + if (TBB_FOUND) + target_link_libraries(Witness_complex_example_sphere ${TBB_LIBRARIES}) + endif() add_executable( Witness_complex_example_strong_off example_strong_witness_complex_off.cpp ) - target_link_libraries(Witness_complex_example_strong_off) + if (TBB_FOUND) + target_link_libraries(Witness_complex_example_strong_off ${TBB_LIBRARIES}) + endif() add_test(NAME Witness_complex_example_off_test_torus COMMAND $ diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index ce2c5448..c2da1ba0 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -204,6 +204,8 @@ make doxygen * Nerve_GIC/Nerve.cpp * \li * Nerve_GIC/VoronoiGIC.cpp + * \li + * Simplex_tree/mini_simplex_tree.cpp * \li * Simplex_tree/simple_simplex_tree.cpp * \li @@ -244,6 +246,12 @@ make doxygen * Witness_complex/weak_witness_persistence.cpp * \li * Witness_complex/example_nearest_landmark_table.cpp + * \li + * Witness_complex/example_strong_witness_complex_off.cpp + * \li + * Witness_complex/example_witness_complex_off.cpp + * \li + * Witness_complex/example_witness_complex_sphere.cpp * * \section Contributions Bug reports and contributions * Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to: -- cgit v1.2.3 From fd6db1cb3c60199b0c7c0eafd4d10e527a505ac3 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Tue, 4 Feb 2020 21:58:52 +0100 Subject: Code review: Rollback installation as these examples are not optimized with TBB --- src/common/doc/installation.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index c2da1ba0..ce2c5448 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -204,8 +204,6 @@ make doxygen * Nerve_GIC/Nerve.cpp * \li * Nerve_GIC/VoronoiGIC.cpp - * \li - * Simplex_tree/mini_simplex_tree.cpp * \li * Simplex_tree/simple_simplex_tree.cpp * \li @@ -246,12 +244,6 @@ make doxygen * Witness_complex/weak_witness_persistence.cpp * \li * Witness_complex/example_nearest_landmark_table.cpp - * \li - * Witness_complex/example_strong_witness_complex_off.cpp - * \li - * Witness_complex/example_witness_complex_off.cpp - * \li - * Witness_complex/example_witness_complex_sphere.cpp * * \section Contributions Bug reports and contributions * Please help us improving the quality of the GUDHI library. You may report bugs or suggestions to: -- cgit v1.2.3 From 966a8e0131cb55d815bfe6c8286c9d7865f1a32f Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Wed, 5 Feb 2020 16:09:45 +0100 Subject: Add gudhi.representations in setup.py packages --- src/python/setup.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 9c2124f4..f993165c 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -44,7 +44,7 @@ for module in modules: setup( name = 'gudhi', - packages=["gudhi",], + packages=["gudhi","gudhi.representations"], author='GUDHI Editorial Board', author_email='gudhi-contact@lists.gforge.inria.fr', version='@GUDHI_VERSION@', -- cgit v1.2.3 From 15e0accb230b2f618e361b96e7f7b2c766179a68 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 10:15:04 +0100 Subject: Install version, clean compilation and test the installed version --- .circleci/config.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e45bc14..34910ad6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,7 @@ jobs: python: docker: - image: gudhi/ci_for_gudhi:latest + parallelism: 4 steps: - checkout - run: @@ -58,10 +59,12 @@ jobs: mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..; - make all; - ctest --output-on-failure; + python setup.py build_ext -j 4 --inplace; make sphinx; cp -R python/sphinx /tmp/sphinx; + python setup.py install; + python setup.py clean --all; + ctest -j 4 --output-on-failure; - store_artifacts: path: /tmp/sphinx -- cgit v1.2.3 From dc44366683dd87d362c82fe2d93cee8d52dc3f28 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 10:53:06 +0100 Subject: must change directory to build python --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 34910ad6..4edb0e1b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,6 +59,7 @@ jobs: mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..; + cd python; python setup.py build_ext -j 4 --inplace; make sphinx; cp -R python/sphinx /tmp/sphinx; -- cgit v1.2.3 From 4ba35f8120c897b378b84e6f0e4b955d254f683e Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 11:10:19 +0100 Subject: Add setuptools --- Dockerfile_for_circleci_image | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index ff4e6018..b7d0dcca 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -49,6 +49,7 @@ RUN apt-get install -y make \ pkg-config RUN pip3 install \ + setuptools \ numpy \ matplotlib \ scipy \ -- cgit v1.2.3 From 7833223f55ca261f4592efd7fbb1ae3002f40f3d Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 12:49:39 +0100 Subject: Try to use a specific version of docker file --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4edb0e1b..a166a439 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,7 @@ jobs: python: docker: - - image: gudhi/ci_for_gudhi:latest + - image: gudhi/ci_for_gudhi@sha256:9c90c7965f2288470fd5b374200f5b1bc23a9bd9939ece9f1bf864a6135fccb5 parallelism: 4 steps: - checkout -- cgit v1.2.3 From b84ea8b77c759e8f8c84ca1b21f5eded3a975a50 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 13:06:10 +0100 Subject: Use python3 --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a166a439..abcd52dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -60,11 +60,11 @@ jobs: cd build; cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 ..; cd python; - python setup.py build_ext -j 4 --inplace; + python3 setup.py build_ext -j 4 --inplace; make sphinx; cp -R python/sphinx /tmp/sphinx; - python setup.py install; - python setup.py clean --all; + python3 setup.py install; + python3 setup.py clean --all; ctest -j 4 --output-on-failure; - store_artifacts: -- cgit v1.2.3 From 9e955b7088ac19cf701b213337d8ea29355f0b40 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 13:11:31 +0100 Subject: Rollback latest docker tag --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index abcd52dd..d9678852 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,7 @@ jobs: python: docker: - - image: gudhi/ci_for_gudhi@sha256:9c90c7965f2288470fd5b374200f5b1bc23a9bd9939ece9f1bf864a6135fccb5 + - image: gudhi/ci_for_gudhi:latest parallelism: 4 steps: - checkout -- cgit v1.2.3 From 31d3c96d65737fbeb0c8762b1f7e7ac4f5aaeab8 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 13:22:55 +0100 Subject: python change directory make copy fail --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d9678852..f4073746 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -62,7 +62,7 @@ jobs: cd python; python3 setup.py build_ext -j 4 --inplace; make sphinx; - cp -R python/sphinx /tmp/sphinx; + cp -R sphinx /tmp/sphinx; python3 setup.py install; python3 setup.py clean --all; ctest -j 4 --output-on-failure; -- cgit v1.2.3 From 2dbe066378ed3b5b4913775873326d0d62a7f1b9 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 13:54:13 +0100 Subject: language_level was not properly set --- src/python/setup.py.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index f993165c..c434f659 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -39,8 +39,7 @@ for module in modules: libraries=libraries, library_dirs=library_dirs, include_dirs=include_dirs, - runtime_library_dirs=runtime_library_dirs, - cython_directives = {'language_level': str(sys.version_info[0])},)) + runtime_library_dirs=runtime_library_dirs,)) setup( name = 'gudhi', @@ -49,7 +48,8 @@ setup( author_email='gudhi-contact@lists.gforge.inria.fr', version='@GUDHI_VERSION@', url='http://gudhi.gforge.inria.fr/', - ext_modules = cythonize(ext_modules), + ext_modules = cythonize(ext_modules, + language_level=str(sys.version_info[0])), install_requires = ['cython','numpy >= 1.9',], setup_requires = ['numpy >= 1.9',], ) -- cgit v1.2.3 From 3f5420aa5d5c9de1cd0cfe6ea1eb57a20a212c7c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 14:04:28 +0100 Subject: Rollback language_level --- src/python/setup.py.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index c434f659..f993165c 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -39,7 +39,8 @@ for module in modules: libraries=libraries, library_dirs=library_dirs, include_dirs=include_dirs, - runtime_library_dirs=runtime_library_dirs,)) + runtime_library_dirs=runtime_library_dirs, + cython_directives = {'language_level': str(sys.version_info[0])},)) setup( name = 'gudhi', @@ -48,8 +49,7 @@ setup( author_email='gudhi-contact@lists.gforge.inria.fr', version='@GUDHI_VERSION@', url='http://gudhi.gforge.inria.fr/', - ext_modules = cythonize(ext_modules, - language_level=str(sys.version_info[0])), + ext_modules = cythonize(ext_modules), install_requires = ['cython','numpy >= 1.9',], setup_requires = ['numpy >= 1.9',], ) -- cgit v1.2.3 From 09a0757357f89ff91fdafb535a0b250b937ee88b Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 17:09:17 +0100 Subject: 3.1.1 release candidate 1 --- CMakeGUDHIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index ed19ecfb..ec9794ce 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,6 +1,6 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 1) -set (GUDHI_PATCH_VERSION 0) +set (GUDHI_PATCH_VERSION 1.rc1) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") -- cgit v1.2.3 From 57eabeaa00f724fe60e1ee69b5db3c35a765e198 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Thu, 6 Feb 2020 17:16:08 +0100 Subject: Release note for version 3.1.1 --- next_release.md | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/next_release.md b/next_release.md index 26d4fca5..deb04085 100644 --- a/next_release.md +++ b/next_release.md @@ -1,20 +1,6 @@ -We are pleased to announce the release 3.X.X of the GUDHI library. - -As a major new feature, the GUDHI library now offers ... - -We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz). - -Below is a list of changes made since Gudhi 3.1.0: - -- [Module](link) - - ... - -- [Module](link) - - ... - -- Miscellaneous - - See the list of [bug fixes](https://github.com/GUDHI/gudhi-devel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A3.X.X+). +gudhi-3.1.1 is a bug-fix release. In particular, it fixes the installation of the Python representation module. +The [list of bugs that were solved since gudhi-3.1.0](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.1.1+is%3Aclosed) is available on GitHub. All modules are distributed under the terms of the MIT license. However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details. @@ -25,4 +11,4 @@ We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) fo Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. -For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.0.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.0.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.1.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.1.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). -- cgit v1.2.3 From 00c46d21df80c51a0c83e412230f4583a5803fc9 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 6 Feb 2020 19:27:36 +0100 Subject: Print pybind11 version, protect test --- src/python/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index edb1ba02..090a7446 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -32,6 +32,10 @@ function( add_gudhi_debug_info DEBUG_INFO ) endfunction( add_gudhi_debug_info ) if(PYTHONINTERP_FOUND) + if(PYBIND11_FOUND) + add_gudhi_debug_info("Pybind11 version ${PYBIND11_VERSION}") + set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") + endif() if(CYTHON_FOUND) set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_reader', ") set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'simplex_tree', ") @@ -391,9 +395,9 @@ endif(CGAL_FOUND) add_gudhi_py_test(test_reader_utils) # Wasserstein - if(OT_FOUND) + if(OT_FOUND AND PYBIND11_FOUND) add_gudhi_py_test(test_wasserstein_distance) - endif(OT_FOUND) + endif() # Representations if(SKLEARN_FOUND AND MATPLOTLIB_FOUND) -- cgit v1.2.3 From 08b82e8a606a7fcd1219e7074cc2f15340090e59 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 6 Feb 2020 21:20:17 +0100 Subject: Make pybind11 mandatory and simplify The use of install_requires and setup_requires looks strange, I would expect cython in setup_requires, not install_requires. But setup_requires doesn't seem to work so well anyway. --- src/python/doc/installation.rst | 13 +++---------- src/python/setup.py.in | 19 +++---------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index f8456799..d459145b 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -14,10 +14,11 @@ Compiling ********* The library uses c++14 and requires `Boost `_ ≥ 1.56.0, `CMake `_ ≥ 3.1 to generate makefiles, -`NumPy `_ and `Cython `_ to compile +`NumPy `_, `Cython `_ and +`pybind11 `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual -Studio 2015. +Studio 2017. On `Windows `_ , only Python ≥ 3.5 are available because of the required Visual Studio version. @@ -257,14 +258,6 @@ The :doc:`Wasserstein distance ` module requires `POT `_, a library that provides several solvers for optimization problems related to Optimal Transport. -Pybind11 -======== - -The :doc:`Wasserstein distance ` module requires -`pybind11 `_, a library that provides -interoperability between C++ and Python, for its interface to `Hera -`_. - Scikit-learn ============ diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 851188bd..d05e4675 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -12,6 +12,7 @@ from setuptools import setup, Extension from Cython.Build import cythonize from numpy import get_include as numpy_get_include import sys +import pybind11 __author__ = "Vincent Rouvreau" __copyright__ = "Copyright (C) 2016 Inria" @@ -27,20 +28,6 @@ library_dirs=[@GUDHI_PYTHON_LIBRARY_DIRS@] include_dirs = [numpy_get_include(), '@CMAKE_CURRENT_SOURCE_DIR@/gudhi/', @GUDHI_PYTHON_INCLUDE_DIRS@] runtime_library_dirs=[@GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS@] -# Copied from https://github.com/pybind/python_example/blob/master/setup.py -class get_pybind_include(object): - """Helper class to determine the pybind11 include path - The purpose of this class is to postpone importing pybind11 - until it is actually installed, so that the ``get_include()`` - method can be invoked. """ - - def __init__(self, user=False): - self.user = user - - def __str__(self): - import pybind11 - return pybind11.get_include(self.user) - # Create ext_modules list from module list ext_modules = [] for module in modules: @@ -64,7 +51,7 @@ ext_modules.append(Extension( language = 'c++', include_dirs = include_dirs + ['@HERA_WASSERSTEIN_INCLUDE_DIR@', - get_pybind_include(False), get_pybind_include(True)], + pybind11.get_include(False), pybind11.get_include(True)], extra_compile_args=extra_compile_args + [@GUDHI_PYBIND11_EXTRA_COMPILE_ARGS@], )) @@ -76,6 +63,6 @@ setup( version='@GUDHI_VERSION@', url='http://gudhi.gforge.inria.fr/', ext_modules = ext_modules, - install_requires = ['cython','numpy >= 1.9','pybind11',], + install_requires = ['cython','numpy >= 1.9',], setup_requires = ['numpy >= 1.9','pybind11',], ) -- cgit v1.2.3 From 518c619d578dc6f168b6369417f15872e3cd0056 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 6 Feb 2020 21:54:44 +0100 Subject: use bibtex --- biblio/bibliography.bib | 12 ++++++++++++ src/python/doc/wasserstein_distance_user.rst | 10 +++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/biblio/bibliography.bib b/biblio/bibliography.bib index a1b951e0..3bbe7960 100644 --- a/biblio/bibliography.bib +++ b/biblio/bibliography.bib @@ -1180,3 +1180,15 @@ language={English} booktitle = {In Neural Information Processing Systems}, year = {2007} } +@inproceedings{10.5555/3327546.3327645, +author = {Lacombe, Th\'{e}o and Cuturi, Marco and Oudot, Steve}, +title = {Large Scale Computation of Means and Clusters for Persistence Diagrams Using Optimal Transport}, +year = {2018}, +publisher = {Curran Associates Inc.}, +address = {Red Hook, NY, USA}, +booktitle = {Proceedings of the 32nd International Conference on Neural Information Processing Systems}, +pages = {9792–9802}, +numpages = {11}, +location = {Montr\'{e}al, Canada}, +series = {NIPS’18} +} diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 648cc568..99445b99 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -13,15 +13,15 @@ Functions --------- This implementation uses the Python Optimal Transport library and is based on ideas from "Large Scale Computation of Means and Cluster for Persistence -Diagrams via Optimal Transport". +Diagrams via Optimal Transport" :cite:`10.5555/3327546.3327645`. .. autofunction:: gudhi.wasserstein.wasserstein_distance This other implementation comes from `Hera -`_ (BSD-3-Clause) and is -based on `"Geometry Helps to Compare Persistence Diagrams." -`_ by Michael Kerber, Dmitriy -Morozov, and Arnur Nigmetov, at ALENEX 2016. +`_ (BSD-3-Clause) which is +based on "Geometry Helps to Compare Persistence Diagrams" +:cite:`Kerber:2017:GHC:3047249.3064175` by Michael Kerber, Dmitriy +Morozov, and Arnur Nigmetov. .. autofunction:: gudhi.hera.wasserstein_distance -- cgit v1.2.3 From e8c908469cb4ac547d4fd46ad8daf5ee21739f58 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 6 Feb 2020 22:14:08 +0100 Subject: pytest.approx --- src/python/test/test_wasserstein_distance.py | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 46a7079f..6a14c50e 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -11,6 +11,7 @@ from gudhi.wasserstein import wasserstein_distance as pot from gudhi.hera import wasserstein_distance as hera import numpy as np +import pytest __author__ = "Theo Lacombe" __copyright__ = "Copyright (C) 2019 Inria" @@ -24,32 +25,31 @@ def _basic_wasserstein(wasserstein_distance, delta, test_infinity=True): emptydiag = np.array([]) # We just need to handle positive numbers here - def approx(a, b): - f = 1 + delta - return a <= b*f and b <= a*f + def approx(x): + return pytest.approx(x, rel=delta) assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=1.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=1.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=np.inf, order=2.) == 0. assert wasserstein_distance(emptydiag, emptydiag, internal_p=2., order=2.) == 0. - assert approx(wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.), 2.) - assert approx(wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.), 4.) + assert wasserstein_distance(diag3, emptydiag, internal_p=np.inf, order=1.) == approx(2.) + assert wasserstein_distance(diag3, emptydiag, internal_p=1., order=1.) == approx(4.) - assert approx(wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.), 5.) # thank you Pythagorician triplets - assert approx(wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.), 2.5) - assert approx(wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.), 3.5355339059327378) + assert wasserstein_distance(diag4, emptydiag, internal_p=1., order=2.) == approx(5.) # thank you Pythagorician triplets + assert wasserstein_distance(diag4, emptydiag, internal_p=np.inf, order=2.) == approx(2.5) + assert wasserstein_distance(diag4, emptydiag, internal_p=2., order=2.) == approx(3.5355339059327378) - assert approx(wasserstein_distance(diag1, diag2, internal_p=2., order=1.) , 1.4453593023967701) - assert approx(wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74), 0.9772734057168739) + assert wasserstein_distance(diag1, diag2, internal_p=2., order=1.) == approx(1.4453593023967701) + assert wasserstein_distance(diag1, diag2, internal_p=2.35, order=1.74) == approx(0.9772734057168739) - assert approx(wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863), 3.141592214572228) + assert wasserstein_distance(diag1, emptydiag, internal_p=2.35, order=1.7863) == approx(3.141592214572228) - assert approx(wasserstein_distance(diag3, diag4, internal_p=1., order=1.), 3.) - assert approx(wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.), 3.) # no diag matching here - assert approx(wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.), np.sqrt(5)) - assert approx(wasserstein_distance(diag3, diag4, internal_p=1., order=2.), np.sqrt(5)) - assert approx(wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.), np.sqrt(5)) + assert wasserstein_distance(diag3, diag4, internal_p=1., order=1.) == approx(3.) + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=1.) == approx(3.) # no diag matching here + assert wasserstein_distance(diag3, diag4, internal_p=np.inf, order=2.) == approx(np.sqrt(5)) + assert wasserstein_distance(diag3, diag4, internal_p=1., order=2.) == approx(np.sqrt(5)) + assert wasserstein_distance(diag3, diag4, internal_p=4.5, order=2.) == approx(np.sqrt(5)) if(not test_infinity): return @@ -58,7 +58,7 @@ def _basic_wasserstein(wasserstein_distance, delta, test_infinity=True): diag6 = np.array([[7, 8], [4, 6], [3, np.inf]]) assert wasserstein_distance(diag4, diag5) == np.inf - assert approx(wasserstein_distance(diag5, diag6, order=1, internal_p=np.inf), 4.) + assert wasserstein_distance(diag5, diag6, order=1, internal_p=np.inf) == approx(4.) def hera_wrap(delta): def fun(*kargs,**kwargs): -- cgit v1.2.3 From cbe3d0d2b16e19048928ae308851c4312cca42c8 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 7 Feb 2020 14:37:06 +0100 Subject: Release note and Version for 3.1.1 version --- CMakeGUDHIVersion.txt | 2 +- next_release.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeGUDHIVersion.txt b/CMakeGUDHIVersion.txt index ec9794ce..0f827b9e 100644 --- a/CMakeGUDHIVersion.txt +++ b/CMakeGUDHIVersion.txt @@ -1,6 +1,6 @@ set (GUDHI_MAJOR_VERSION 3) set (GUDHI_MINOR_VERSION 1) -set (GUDHI_PATCH_VERSION 1.rc1) +set (GUDHI_PATCH_VERSION 1) set(GUDHI_VERSION ${GUDHI_MAJOR_VERSION}.${GUDHI_MINOR_VERSION}.${GUDHI_PATCH_VERSION}) message(STATUS "GUDHI version : ${GUDHI_VERSION}") diff --git a/next_release.md b/next_release.md index deb04085..78270d15 100644 --- a/next_release.md +++ b/next_release.md @@ -11,4 +11,4 @@ We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) fo Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. -For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.1.rc1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.1.rc1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). -- cgit v1.2.3 From 5c037fb06250e93ad04bb45bdbceb937701e03fa Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Fri, 7 Feb 2020 16:32:33 +0100 Subject: Bad link for last version --- src/common/doc/header.html | 2 +- src/python/doc/_templates/layout.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/doc/header.html b/src/common/doc/header.html index 9fdb2321..99ab6bb7 100644 --- a/src/common/doc/header.html +++ b/src/common/doc/header.html @@ -56,7 +56,7 @@ $extrastylesheet Download diff --git a/src/python/doc/_templates/layout.html b/src/python/doc/_templates/layout.html index 2f2d9c72..a672a281 100644 --- a/src/python/doc/_templates/layout.html +++ b/src/python/doc/_templates/layout.html @@ -201,7 +201,7 @@ Download -- cgit v1.2.3 From 7be3cfef278917dc0c1905588ae88314273909d4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 7 Feb 2020 19:38:27 +0100 Subject: More uniform notations between the 2 wassersteins --- src/python/gudhi/wasserstein.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index db5ddff2..b1cfd588 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -27,8 +27,8 @@ def _build_dist_matrix(X, Y, order=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (points of the) first diagram. :param Y: (m x 2) numpy.array encoding the second diagram. - :param internal_p: Ground metric (i.e. norm l_p). :param order: exponent for the Wasserstein metric. + :param internal_p: Ground metric (i.e. norm L^p). :returns: (n+1) x (m+1) np.array encoding the cost matrix C. For 1 <= i <= n, 1 <= j <= m, C[i,j] encodes the distance between X[i] and Y[j], while C[i, m+1] (resp. C[n+1, j]) encodes the distance (to the p) between X[i] (resp Y[j]) and its orthogonal proj onto the diagonal. note also that C[n+1, m+1] = 0 (it costs nothing to move from the diagonal to the diagonal). @@ -54,8 +54,8 @@ def _build_dist_matrix(X, Y, order=2., internal_p=2.): def _perstot(X, order, internal_p): ''' :param X: (n x 2) numpy.array (points of a given diagram). - :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (Euclidean norm). :param order: exponent for Wasserstein. Default value is 2. + :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (Euclidean norm). :returns: float, the total persistence of the diagram (that is, its distance to the empty diagram). ''' Xdiag = _proj_on_diag(X) @@ -66,8 +66,8 @@ def wasserstein_distance(X, Y, order=2., internal_p=2.): ''' :param X: (n x 2) numpy.array encoding the (finite points of the) first diagram. Must not contain essential points (i.e. with infinite coordinate). :param Y: (m x 2) numpy.array encoding the second diagram. - :param internal_p: Ground metric on the (upper-half) plane (i.e. norm l_p in R^2); Default value is 2 (euclidean norm). :param order: exponent for Wasserstein; Default value is 2. + :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (euclidean norm). :returns: the Wasserstein distance of order q (1 <= q < infinity) between persistence diagrams with respect to the internal_p-norm as ground metric. :rtype: float ''' -- cgit v1.2.3 From 458ee3e95c752f09058d933349851c8a3a730cad Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 7 Feb 2020 19:41:38 +0100 Subject: Name argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Théo Lacombe --- src/python/test/test_wasserstein_distance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 6a14c50e..4bc7114e 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -66,7 +66,7 @@ def hera_wrap(delta): return fun def test_wasserstein_distance_pot(): - _basic_wasserstein(pot, 1e-15, False) + _basic_wasserstein(pot, 1e-15, test_infinity=False) def test_wasserstein_distance_hera(): _basic_wasserstein(hera_wrap(1e-12), 1e-12) -- cgit v1.2.3 From b75123eeda446e7f778d4939da67a78e4c8c6abc Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 8 Feb 2020 17:39:05 +0100 Subject: Euclidean with a capital E --- src/Bottleneck_distance/include/gudhi/Persistence_graph.h | 2 +- src/python/doc/wasserstein_distance_user.rst | 2 +- src/python/gudhi/wasserstein.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h index f791e37c..e1e3522e 100644 --- a/src/Bottleneck_distance/include/gudhi/Persistence_graph.h +++ b/src/Bottleneck_distance/include/gudhi/Persistence_graph.h @@ -25,7 +25,7 @@ namespace Gudhi { namespace persistence_diagram { -/** \internal \brief Structure representing an euclidean bipartite graph containing +/** \internal \brief Structure representing a Euclidean bipartite graph containing * the points from the two persistence diagrams (including the projections). * * \ingroup bottleneck_distance diff --git a/src/python/doc/wasserstein_distance_user.rst b/src/python/doc/wasserstein_distance_user.rst index 99445b99..94b454e2 100644 --- a/src/python/doc/wasserstein_distance_user.rst +++ b/src/python/doc/wasserstein_distance_user.rst @@ -28,7 +28,7 @@ Morozov, and Arnur Nigmetov. Basic example ------------- -This example computes the 1-Wasserstein distance from 2 persistence diagrams with euclidean ground metric. +This example computes the 1-Wasserstein distance from 2 persistence diagrams with Euclidean ground metric. Note that persistence diagrams must be submitted as (n x 2) numpy arrays and must not contain inf values. .. testcode:: diff --git a/src/python/gudhi/wasserstein.py b/src/python/gudhi/wasserstein.py index b1cfd588..13102094 100644 --- a/src/python/gudhi/wasserstein.py +++ b/src/python/gudhi/wasserstein.py @@ -67,7 +67,7 @@ def wasserstein_distance(X, Y, order=2., internal_p=2.): :param X: (n x 2) numpy.array encoding the (finite points of the) first diagram. Must not contain essential points (i.e. with infinite coordinate). :param Y: (m x 2) numpy.array encoding the second diagram. :param order: exponent for Wasserstein; Default value is 2. - :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (euclidean norm). + :param internal_p: Ground metric on the (upper-half) plane (i.e. norm L^p in R^2); Default value is 2 (Euclidean norm). :returns: the Wasserstein distance of order q (1 <= q < infinity) between persistence diagrams with respect to the internal_p-norm as ground metric. :rtype: float ''' -- cgit v1.2.3 From 486fc4b560c61e936e6aae83ce90994f318517df Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 8 Feb 2020 23:23:50 +0100 Subject: Add tensorflow to the circleci docker image Needed for perslay --- Dockerfile_for_circleci_image | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile_for_circleci_image b/Dockerfile_for_circleci_image index b7d0dcca..ebd2f366 100644 --- a/Dockerfile_for_circleci_image +++ b/Dockerfile_for_circleci_image @@ -58,7 +58,8 @@ RUN pip3 install \ scikit-learn \ sphinx \ sphinx-paramlinks \ - sphinxcontrib-bibtex + sphinxcontrib-bibtex \ + tensorflow # apt clean up RUN apt autoremove && rm -rf /var/lib/apt/lists/* -- cgit v1.2.3 From f2c85ed1fd87f9ca50b1ed80135b6eea21d08c33 Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 10 Feb 2020 11:05:40 +0100 Subject: Move next_release in for_dev directory. Add a for_dev/for_maintainer directory to explain how to create a GUDHI release --- CMakeLists.txt | 2 + code_conventions.md | 26 ------ for_dev/code_conventions.md | 26 ++++++ .../for_maintainers/new_gudhi_version_creation.md | 97 ++++++++++++++++++++++ for_dev/for_maintainers/next_release_template.md | 28 +++++++ for_dev/next_release.md | 28 +++++++ next_release.md | 14 ---- 7 files changed, 181 insertions(+), 40 deletions(-) delete mode 100644 code_conventions.md create mode 100644 for_dev/code_conventions.md create mode 100644 for_dev/for_maintainers/new_gudhi_version_creation.md create mode 100644 for_dev/for_maintainers/next_release_template.md create mode 100644 for_dev/next_release.md delete mode 100644 next_release.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dcc6803..d9244dc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,5 +65,7 @@ include(GUDHI_user_version_target) # For "make doxygen" - Requires GUDHI_USER_VERSION_DIR to be set - Done in GUDHI_user_version_target for dev version include(GUDHI_doxygen_target) +configure_file(${CMAKE_SOURCE_DIR}/for_dev/for_maintainers/new_gudhi_version_creation.md "${CMAKE_CURRENT_BINARY_DIR}/" @ONLY) + message("++ GUDHI_MODULES list is:\"${GUDHI_MODULES}\"") message("++ GUDHI_MISSING_MODULES list is:\"${GUDHI_MISSING_MODULES}\"") diff --git a/code_conventions.md b/code_conventions.md deleted file mode 100644 index 5882f78e..00000000 --- a/code_conventions.md +++ /dev/null @@ -1,26 +0,0 @@ -# Naming conventions - -## C++ - -### In the code: -* The classes and functions of a package should be in a sub-namespace of the `Gudhi` namespace. The sub-namespace names are in lowercase and use underscore separators. E.g. `Gudhi::package_name::` -* Concepts are named with camel case starting with uppercase. E.g. `PersistentHomology` for the concept of Persitence homology. -* Classes start with an uppercase letter and use underscore separators. E.g. `Skeleton_blocker_contractor`. -* Member functions and free functions are in lowercase and use underscore separators. E.g. `int num_vertices()`. -* Constants and macros are in uppercase. -* Macros should begin with the prefix `GUDHI_`. - -### File names: -* All headers are named *.h and all sources are named *.cpp. -* If a single class or function is provided in a file, its name (with the same letter case) should be used for the file name. -* If a file does not contain a single class, its name should not begin with a capital letter. -* Test files should be called `test_[what_is_tested].cpp`. E.g. `test_sparsify_point_set.cpp` -* Example files should be called `example_[what_it_is].cpp`. E.g. `example_sparsify_point_set.cpp` - -### In CMakeLists.txt files: -* The name of the "project" should be in this form: `Package_[tests|examples|…]`. E.g. `project(Simplex_tree_examples)`. -* The name if each "target" (first parameter of add_executable) should be in this form: `Package_{name of the cpp file without extension}`. E.g `add_executable(Subsampling_test_sparsify_point_set test_sparsify_point_set.cpp)`. - -## Python - -In progress... \ No newline at end of file diff --git a/for_dev/code_conventions.md b/for_dev/code_conventions.md new file mode 100644 index 00000000..5882f78e --- /dev/null +++ b/for_dev/code_conventions.md @@ -0,0 +1,26 @@ +# Naming conventions + +## C++ + +### In the code: +* The classes and functions of a package should be in a sub-namespace of the `Gudhi` namespace. The sub-namespace names are in lowercase and use underscore separators. E.g. `Gudhi::package_name::` +* Concepts are named with camel case starting with uppercase. E.g. `PersistentHomology` for the concept of Persitence homology. +* Classes start with an uppercase letter and use underscore separators. E.g. `Skeleton_blocker_contractor`. +* Member functions and free functions are in lowercase and use underscore separators. E.g. `int num_vertices()`. +* Constants and macros are in uppercase. +* Macros should begin with the prefix `GUDHI_`. + +### File names: +* All headers are named *.h and all sources are named *.cpp. +* If a single class or function is provided in a file, its name (with the same letter case) should be used for the file name. +* If a file does not contain a single class, its name should not begin with a capital letter. +* Test files should be called `test_[what_is_tested].cpp`. E.g. `test_sparsify_point_set.cpp` +* Example files should be called `example_[what_it_is].cpp`. E.g. `example_sparsify_point_set.cpp` + +### In CMakeLists.txt files: +* The name of the "project" should be in this form: `Package_[tests|examples|…]`. E.g. `project(Simplex_tree_examples)`. +* The name if each "target" (first parameter of add_executable) should be in this form: `Package_{name of the cpp file without extension}`. E.g `add_executable(Subsampling_test_sparsify_point_set test_sparsify_point_set.cpp)`. + +## Python + +In progress... \ No newline at end of file diff --git a/for_dev/for_maintainers/new_gudhi_version_creation.md b/for_dev/for_maintainers/new_gudhi_version_creation.md new file mode 100644 index 00000000..74d818f3 --- /dev/null +++ b/for_dev/for_maintainers/new_gudhi_version_creation.md @@ -0,0 +1,97 @@ +# Create a new GUDHI version + +We will consider that all operations will be performed in a brand new clone of the main project: +```bash +git clone https://github.com/GUDHI/gudhi-devel.git +cd gudhi-devel +``` + +## Version file modification + +**Edit the file CMakeGUDHIVersion.txt**, and increment major, minor, or patch version number, in function of the version new delivery. +```bash +# cf. .gitignore - ignore this if it is a fresh clone version +rm -rf data/points/COIL_database/lucky_cat.off_dist data/points/COIL_database/lucky_cat.off_sc.dot data/points/KleinBottle5D.off_dist data/points/KleinBottle5D.off_sc.dot data/points/human.off_dist data/points/human.off_sc.off data/points/human.off_sc.txt +``` + +Checkin the modifications, build and test the version: +```bash +mkdir build +cd build +cmake -DCGAL_DIR=/your/path/to/CGAL -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_BENCHMARK=ON -DUSER_VERSION_DIR=gudhi.@GUDHI_VERSION@ -DPython_ADDITIONAL_VERSIONS=3 .. +make user_version +date +"%d-%m-%Y-%T" > gudhi.@GUDHI_VERSION@/timestamp.txt +tar -czvf gudhi.@GUDHI_VERSION@.tar.gz gudhi.@GUDHI_VERSION@ +md5sum gudhi.@GUDHI_VERSION@.tar.gz > md5sum.txt +sha256sum gudhi.@GUDHI_VERSION@.tar.gz > sha256sum.txt +sha512sum gudhi.@GUDHI_VERSION@.tar.gz > sha512sum.txt + +make -j all test +``` + +***[Check there are no error]*** + +## Create the documentation +```bash +mkdir gudhi.doc.@GUDHI_VERSION@ +make doxygen 2>&1 | tee dox.log && grep warning dox.log +``` + +***[Check there are no error and the warnings]*** + +```bash +cp -R gudhi.@GUDHI_VERSION@/doc/html gudhi.doc.@GUDHI_VERSION@/cpp +cd gudhi.@GUDHI_VERSION@ +rm -rf build; mkdir build; cd build; cmake -DCGAL_DIR=/your/path/to/CGAL -DWITH_GUDHI_EXAMPLE=ON -DPython_ADDITIONAL_VERSIONS=3 .. +export LC_ALL=en_US.UTF-8 # cf. bug +make sphinx +``` + +***[Check there are no error]*** + +```bash +cp -R python/sphinx ../../gudhi.doc.@GUDHI_VERSION@/python +cd ../.. +tar -czvf gudhi.doc.@GUDHI_VERSION@.tar.gz gudhi.doc.@GUDHI_VERSION@ + +cd gudhi.@GUDHI_VERSION@/build +make all test +``` + +***[Check there are no error]*** + +## Upload the documentation + +Upload by ftp the content of the directory gudhi.doc.@GUDHI_VERSION@/cpp in a new directory on ForgeLogin@scm.gforge.inria.fr:/home/groups/gudhi/htdocs/doc/@GUDHI_VERSION@ + +Upload by ftp the content of the directory gudhi.doc.@GUDHI_VERSION@/python in a new directory on ForgeLogin@scm.gforge.inria.fr:/home/groups/gudhi/htdocs/python/@GUDHI_VERSION@ + +Through ssh, make the **latest** link to your new version of the documentation: +```bash +ssh ForgeLogin@scm.gforge.inria.fr +cd /home/groups/gudhi/htdocs/doc +rm latest +ln -s @GUDHI_VERSION@ latest +cd /home/groups/gudhi/htdocs/python +rm latest +ln -s @GUDHI_VERSION@ latest +``` + +## Put a version label on files + +* Go on page https://github.com/GUDHI/gudhi-devel/releases/new +* Name the tag: tags/gudhi-release-@GUDHI_VERSION@ +* Name the release GUDHI @GUDHI_VERSION@ +* Write the release note +* Drag'n drop *gudhi.@GUDHI_VERSION@.tar.gz*, *md5sum.txt*, *sha256sum.txt*, *sha512sum.txt* files +* Tick the *This is a pre-release* check button if this is a release candidate (untick if this is an official version) +* Click the *Publish the release* button + +***[Where X, Y and Z corresponds respectively to the major, minor, and patch version number]*** + + +===Mail sending=== +Send version mail to the following lists : +gudhi-devel@lists.gforge.inria.fr +gudhi-users@lists.gforge.inria.fr (not for release candidate) + diff --git a/for_dev/for_maintainers/next_release_template.md b/for_dev/for_maintainers/next_release_template.md new file mode 100644 index 00000000..a2805a55 --- /dev/null +++ b/for_dev/for_maintainers/next_release_template.md @@ -0,0 +1,28 @@ +We are pleased to announce the release 3.X.X of the GUDHI library. + +As a major new feature, the GUDHI library now offers ... + +We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz). + +Below is a list of changes made since GUDHI 3.X-1.X-1: + +- [Module](link) + - ... + +- [Module](link) + - ... + +- Miscellaneous + - The [list of bugs that were solved since GUDHI-3.X-1.X-1](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.1.1+is%3Aclosed) is available on GitHub. + +All modules are distributed under the terms of the MIT license. +However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details. + +We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. + +We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. + +Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. + +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/latest/installation.html) or [Python](https://gudhi.inria.fr/python/latest/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). + diff --git a/for_dev/next_release.md b/for_dev/next_release.md new file mode 100644 index 00000000..a2805a55 --- /dev/null +++ b/for_dev/next_release.md @@ -0,0 +1,28 @@ +We are pleased to announce the release 3.X.X of the GUDHI library. + +As a major new feature, the GUDHI library now offers ... + +We are now using GitHub to develop the GUDHI library, do not hesitate to [fork the GUDHI project on GitHub](https://github.com/GUDHI/gudhi-devel). From a user point of view, we recommend to download GUDHI user version (gudhi.3.X.X.tar.gz). + +Below is a list of changes made since GUDHI 3.X-1.X-1: + +- [Module](link) + - ... + +- [Module](link) + - ... + +- Miscellaneous + - The [list of bugs that were solved since GUDHI-3.X-1.X-1](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.1.1+is%3Aclosed) is available on GitHub. + +All modules are distributed under the terms of the MIT license. +However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details. + +We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. + +We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. + +Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. + +For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/latest/installation.html) or [Python](https://gudhi.inria.fr/python/latest/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). + diff --git a/next_release.md b/next_release.md deleted file mode 100644 index 78270d15..00000000 --- a/next_release.md +++ /dev/null @@ -1,14 +0,0 @@ -gudhi-3.1.1 is a bug-fix release. In particular, it fixes the installation of the Python representation module. - -The [list of bugs that were solved since gudhi-3.1.0](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.1.1+is%3Aclosed) is available on GitHub. - -All modules are distributed under the terms of the MIT license. -However, there are still GPL dependencies for many modules. We invite you to check our [license dedicated web page](https://gudhi.inria.fr/licensing/) for further details. - -We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. - -We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. - -Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. - -For further information about downloading and installing the library ([C++](https://gudhi.inria.fr/doc/3.1.1/installation.html) or [Python](https://gudhi.inria.fr/python/3.1.1/installation.html)), please visit the [GUDHI web site](https://gudhi.inria.fr/). -- cgit v1.2.3 From f7317664c051dd1f49861c2e22c3bf3ca471052c Mon Sep 17 00:00:00 2001 From: ROUVREAU Vincent Date: Mon, 10 Feb 2020 13:21:01 +0100 Subject: Gudhi version 3.1.1 --- Dockerfile_gudhi_installation | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile_gudhi_installation b/Dockerfile_gudhi_installation index d5d86338..33864d11 100644 --- a/Dockerfile_gudhi_installation +++ b/Dockerfile_gudhi_installation @@ -57,11 +57,11 @@ RUN pip3 install \ # apt clean up RUN apt autoremove && rm -rf /var/lib/apt/lists/* -RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.1.0/gudhi.3.1.0.tar.gz" \ -&& tar xf gudhi.3.1.0.tar.gz \ -&& cd gudhi.3.1.0 \ +RUN curl -LO "https://github.com/GUDHI/gudhi-devel/releases/download/tags%2Fgudhi-release-3.1.1/gudhi.3.1.1.tar.gz" \ +&& tar xf gudhi.3.1.1.tar.gz \ +&& cd gudhi.3.1.1 \ && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_PYTHON=OFF -DPython_ADDITIONAL_VERSIONS=3 .. \ && make all test install \ && cmake -DWITH_GUDHI_PYTHON=ON . \ && cd python \ -&& python3 setup.py install \ No newline at end of file +&& python3 setup.py install -- cgit v1.2.3 From a3b15cf6c7bcdcc815c3c9a4a1d6876a5b29873f Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Mon, 10 Feb 2020 14:14:47 +0100 Subject: Markdown was not correct --- for_dev/for_maintainers/new_gudhi_version_creation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/for_dev/for_maintainers/new_gudhi_version_creation.md b/for_dev/for_maintainers/new_gudhi_version_creation.md index 74d818f3..4a40f373 100644 --- a/for_dev/for_maintainers/new_gudhi_version_creation.md +++ b/for_dev/for_maintainers/new_gudhi_version_creation.md @@ -90,8 +90,8 @@ ln -s @GUDHI_VERSION@ latest ***[Where X, Y and Z corresponds respectively to the major, minor, and patch version number]*** -===Mail sending=== +## Mail sending Send version mail to the following lists : -gudhi-devel@lists.gforge.inria.fr -gudhi-users@lists.gforge.inria.fr (not for release candidate) +* gudhi-devel@lists.gforge.inria.fr +* gudhi-users@lists.gforge.inria.fr (not for release candidate) -- cgit v1.2.3 From ee0f12f1df406c81c6ad860c494eed908021fad9 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 8 Feb 2020 19:54:46 +0100 Subject: Use setuptools.find_packages --- src/python/setup.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/setup.py.in b/src/python/setup.py.in index f993165c..bd7fb180 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -8,7 +8,7 @@ - YYYY/MM Author: Description of the modification """ -from setuptools import setup, Extension +from setuptools import setup, Extension, find_packages from Cython.Build import cythonize from numpy import get_include as numpy_get_include import sys @@ -44,7 +44,7 @@ for module in modules: setup( name = 'gudhi', - packages=["gudhi","gudhi.representations"], + packages=find_packages(), # find_namespace_packages(include=["gudhi*"]) author='GUDHI Editorial Board', author_email='gudhi-contact@lists.gforge.inria.fr', version='@GUDHI_VERSION@', -- cgit v1.2.3 From d6f3165831d20bf3a91f1ff7e9734a574eaa567a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 11 Feb 2020 13:06:48 +0100 Subject: License and author --- src/python/gudhi/hera.cc | 13 +++++++++++-- src/python/test/test_wasserstein_distance.py | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/python/gudhi/hera.cc b/src/python/gudhi/hera.cc index 61f0da10..0d562b4c 100644 --- a/src/python/gudhi/hera.cc +++ b/src/python/gudhi/hera.cc @@ -1,9 +1,19 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Marc Glisse + * + * Copyright (C) 2020 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + #include #include #include -#include +#include // Hera #include @@ -41,7 +51,6 @@ double wasserstein_distance( PYBIND11_MODULE(hera, m) { m.def("wasserstein_distance", &wasserstein_distance, py::arg("X"), py::arg("Y"), - // Should we name those q, p and d instead? py::arg("order") = 1, py::arg("internal_p") = std::numeric_limits::infinity(), py::arg("delta") = .01, diff --git a/src/python/test/test_wasserstein_distance.py b/src/python/test/test_wasserstein_distance.py index 4bc7114e..6a6b217b 100755 --- a/src/python/test/test_wasserstein_distance.py +++ b/src/python/test/test_wasserstein_distance.py @@ -1,6 +1,6 @@ """ This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. - Author(s): Theo Lacombe + Author(s): Theo Lacombe, Marc Glisse Copyright (C) 2019 Inria -- cgit v1.2.3